diff -Nru libgnatcoll-18/CHANGES libgnatcoll-19/CHANGES --- libgnatcoll-18/CHANGES 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/CHANGES 2019-05-16 17:44:09.000000000 +0000 @@ -1 +1 @@ -{anod.anod: 6a0487d59525e9ed7a4fb16cfbc25c7290671150, gnatcoll-core: f0cc81c, gnatcoll-core.anod: 5ceebf7e3cf59d660450b6f6f95a0184595b6f83} +{anod.anod: df77c06d8887b3536f1f28cf5dbce113b2c49530, gnatcoll-core: 54cace4, gnatcoll-core.anod: fc7b20ba0ea5b3a4bfd39ca1fcf3edd84ddb046f} diff -Nru libgnatcoll-18/CONTRIBUTING.md libgnatcoll-19/CONTRIBUTING.md --- libgnatcoll-18/CONTRIBUTING.md 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/CONTRIBUTING.md 2018-06-13 07:43:28.000000000 +0000 @@ -0,0 +1,36 @@ +Contributing to GNATcoll +======================== + +Thank you for taking the time to contribute! + +If this is your first contribution, we invite you to read our [list of +guidelines](https://github.com/AdaCore/contributing-howto), common to all +AdaCore repositories. + +Below are specific guidelines to contribute to GNATcoll. + +Coding style +------------ + +Please follow [GNAT's coding style](https://gcc.gnu.org/onlinedocs/gnat-style/) +for Ada code, and [PEP8](https://www.python.org/dev/peps/pep-0008/) for Python +code. + +Commits +------- + +Organize your work into separated, atomic commits. A commit should +ideally contain the single smallest unit of change possible without breaking +anything. A change should include any tests that were added or modified for it. + +Testing +------- + +Every change you add to the code should be tested. If this is a bug fix, add +regression test(s). If it's a change of functionality, add functional test(s). +The available tests should provide 100% coverage of the lines added or modified +by the change; if this is not achievable, provide justification why some lines +can't be covered (such as defensive code, etc). + +Please refer to [GNATcoll testsuite documentation](testsuite/README.md) for +technical details. diff -Nru libgnatcoll-18/debian/changelog libgnatcoll-19/debian/changelog --- libgnatcoll-18/debian/changelog 2019-01-09 18:04:22.000000000 +0000 +++ libgnatcoll-19/debian/changelog 2020-02-25 14:28:56.000000000 +0000 @@ -1,3 +1,39 @@ +libgnatcoll (19-4) unstable; urgency=medium + + * Reupload to unstable for gnat-9 transition. + * Use debhelper 12 dh-sequenc syntax. + * Wrap and sort build dependencies. + * Standards-Version: 4.5.0. + + -- Nicolas Boulenguez Tue, 25 Feb 2020 15:28:56 +0100 + +libgnatcoll (19-3) experimental; urgency=medium + + * Use dh-sequence-* syntax for dh-ada-library. + This also ensures a dh-ada-library updated for libgnatprj. + * Remove redundant branch selection from Vcs-Git field. + * Override doc-main-package to silent a warning by dh_installdocs. + + -- Nicolas Boulenguez Mon, 30 Dec 2019 23:32:05 +0100 + +libgnatcoll (19-2) experimental; urgency=medium + + * Standards-Version 4.4.1. + * Rebuild against renamed libgpr-dev -> libgnatprj-dev. + + -- Nicolas Boulenguez Tue, 03 Dec 2019 19:43:04 +0100 + +libgnatcoll (19-1) experimental; urgency=medium + + * New upstream release, built with gnat-9 and updated dependencies. + Rename library and -dev package accordingly. + * Move VCS to git and salsa.debian.org. + * Standards-Version 4.4.0. + * Forward most patches. + * GCC-9 implicitly selects --as-needed linker option. + + -- Nicolas Boulenguez Tue, 03 Sep 2019 10:49:22 +0200 + libgnatcoll (18-4) unstable; urgency=medium * Debhelper 12. No need for d/compat anymore. diff -Nru libgnatcoll-18/debian/control libgnatcoll-19/debian/control --- libgnatcoll-18/debian/control 2019-01-09 18:04:22.000000000 +0000 +++ libgnatcoll-19/debian/control 2020-02-25 14:28:14.000000000 +0000 @@ -4,31 +4,30 @@ Maintainer: Nicolas Boulenguez Build-Depends: debhelper-compat (= 12), - gnat, gnat-8, + gnat, gnat-9, # This line is parsed to set gnat version. -# dh-ada-library allowing .ada extension. - dh-ada-library (>= 6.10), + dh-sequence-ada-library, # gprbuild building static libraries. gprbuild (>= 2018-3), - libgpr2-dev (>= 2017-5), + libgnatprj7-dev, # Implicit libc6-dev provides: iconv, syslog. Build-Depends-Indep: - python3-sphinx, + dh-sequence-sphinxdoc, +# Sphinx >= 1.6 uses the latexmk driver: latexmk, -# Sphinx >= 1.6 uses the latexmk driver. + python3-sphinx, + sphinx-common, texlive-fonts-recommended, + texlive-latex-extra, # sphinx-doc requires iftex.sty: texlive-plain-generic, - texlive-latex-extra -# dh_sphinxdoc - ,sphinx-common Homepage: https://www.adacore.com/community -Standards-Version: 4.3.0 +Standards-Version: 4.5.0 Rules-Requires-Root: no -Vcs-Browser: http://www.ada-france.org:8081/branch/changes/org.debian.libgnatcoll -Vcs-Mtn: mtn://www.ada-france.org?org.debian.libgnatcoll +Vcs-Browser: https://salsa.debian.org/debian/libgnatcoll +Vcs-Git: https://salsa.debian.org/debian/libgnatcoll.git -Package: libgnatcoll17-dev +Package: libgnatcoll18-dev # Such lines are parsed to set Ada Library Information versions. Section: libdevel Architecture: any @@ -59,7 +58,7 @@ . This package contains the documentation in text, PDF and HTML. -Package: libgnatcoll17 +Package: libgnatcoll18 # Such lines are parsed to set Shared Object versions. Section: libs Architecture: any diff -Nru libgnatcoll-18/debian/copyright libgnatcoll-19/debian/copyright --- libgnatcoll-18/debian/copyright 2019-01-09 18:04:22.000000000 +0000 +++ libgnatcoll-19/debian/copyright 2019-09-02 21:40:23.000000000 +0000 @@ -3,7 +3,6 @@ Source: https://www.adacore.com/community Files-Excluded: docs/_build* distrib/gnatcoll/runtime.py - testsuite/support/test_assert.ads.orig Comment: Upstream likes to provide prebuilt documentation for the end user, but this includes minified javascript. @@ -11,7 +10,7 @@ dividing the archive size by 4. Files: * -Copyright: 2001-2018 AdaCore +Copyright: 2001-2019 AdaCore License: GPL-3+ Files: src/getRSS.c diff -Nru libgnatcoll-18/debian/patches/compilation_options.diff libgnatcoll-19/debian/patches/compilation_options.diff --- libgnatcoll-18/debian/patches/compilation_options.diff 2019-01-09 17:56:39.000000000 +0000 +++ libgnatcoll-19/debian/patches/compilation_options.diff 2019-09-02 23:03:57.000000000 +0000 @@ -1,10 +1,10 @@ Description: handle ADAFLAGS CFLAGS CPPFLAGS +Forwarded: https://github.com/AdaCore/gnatcoll-core/pull/39 Author: Nicolas Boulenguez -Forwarded: no --- a/gnatcoll.gpr +++ b/gnatcoll.gpr -@@ -95,6 +95,10 @@ +@@ -85,6 +85,10 @@ case Library_Type is when "relocatable" => for Library_Options use Extra_Libs; @@ -15,7 +15,7 @@ when others => null; end case; -@@ -116,6 +120,13 @@ +@@ -106,6 +110,13 @@ for Switches ("gnatcoll_support.c") use Compiler'Switches ("C") & Extra_Switches; diff -Nru libgnatcoll-18/debian/patches/gpr-renamed-to-gnatprj.diff libgnatcoll-19/debian/patches/gpr-renamed-to-gnatprj.diff --- libgnatcoll-18/debian/patches/gpr-renamed-to-gnatprj.diff 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/debian/patches/gpr-renamed-to-gnatprj.diff 2019-12-03 19:15:18.000000000 +0000 @@ -0,0 +1,16 @@ +Description: libgpr is called libgnatprj in Debian. + because of a conflict with the grpc source package. +Forwarded: not-needed +Author: Nicolas Boulenguez + +--- a/gnatcoll.gpr ++++ b/gnatcoll.gpr +@@ -21,7 +21,7 @@ + -- -- + ------------------------------------------------------------------------------ + +-with "gpr"; ++with "gnatprj"; + + project GnatColl is + diff -Nru libgnatcoll-18/debian/patches/link-with-libdl.diff libgnatcoll-19/debian/patches/link-with-libdl.diff --- libgnatcoll-18/debian/patches/link-with-libdl.diff 2019-01-09 17:56:39.000000000 +0000 +++ libgnatcoll-19/debian/patches/link-with-libdl.diff 2019-09-02 22:51:06.000000000 +0000 @@ -1,9 +1,14 @@ Description: Link with libdl on unix OS. + This has been introduced after a failure introduced by GPL-2018. + . + With --as-needed active by default on Debian, + there is no counter part to this trivial work-around. +Forwarded: no Author: Nicolas Boulenguez --- a/gnatcoll.gpr +++ b/gnatcoll.gpr -@@ -71,6 +71,7 @@ +@@ -68,6 +68,7 @@ when others => null; end case; diff -Nru libgnatcoll-18/debian/patches/python3-sphinx.diff libgnatcoll-19/debian/patches/python3-sphinx.diff --- libgnatcoll-18/debian/patches/python3-sphinx.diff 2019-01-09 17:56:39.000000000 +0000 +++ libgnatcoll-19/debian/patches/python3-sphinx.diff 2019-09-02 23:03:48.000000000 +0000 @@ -1,6 +1,7 @@ Description: replace obsolete file() constructor with a context manager. Replace file(), specific to python2, with a context manager that also closes the file after use. +Forwarded: https://github.com/AdaCore/gnatcoll-core/pull/38 Author: Nicolas Boulenguez --- a/docs/conf.py diff -Nru libgnatcoll-18/debian/patches/series libgnatcoll-19/debian/patches/series --- libgnatcoll-18/debian/patches/series 2019-01-09 17:59:42.000000000 +0000 +++ libgnatcoll-19/debian/patches/series 2019-12-03 19:15:18.000000000 +0000 @@ -5,3 +5,4 @@ link-with-libdl.diff doc_path.diff sphinx-no-math.diff +gpr-renamed-to-gnatprj.diff diff -Nru libgnatcoll-18/debian/patches/spelling.diff libgnatcoll-19/debian/patches/spelling.diff --- libgnatcoll-18/debian/patches/spelling.diff 2019-01-09 17:56:39.000000000 +0000 +++ libgnatcoll-19/debian/patches/spelling.diff 2019-09-03 09:10:43.000000000 +0000 @@ -1,6 +1,7 @@ Description: spelling + The second fix is already applied upstream. +Forwarded: https://github.com/AdaCore/gnatcoll-core/pull/36 Author: Nicolas Boulenguez -Forwarded: no --- a/src/gnatcoll-pools.adb +++ b/src/gnatcoll-pools.adb @@ -13,3 +14,14 @@ end if; end loop; +--- a/src/gnatcoll-projects.adb ++++ b/src/gnatcoll-projects.adb +@@ -5317,7 +5317,7 @@ + Values_Identical : Boolean := True; + begin + if Old_Values.all'Length /= New_Values.all'Length then +- Trace (Me_SV, "different ammount of values"); ++ Trace (Me_SV, "different amount of values"); + Values_Identical := False; + else + Sort_Values (Old_Values.all); diff -Nru libgnatcoll-18/debian/patches/sphinx-no-math.diff libgnatcoll-19/debian/patches/sphinx-no-math.diff --- libgnatcoll-18/debian/patches/sphinx-no-math.diff 2019-01-09 18:04:22.000000000 +0000 +++ libgnatcoll-19/debian/patches/sphinx-no-math.diff 2019-09-02 23:03:48.000000000 +0000 @@ -1,4 +1,5 @@ Description: remove unused and obsolete pngmath sphinx extension +Forwarded: https://github.com/AdaCore/gnatcoll-core/pull/40 Bug-Debian: https://bugs.debian.org/918816 Author: Dmitry Shachnev diff -Nru libgnatcoll-18/debian/README.source libgnatcoll-19/debian/README.source --- libgnatcoll-18/debian/README.source 2019-01-09 17:56:39.000000000 +0000 +++ libgnatcoll-19/debian/README.source 2019-09-02 21:40:23.000000000 +0000 @@ -21,42 +21,4 @@ Repackage it without generated files. # mk-origtargz --repack --compression=xz --version=YY ../PKG-gpl-YYYY-src.tar.gz -Use of the version control system ---------------------------------- - -You may either create an empty Monotone database -# mtn -d $db db init -or use an existing one. - -A branch tracks the unpatched repackaged upstream archives, another -adds the debian/ subdirectory. -# upstream_branch=com.adacore.libgnatcoll -# debian_branch=org.debian.libgnatcoll - -Download the two branches from the server to your database. The first -time you contact this server, monotone will show its key. You should -check that it matches f8a11727e8983cf9083c08c6a2acaa27e439dd39. -# server=www.ada-france.org -# mtn -d $db pull mtn://$server?$upstream_branch -# mtn -d $db pull mtn://$server?$debian_branch - -Create a workspace with the head of debian branch. -# mtn -d $db checkout -r h:$debian_branch libgnatcoll -# cd libgnatcoll - -Recreate the orig archive from a tag in upstream branch. -# mtn checkout -r t:libgnatcoll-1.6gpl2014 kilroy -# tar caf ../libgnatcoll_1.6gpl2014.orig.tar.xz kilroy --exclude=_MTN -# rm -fr kilroy - -Build the package -# debuild - -Beware that: -- mtn status does not list all changes. Try "mtn list missing", "mtn - list unknown", "mtn list ignored" and "mtn status" to get the - equivalent of "git status". -- Monotone will detect changes outside debian/ caused by patches. - Always "quilt pop -a" when preparing a commit. - - -- Nicolas Boulenguez , Sat, 23 Jun 2018 00:31:41 +0200 + -- Nicolas Boulenguez , Mon, 2 Sep 2019 23:13:05 +0200 diff -Nru libgnatcoll-18/debian/rules libgnatcoll-19/debian/rules --- libgnatcoll-18/debian/rules 2019-01-09 17:56:39.000000000 +0000 +++ libgnatcoll-19/debian/rules 2020-01-12 18:17:06.000000000 +0000 @@ -1,6 +1,6 @@ #!/usr/bin/make -f # Build script for GNATColl in Debian. -# Copyright (c) 2014-2018 Nicolas Boulenguez +# Copyright (c) 2014-2019 Nicolas Boulenguez # This build script is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -21,14 +21,14 @@ ' debian/control),$(eval $(line))) DEB_BUILD_MAINT_OPTIONS := hardening=+all -DEB_LDFLAGS_MAINT_APPEND := -Wl,--as-needed -Wl,--no-undefined \ +DEB_LDFLAGS_MAINT_APPEND := -Wl,--no-undefined \ -Wl,--no-copy-dt-needed-entries -Wl,--no-allow-shlib-undefined include /usr/share/dpkg/architecture.mk include /usr/share/dpkg/buildflags.mk include /usr/share/ada/debian_packaging-$(GNAT_VERSION).mk %: - dh $@ --with ada-library + dh $@ .PHONY: override_dh_auto_clean # We can do better than gprclean. @@ -58,9 +58,8 @@ # Ignore upstream install target. .PHONY: override_dh_auto_install -# Mimic 'dh --with sphinxdoc', but without adding sphinx-common to -# Build-Depends for arch-only builds. -.PHONY: override_dh_installdocs-indep -override_dh_installdocs-indep: - dh_installdocs -i - dh_sphinxdoc +# Avoid a warning about doc-main-package. +.PHONY: override_dh_installdocs +override_dh_installdocs: + dh_installdocs --package=libgnatcoll-doc --doc-main-package=libgnatcoll-doc + dh_installdocs --remaining-packages diff -Nru libgnatcoll-18/debian/tests/projects libgnatcoll-19/debian/tests/projects --- libgnatcoll-18/debian/tests/projects 2019-01-09 17:56:39.000000000 +0000 +++ libgnatcoll-19/debian/tests/projects 2019-12-03 19:15:15.000000000 +0000 @@ -1,7 +1,7 @@ #!/bin/sh set -C -e -f -u -cd "$ADTTMP" +cd "$AUTOPKGTEST_TMP" # From docs/projects.rst. # Checks that libgnatcoll-dev depends libgpr-dev. diff -Nru libgnatcoll-18/docs/building.rst libgnatcoll-19/docs/building.rst --- libgnatcoll-18/docs/building.rst 2018-03-05 13:06:24.000000000 +0000 +++ libgnatcoll-19/docs/building.rst 2018-07-19 04:20:17.000000000 +0000 @@ -57,9 +57,6 @@ *GNATCOLL_MADVISE* Whether MADVISE: yes (default) or no; this has no effect on Windows where MADVISE functionality is unavailable -*GNATCOLL_ATOMICS* - Selects atomics model: intrinsic (default) or mutex. - .. _Building_GNATColl: diff -Nru libgnatcoll-18/docs/index.rst libgnatcoll-19/docs/index.rst --- libgnatcoll-18/docs/index.rst 2018-03-05 13:06:24.000000000 +0000 +++ libgnatcoll-19/docs/index.rst 2018-06-13 07:43:29.000000000 +0000 @@ -26,7 +26,6 @@ config pools json - sql terminals promises diff -Nru libgnatcoll-18/docs/json.rst libgnatcoll-19/docs/json.rst --- libgnatcoll-18/docs/json.rst 2018-03-05 13:06:24.000000000 +0000 +++ libgnatcoll-19/docs/json.rst 2018-10-20 04:31:46.000000000 +0000 @@ -5,53 +5,110 @@ .. index:: json .. highlight:: ada -JSON is a format often used on the web to communicate between -a server and a browser, or between servers. It plays a similar -role to XML, but is much lighter in terms of size. On the -other hand, it doesn't provide advanced features like validation -which XML provides. - -The package **GNATCOLL.JSON** provides an Ada for creating -JSON data, or parse such data that your application receives. - -Most JSON data will generally start with an object, on which -attributes can be set. The value for the attributes are also -JSON data. - -Here is an example of use:: - - pragma Ada_05; - with GNATCOLL.JSON; use GNATCOLL.JSON; - with Ada.Text_IO; use Ada.Text_IO; +`JSON `_ is a format often used on the web +to communicate between a server and a browser, or between servers. It plays a +similar role to XML, but it has a much lighter syntax. On the other hand, it +doesn't provide advanced features like validation, which XML provides. + +The ``GNATCOLL.JSON`` package provides an Ada API to decode JSON data from +strings and to encode that data back to strings. It also allows one to create +and modify JSON data. + +API overview +============ + +The entry point for this API is the ``JSON_Value`` data type. JSON values can +be any of: + +* a null value (``JSON_Null_Type``): all such JSON values are equivalent; +* a boolean value (``JSON_Boolean_Type``): either true or false; +* an integer value (``JSON_Int_Type``), they are encoded as an Ada + ``Long_Long_Integer``; +* a floating point value (``JSON_Float_Type``), they are encoded as an Ada + ``Long_Float``; +* an UTF-8 encoded string (``JSON_String_Type``); +* an array of JSON values (``JSON_Array_Type``); +* a JSON object (``JSON_Object_Type``), which is a sequence of fields. Each + field has a unique name and maps to a JSON value. Depending on the context, + this sequence can be processed as a mapping, because each field name is + unique, but iterating on fields is deterministic because it is a sequence + underneath. + +Parsing JSON is as easy as calling the ``Read`` function:: + + Data : JSON_Value := Read ("[1, ""foo"", {""foo"": null}]"); + +Encoding to JSON is not any more complex:: + + JSON_String : String := Write (Data); + +JSON trees (``JSON_Value``) are available for both inspection and +modification:: + + Float_Number : JSON_Value := Create (Float'(1.0)); + -- Mere float number + + Object : JSON_Value := Get (Get (Data), 3); + -- JSON object from Data: {"foo": null} + + Some_Array : JSON_Value := + Create (Float_Number & Object & Create (False)); + -- Synthetic JSON array: [1.0, {"foo": null}, False] + + -- Modify Data in place + Data.Append (Some_Array); + +Examples +======== + +Here is a complete program demonstrating the use of this API:: + + with Ada.Text_IO; use Ada.Text_IO; + with GNATCOLL.JSON; use GNATCOLL.JSON; procedure JSON_Test is - MyObj : JSON_Value := Create_Object; + -- Create a JSON value from scratch + My_Obj : JSON_Value := Create_Object; begin - MyObj.Set_Field ("field1", Create (1)); - MyObj.Set_Field ("name", "theName"); + My_Obj.Set_Field ("field1", Create (1)); + My_Obj.Set_Field ("name", "theName"); - -- Now print the value - Put_Line (MyObj.Write); + -- Now serialize it. The call below will display: + -- {"field1": 1, "name": "thename"} + Put_Line (My_Obj.Write); end JSON_Test; -This example used the Ada05 dot notation to call the primitive -operations, but would also work using the more traditional -prefix notation. - -It is also possible to create JSON arrays. These are not -tagged types, so the prefix notation has to be used. Here -is a further example that sets another field in the object -we had before:: - - declare - MyArr : JSON_Array := Empty_Array; - begin - Append (MyArr, Create (1)); - Append (MyArr, Create ("aString")); - - MyObj.Set_Field ("vals", MyArr); - end; - -GNATColl automatically takes care of memory management, and -all allocated memory is automatically freed when the object -is no longer needed. +The above uses the Ada 2005 "dot notation" to call primitive operations +(``.Set_Field``, ``.Write``), but naturally the more traditional "prefix +notation" is also available:: + + Set_Field (My_Obj, "field1", Create (1)); + +It is also possible to create JSON arrays. These are not tagged types, so the +prefix notation has to be used. Here is a further example that sets another +field in the object we had before (``My_Obj``):: + + declare + -- Create a JSON array + My_Arr : JSON_Array := Empty_Array; + begin + -- Fill it + Append (My_Arr, Create (1)); + Append (My_Arr, Create ("aString")); + + -- Create a field in My_Obj to hold this array + My_Obj.Set_Field ("vals", My_Arr); + + -- This will now display: + -- {"field1": 1, "name": "thename", "vals": [1, "aString"]} + Put_Line (My_Obj.Write); + end; + +Similarly to containers from the standard Ada library (from +``Ada.Containers``), ``GNATCOLL.JSON`` features automatic memory management. +This means that there is no need for explicit destructors. + +The above is all that is needed for most uses of ``GNATCOLL.JSON``. To know +more about its API, please refer to the `gnatcoll-json.ads +`_ +source file. diff -Nru libgnatcoll-18/docs/projects.rst libgnatcoll-19/docs/projects.rst --- libgnatcoll-18/docs/projects.rst 2018-04-20 07:45:39.000000000 +0000 +++ libgnatcoll-19/docs/projects.rst 2018-10-20 04:31:46.000000000 +0000 @@ -6,95 +6,137 @@ .. highlight:: ada -The package `GNATCOLL.Projects` provides an extensive interface to -parse, manipulate and edit project files (:file:`.gpr` files). +The package `GNATCOLL.Projects` provides an extensive interface to parse, +manipulate and edit project files (:file:`.gpr` files). -Although the interface is best used using the Ada05 notation, it is fully -compatible with Ada95. +Although the interface is best used using the Ada 2012 notation, it is fully +compatible with Ada 95. -Here is a quick example on how to use the interface, although the spec -file itself contains much more detailed information on all the subprograms -related to the manipulation of project files:: - - pragma Ada_05; - with GNATCOLL.Projects; use GNATCOLL.Projects; - with GNATCOLL.VFS; use GNATCOLL.VFS; - - procedure Test_Project is - Tree : Project_Tree; - Files : File_Array_Access; - begin - Tree.Load (GNATCOLL.VFS.Create (+"path_to_project.gpr")); - - -- List the source files for project and all imported projects - - Files := Tree.Root_Project.Source_Files (Recursive => True); - for F in Files'Range loop - Put_Line ("File is: " & Files (F).Display_Full_Name); - end loop; +Here is a quick example on how to use the interface, although the spec file +itself contains much more detailed information on all the subprograms related +to the manipulation of project files: - Tree.Unload; - end Test_Project; +.. code-block:: ada -Defining a project with user-defined packages and reading them. -================================================================= + with GNATCOLL.Projects; use GNATCOLL.Projects; + with GNATCOLL.VFS; use GNATCOLL.VFS; + + procedure Test_Project is + Tree : Project_Tree; + Files : File_Array_Access; + begin + Tree.Load (GNATCOLL.VFS.Create (+"path_to_project.gpr")); + + -- List the source files for project and all imported projects + + Files := Tree.Root_Project.Source_Files (Recursive => True); + for F in Files'Range loop + Put_Line ("File is: " & Files (F).Display_Full_Name); + end loop; + + Tree.Unload; + end Test_Project; + +Defining a project with user-defined packages and reading them +============================================================== .. highlight:: ada If you want to use `GNATCOLL.Projects` with a GPR file that contains specific packages and attributes, you must procede in several steps. The following -example will show you how to do it:: +example will show you how to do it: - pragma Ada_05; - with GNATCOLL.Projects; use GNATCOLL.Projects; - with GNATCOLL.VFS; use GNATCOLL.VFS; - - procedure Test_Project is - Tree : Project_Tree; - Virtual_File : VFS; -- We assume it points to a valid file. - begin - -- 1 - Register_New_Attribute ("String", "Package_Name"); - Register_New_Attribute ("List", "Package_Name", Is_List => True); - Register_New_Attribute ("Index", "Package_Name", Is_Index => True); - - -- 2 - Tree.Load (Root_Project_Path => VFS, - Packages_To_Check => All_Packs); - - declare -- 3 - String_Attribute := constant Attribute_Pkg_String := - Build ("string", "package_name") - - Index_Attribute := constant Attribute_Pkg_List := - Build ("index", "package_name") - - List_Attribute := constant Attribute_Pkg_List := - Build ("list", "package_name") - begin -- 4 - for Val in Tree.Root_Project.Attribute_Value (List_Attribute).all loop - Put_Line ("Value:" & Val.all); - end loop; - - declare - Indexed_Value : constant String := Tree.Root_Project. - Attribute_Value (Index_Attribute, Index => "Index").all - begin - Put_Line ("Indexed_Value:" & Indexed_Value); - end; - end; - end Test_Project; +.. code-block:: ada + + with Ada.Text_IO; use Ada.Text_IO; + + with GNAT.Strings; + + with GNATCOLL.Projects; use GNATCOLL.Projects; + with GNATCOLL.VFS; use GNATCOLL.VFS; + + procedure Test_Project is + Tree : Project_Tree; + Project_File : constant Virtual_File := + GNATCOLL.VFS.Create (+"path_to_project.gpr"); + begin + -- 1 + if Register_New_Attribute + ("String", "Package_Name") /= "" + or else Register_New_Attribute + ("List", "Package_Name", Is_List => True) /= "" + or else Register_New_Attribute + ("Indexed", "Package_Name", Indexed => True) /= "" + then + raise Program_Error; + end if; + + -- 2 + Tree.Load (Root_Project_Path => Project_File, + Packages_To_Check => All_Packs); + + declare + Root : constant Project_Type := Tree.Root_Project; + + -- 3 + String_Attribute : constant Attribute_Pkg_String := + Build ("Package_Name", "String"); + String_Value : constant String := + Root.Attribute_Value (String_Attribute); + + Indexed_Attribute : constant Attribute_Pkg_String := + Build ("Package_Name", "Indexed"); + Indexed_Value : constant String := + Root.Attribute_Value + (Indexed_Attribute, Index => "Index"); + + List_Attribute : constant Attribute_Pkg_List := + Build ("Package_Name", "List"); + List_Value : constant GNAT.Strings.String_List_Access := + Root.Attribute_Value (List_Attribute); + begin + -- 4 + Put_Line ("Package_Name.String: " & String_Value); + Put_Line ("Package_Name.Indexed (""Index""): " + & Indexed_Value); + Put_Line ("Package_Name.List:"); + for Val of List_Value.all loop + Put_Line (" Value: " & Val.all); + end loop; + end; + end Test_Project; + +And the corresponding project file: + +.. code-block:: ada + + project Path_To_Project is + package Package_Name is + for String use "some string" + for Indexed ("Index") use "other string"; + for List use ("first item", "second item"); + end Package_Name; + end Path_To_Project; Step 1: We register all the attributes that we want for a given package. If the package does not already exists it is created. -Step 2: We load the project into the projects hierarchy. We tell Tree.Load to - check all packages otherwise it will not load any packages. +Step 2: We load the project into the projects hierarchy. We tell ``Tree.Load`` + to check all packages otherwise it will not load any packages. -Step 3: We read the Attributes from the project. An attribute can be an - Attribute_Pkg_String (representing a plain string) or an - Attribute_Pkg_List (representing a list or an index). +Step 3: We read attributes from the project. An attribute can be an + ``Attribute_Pkg_String`` (representing a plain string) or an + ``Attribute_Pkg_List`` (representing a list of strings). Step 4: We can do something with those values. Here we print the plain string - and the content of the list, aswell as an indexed value from the index. + and the content of the list. + +This program should output: + +.. code-block:: text + Package_Name.String: some string + Package_Name.Indexed ("Index"): hello world + Package_Name.List: + Value: hello + Value: world diff -Nru libgnatcoll-18/docs/sql.rst libgnatcoll-19/docs/sql.rst --- libgnatcoll-18/docs/sql.rst 2018-03-05 13:06:24.000000000 +0000 +++ libgnatcoll-19/docs/sql.rst 1970-01-01 00:00:00.000000000 +0000 @@ -1,1872 +0,0 @@ -*************************** -**SQL**: Database interface -*************************** - -.. highlight:: ada - -A lot of applications need to provide **persistence** for their data -(or a part of it). This means the data needs to be somehow saved on the -disk, to be read and manipulated later, possibly after the application -has been terminated and restarted. Although Ada provides various solutions -for this (including the use of the streams as declared in the Ada Reference -Manual), the common technics is through the use of relational database -management systems (**RDBMS**. The term database is in fact overloaded in -this context, and has come to mean different things: - -* The software system that implements file and query management. - This is generally provided by a third-party. The common abbreviation for - these is **DBMS**. Queries are generally written in a language called - **SQL**. One of the issues is that each DBMS tends to make minor changes - to this language. Another issue is that the way to send these SQL - commands to the DBMS is vendor-specific. GNATColl tries to - abstract this communication through its own API. Optional components can - instantiate this framework to specific DBMS, for example - **PostgreSQL** and **sqlite**. Common API makes it relatively easy to change - between two systems. For instance, development could be done - using a local sqlite DBMS, and then deployed (after testing, of course!) - on a PostgreSQL system. - - The code in GNATColl is such that adding support for a new DBMS - should be relatively easy. - -* A place where an application stores its data. The term - **database** in this document refers to this meaning. In a relational - database, this place is organized into tables, each of which contains - a number of fields. A row in a table represents one object. The set of - tables and their fields is called the **schema** of the database. - -Traditionally, writing the SQL queries is done inline: special markers -are inserted into your code to delimit sections that contain SQL code (as -opposed to Ada code), and these are then preprocessed to generate actual -code. This isn't the approach chosen in GNATColl: there are -several drawbacks, in particular your code is no longer Ada and various -tools will choke on it. - -The other usual approach is to write the queries as strings, which are -passed, via a DBMS-specific API, to the DBMS server. This approach is -very fragile: - -* The string might not contain **well-formed** SQL. This will - unfortunately only be detected at run time when the DBMS complains. - -* This is not **type safe**. You might be comparing a text field - with an integer, for instance. In some cases, the DBMS will accept that - (sqlite for instance), but in some other cases it won't (PostgreSQL). The - result might then either raise an error, or return an empty list. - -* There is a risk of **SQL injection**. Assuming the string is - constructed dynamically (using Ada's `&` operator), it might be easy - for a user to pass a string that breaks the query, and even destroys - things in the database. - -* As discussed previously, the SQL code might not be **portable** - across DBMS. For instance, creating an automatically increment integer - primary key in a table is DBMS specific. - -* The string is fragile if the database **schema changes**. Finding - whether a schema change impacts any of the queries requires looking at - all the strings in your application. - -* **performance** might be an issue. Whenever you execute a query, - the DBMS will analyze it, decide how to execute it (for instance, whether - it should traverse all the rows of a table, or whether it can do a faster - lookup), and then retrieve the results. The analysis pass is typically - slow (relatively the overall execution time), and queries can in fact - be **prepared** on the server: they are then analyzed only once, and it - is possible to run them several times without paying the price of the - analysis every time. Such a query can also be **parameterized**, in that - some values can be deferred until the query is actually executed. - All the above is made easy and portable in GNATColl, instead of - requiring DBMS-specific techniques. - -* This might require **large amount of code** to setup the query, - bind the parameters, execute it, and traverse the list of results. - -GNATColl attempts to solve all these issues. It also -provides further performance improvements, for instance -by keeping connections to the DBMS open and reusing them when possible. -A paper was published at the Ada-Europe conference in 2008 which describes -the various steps we went through in the design of this library. - -.. _Database_abstraction_layers: - -Database Abstraction Layers -=========================== - -GNATColl organizes the API into several layers, each written on -top of the previous one and providing more abstraction. All layers are -compatible with each other and can be mixed inside a given application. - -* **low-level binding**. - - This API is DBMS-specific, and is basically a mapping of the C API provided - by the DBMS vendors into Ada. If you are porting C code, or working with an - existing application, as a way to start using GNATColl before moving - to higher levels of abstraction. - - The code is found in :file:`gnatcoll-sql-sqlite-gnade.ads` and - :file:`gnatcoll-sql-postgres-gnade.ads`. The *gnade* part in the file names - indicate that this code was initially inspired by the **GNADE** library - that used to be available on the internet. Part of the code might in fact - come from that library. - - Using this API requires writing the SQL queries as strings, with all the - disadvantages that were highlighted at the beginning of this chapter. - -* **GNATCOLL.SQL** and **GNATCOLL.SQL.Exec** - - The first of these packages makes it possible to write type-safe queries - strongly linked to the database schema (thus with a guarantee that the - query is up-to-date with regards to the schema). To accomplish this, it - also relies on code that is generated automatically from a description of - your database schema, using the tool `gnatcoll_db2ada`. To simplify - memory management, the queries are automatically referenced counted and - freed when they are no longer needed. - - The second of these packages provides communication with the DBMS. It - provides a vendor-neutral API. You can send your queries either as strings, - or preferably as written with `GNATCOLL.SQL`. It also provides a simple - way to prepare parameterized statements on the server for maximum efficiency, - as well as the reuse of existing DBMS connections. It provides a simple - API to retrieve and manipulate the results from a query. - -* **GNATCOLL.SQL.ORM** and **GNATCOLL.SQL.Sessions** - - This is an Object-Relational Mapping (ORM). - - The first of these packages makes it possible to manipulate a database - without writing SQL. Instead, you manipulate Ada objects (tagged types), - whose primitive operations might transparently execute SQL queries. This - API provides caching for maximum efficiency. It relies on code automatically - generated by `gnatcoll_db2ada` from the schema of your database. The - generated objects can then be extended in your own code if needed. - - The second package encapsulates DBMS connections into higher-level objects - which provide their own caching and work best with the ORM objects. A - session is automatically released to a pool when no longer needed and will - be reused later on. - - -The following sections will ignore the lower layer, and concentrate on the -other layers. They share a number of types and, again, are fully compatible -with each other. You could connect to the database, and then write some queries -using **GNATCOLL.SQL** and some using **GNATCOLL.SQL.ORM**. - -.. _Database_example: - -Database example -================ - -This section describes an example that will be extended throughout this -chapter. We will build an application that represents a library. Such -a library contains various media (books and DVDs for instance), and -customers. A customer can borrow multiple media at the same time, but a -media is either at a customer's, or still in the library. - -The GNATColl distribution includes an example directory which -contains all the code and data for this example. - -.. _Database_schema: - -Database schema -=============== - -As was mentioned earlier (:ref:`Database_abstraction_layers`), -GNATColl relies on automatic code generation to provide a type -safe interface to your database. This code is generated by an external -tool called `gnatcoll_db2ada` provided as an optional component. -In some cases, this tool requires an installation of python -(`www.python.org `_) on your machine, since part -of the code is written in that language. - -This tool is able to output various kind of information, and is fully -described in the corresponding component. However, the input -is always the same: this is the schema of your database, that is the list -of tables and fields that make up your database. There exist two ways to -provide that information: - -* From a running database - - If you pass the DBMS vendor (postgresql, sqlite,...) and the connection - parameters to `gnatcoll_db2ada`, it is able to query the schema on - its own. However, this should not be the preferred method: this is similar - to reverse engineering assembly code into the original high-level code, and - some semantic information will be missing. For instance, in SQL - we have to create tables just to represent the many-to-many relationships. - These extra tables are part of the implementation of the schema, but are - just noise when it comes to the semantics of the schema. For this reason, - it is better to use the second solution below: - -* From a textual description - - Using the `-dbmodel` switch to `gnatcoll_db2ada`, you can pass - a file that describes the schema. We do not use SQL as the syntax in this, - because as explained above this is too low-level. This text file also - provides additional capabilities that do not exist when reverse-engineering - an existing database, for instance the ability to use name to represent - reverse relationships for foreign keys (see below and the ORM). - - The most convenient editor for this file is Emacs, using the `org-mode` - which provides convenient key shortcuts for editing the contents of ASCII - tables. But any text editor will do, and you do not need to align the columns - in this file. - - All lines starting with a hash sign ('#') will be ignored. - - This file is a collection of ASCII tables, each of which relates to one table - or one SQL view in your database. The paragraphs start with a line - containing:: - - table ::= - '|' ('ABSTRACT')? ('TABLE'|'VIEW') ['(' supertable ')'] - '|' '|' - - "name" is the name of the table. The third pipe and third column are optional, - and should be used to specify the name for the element represented by a single - row. For instance, if the table is called "books", the third column could - contain "book". This is used when generating objects for use with - `GNATCOLL.SQL.ORM`. - - If the first line starts with the keyword `ABSTRACT`, then no instance - of that table actually exists in the database. This is used in the context - of table inheritance, so define shared fields only once among multiple tables. - - The keyword `TABLE` can be followed by the name of a table from which it - inherits the fields. Currently, that supertable must be abstract, and the - fields declared in that table are simply duplicated in the new table. - - Following the declaration of the table, the file then describe their fields, - each on a separate line. Each of these lines must start with a pipe - character ("|"), and contain a number of pipe-separated fields. The order of - the fields is always given by the following grammar:: - - fields ::= - '|' '|' - '|' ('PK'|''|'NULL'|'NOT NULL'|'INDEX'|'UNIQUE'|'NOCASE') - '|' [default] '|' [doc] '|' - - The type of the field is the SQL type ("INTEGER", "TEXT", "TIMESTAMP", "DATE", - "DOUBLE PRECISION", "MONEY", "BOOLEAN", "TIME", "CHARACTER(1)"). Any maximal - length can be specified for strings, not just 1 as in this example. - The tool will automatically convert these to - Ada when generating Ada code. A special type ("AUTOINCREMENT") is an integer - that is automatically incremented according to available ids in the table. - The exact type used will depend on the specific DBMS. - - The property 'NOCASE' indicates that comparison should be case insensitive - for this field. - - If the field is a foreign key (that is a value that must correspond to a row - in another table), you can use the special syntax for its type:: - - fk_type ::= 'FK' [ '(' ')' ] - - As you can see, the type of the field is not specified explicitly, but will - always be that of the foreign table's primary key. With this syntax, the - foreign table must have a single field for its primary key. GNATColl - does not force a specific order for the declaration of tables: if is valid to - have a foreign key to a table that hasn't been declared yet. There is however - a restriction if you use the model to create a sqlite database (through the - `-createdb` switch of `gnatcoll_db2ada`): in this case, a reference - to a table that hasn't been defined yet may not be not through a field marked - as NOT NULL. This is a limitation of the sqlite backend itself. The solution - in this case is to reorder the declaration of tables, or drop the NOT NULL - constraint. - - Another restriction is that a foreign key that is also a primary key must - reference a table that has already been defined. You need to reorder the - declaration of your tables to ensure this is the case. - - "reverse_name" is the optional name that will be generated in the Ada code for the - reverse relationship, in the context of `GNATCOLL.SQL.ORM`. - If the "reverse_name" is empty (the parenthesis are shown), no reverse - relationship is generated. If the parenthesis and the reverse_name are both - omitted, a default name is generated based on the name of the field. - - The third column in the fields definition indicates the constraints of the - type. Multiple keywords can be used if they are separated by commas. Thus, - "NOT NULL, INDEX" indicates a column that must be set by the user, and for - which an index is created to speed up look ups. - - * A primary key ("PK") - * The value must be defined ("NOT NULL") - * The value can be left undefined ("NULL") - * A unique constraint and index ("UNIQUE") - * An index should be created for that column ("INDEX") to speed up - the lookups. - - * The automatic index created for a Foreign Key should not be created - ("NOINDEX"). Every time a field references another table, GNATColl will by - default create an index for it, so that the ORM can more efficiently do a - reverse query (from the target table's row find all the rows in the current - table that reference that target row). This will in general provide more - efficiency, but in some cases you never intend to do the reverse query and - thus can spare the extra index. - - The fourth column gives the default value for the field, and is given in SQL - syntax. Strings must be quoted with single quotes. - - The fifth column contains documentation for the field (if any). This - documentation will be included in the generated code, so that IDEs can - provide useful tooltips when navigating your application's code. - - After all the fields have been defined, you can specify extract constraints - on the table. In particular, if you have a foreign key to a table that uses a - tuple as its primary key, you can define that foreign key on a new line, as:: - - FK ::= '|' "FK:" '|' '|' * - '|' * '|' - - For instance:: - - | TABLE | tableA | - | FK: | tableB | fieldA1, fieldA2 | fieldB1, fieldB2 | - - It is also possible to create multi-column indexes, as in the following - example. In this case, the third column contains the name of the index to - create. If left blank, a default name will be computed by GNATColl:: - - | TABLE | tableA | - | INDEX: | field1,field2,field3 | name | - - The same way the unique multi-column constraint and index can be created. - The name is optional. - - | TABLE | tableA | - | UNIQUE: | field1,field2,field3 | name | - - - Going back to the example we described earlier (:ref:`Database_example`), - let's describe the tables that are involved. - - The first table contains the customers. Here is its definition:: - - | TABLE | customers | customer || The customer for the library | - | id | AUTOINCREMENT | PK || Auto-generated id | - | first | TEXT | NOT NULL || Customers' first name | - | last | TEXT | NOT NULL, INDEX || Customers' last name | - - We highly recommend to set a primary key on all tables. - This is a field whose value is - unique in the table, and thus that can act as an identifier for a specific - row in the table (in this case for a specific customer). We recommand using - integers for these ids for efficiency reasons. It is possible that the - primary key will be made of several fields, in which case they should all - have the "PK" constraint in the third column. - - A table with no primary key is still usable. The difference is in the - code generated for the ORM (:ref:`The_Object_Relational_Mapping_layer`), - since the `Delete` operation for this table will raise a - `Program_Error` instead of doing the actual deletion (that's because there - is no guaranteed unique identifier for the element, so the ORM does not know - which one to delete -- we do not depend on having unique internal ids on the - table, like some DBMS have). Likewise, the elements extracted from such a - primary key-less table will not be cached locally in the session, and cannot - be updated (only new elements can be created in the table). - - As we mentioned, the library contains two types of media, books and DVDs. - Each of those has a title, an author. However, a book also has a number of - pages and a DVD has a region where it can be viewed. There are various ways - to represent this in a database. For illustration purposes, we will use - table inheritance here: we will declare one abstract table (media) which - contains the common fields, and two tables to represent the types of media. - - As we mentioned, a media can be borrowed by at most one customer, but a - customer can have multiple media at any point in time. This is called a - **one-to-many** relationship. In SQL, this is in general described through - the use of a foreign key that goes from the table on the "many" side. In - this example, we therefore have a foreign key from media to customers. We - also provide a name for the reverse relationship, which will become clearer - when we describe the ORM interface. - - Here are the declarations:: - - | ABSTRACT TABLE | media | media || The contents of the library | - | id | AUTOINCREMENT | PK || Auto-generated id | - | title | TEXT | || The title of the media | - | author | TEXT | || The author | - | published | DATE | || Publication date | - | borrowed_by | FK customers(items) | NULL || Who borrowed the media | - - | TABLE (media) | books | book | | The books in the library | - | pages | INTEGER | | 100 | | - - | TABLE (media) | dvds | dvd | | The dvds in the library | - | region | INTEGER | | 1 | | - - For this example, all this description is put in a file called - :file:`dbschema.txt`. - - -.. _Connecting_to_the_database: - -Connecting to the database -========================== - -This library abstracts the specifics of the various database engines -it supports. Ideally, code written for one database could be ported -almost transparently to another engine. This is not completely doable -in practice, since each system has its own SQL specifics, and unless -you are writing things very carefully, the interpretation of your queries -might be different from one system to the next. - -However, the Ada code should remain untouched if you change the engine. -Various engines are supported out of the box (PostgreSQL and Sqlite), -although new ones can be added by overriding the appropriate SQL type -(`Database_Connection`). When you compile GNATColl, the -build scripts will try and detect what systems are installed on your -machine, and only build support for those. It is possible, if no -database was installed on your machine at that time, that the database -interface API is available (and your application compiles), but no -connection can be done to database at run time. - -To connect to a DBMS, you need to specify the various connection parameters. -This is done via a `GNATCOLL.SQL.Exec.Database_Description` object. -The creation of this object depends on the specific DBMS you are connecting -to (and this is the only part of your code that needs to know about the -specific system). The packages `GNATCOLL.SQL.Postgres` and -`GNATCOLL.SQL.Sqlite` contain a `Setup` function, whose parameters -depend on the DBMS. They provide full documentation for their parameters. -Let's take a simple example from sqlite:: - - with GNATCOLL.SQL.Sqlite; -- or Postgres - declare - DB_Descr : GNATCOLL.SQL.Exec.Database_Description; - begin - DB_Descr := GNATCOLL.SQL.Sqlite.Setup ("dbname.db"); - end - - -At this point, no connection to the DBMS has been done, and no information -was exchanged. - -To communicate with the database, however, we need to create another -object, a **GNATCOLL.SQL.Exec.Database_Connection**. Your application can -create any number of these. Typically, one would create one such connection -per task in the application, although other strategies are possible (like -a pool of reusable connections, where a task might be using two connections and -another task none at any point in time). - -If you do not plan on using the ORM interface from **GNATCOLL.SQL.ORM**, -GNATColl provides a simple way to create a task-specific connection. -While in this task, the same connection will always be returned (thus you -do not have to pass it around in parameter, although the latter might be -more efficient):: - - declare - DB : GNATCOLL.SQL.Exec.Database_Connection; - begin - DB := GNATCOLL.SQL.Exec.Get_Task_Connection - (Description => DB_Descr); - end; - -If your application is not multi-tasking, or you wish to implement your -own strategy for a connection pool, you can also use the following code -(using Ada 2005 dotted notation when calling the primitive operation). This -code will always create a new connection, not reuse an existing one, as -opposed to the code above:: - - declare - DB : GNATCOLL.SQL.Exec.Database_Connection; - begin - DB := DB_Descr.Build_Connection; - end; - -A note on concurrency: if you implement your own pool, you might sometimes -end up with dead locks when using sqlite. If a task uses two or more -connections to sqlite, and you setup GNATCOLL to create SQL -transactions even for `SELECT` statements (see -`GNATCOLL.SQL.Sqlite.Always_Use_Transactions`), the following scenario -will result in a deadlock:: - - DB1 := ... new connection to sqlite - ... execute a SELECT through DB1. The latter then holds a shared - ... lock, preventing other connections from writing (but not from - ... reading). - DB2 := ... another connection in the same thread - ... execute an INSERT through DB2. This tries to get a lock, which - ... will fail while DB1 holds the shared lock. Since these are in - ... the same thread, this will deadlock. - -By default, GNATCOLL will not create SQL transactions for select statements -to avoid this case, which occurs frequently in code. - -If you wish to reuse an existing connection later on, you must reset it. This -terminates any on-going SQL transaction, and resets various internal fields -that describe the state of the connection:: - - Reset_Connection (DB); - -In all three cases, the resulting database connection needs to be freed when -you no longer needed (which might be when your program terminates if you are -using pools) to avoid memory leaks. Nothing critical will appear if you do -not close, though, because the transactions to the DBMS server are saved -every time you call `Commit` in any case. So the code would end with:: - - Free (DB); -- for all connections you have opened - Free (DB_Descr); - -At this point, there still hasn't been any connection to the DBMS. This will -be done the first time a query is executed. If for some reason the connection -to the DBMS server is lost, GNATColl will automatically attempt to -reconnect a number of times before it gives up. This might break if there -was an ongoing SQL transaction, but simplifies your code since you do not -have to handle reconnection when there was a network failure, for instance. - -As we saw before, the database interface can be used in multi-tasking -applications. In such a case, it is recommended that each thread has its -own connection to the database, since that is more efficient and you do -not have to handle locking. -However, this assumes that the database server itself is thread safe, -which most often is the case, but not for `sqlite` for instance. -In such a case, you can only connect one per application to the database, -and you will have to manage a queue of queries somehow. - -If you want to use **GNATCOLL.SQL.Sessions** along with the Object-Relational -Mapping API, you will need to initialize the connection pool with the -**Database_Description**, but the session will then take care automatically -of creating the **Database_Connection**. See later sections for more details. - -Loading initial data in the database -==================================== - -We have now created an empty database. To make the queries we will write -later more interesting, we are going to load initial data. - -There are various ways to do it: - -* Manually or with an external tool - - One can connect to the database with an external tool (a web interface - when the DBMS provides one for instance), or via a command line tool - (`psql` for PostgreSQL or `sqlite3` for Sqlite), and start - inserting data manually. This shows one of the nice aspects of using a - standard DBMS for your application: you can alter the database (for instance - to do minor fixes in the data) with a lot of external tools that were - developed specifically for that purpose and that provide a nice interface. - However, this is also tedious and error prone, and can't be repeat easily - every time we recreate the database (for instance before running automatic - tests). - -* Using `GNATCOLL.SQL.EXEC` - - As we will describe later, GNATColl contains all the required - machinery for altering the contents of the database and creating new - objects. Using `GNATCOLL.SQL.ORM` this can also be done at a high-level - and completely hide SQL. - -* Loading a data file - - A lot of frameworks call such a file that contains initial data a "fixture". - We will use this techniques as an example. At the Ada level, this is a simple - call to `GNATCOLL.SQL.Inspect.Load_Data`. The package contains a lot - more than just this subprogram (:ref:`The_gnatcoll_db2ada_tool`):: - - declare - File : GNATCOLL.VFS.Virtual_File := Create ("fixture.txt"); - DB : Database_Connection; -- created earlier - begin - GNATCOLL.SQL.Inspect.Load_Data (DB, File); - DB.Commit; - end; - - The format of this file is described just below. - -As we mentioned, GNATColl can load data from a file. The format -of this file is similar to the one that describes the database schema. It -is a set of ASCII tables, each of which describes the data that should go -in a table (it is valid to duplicate tables). Each block starts with two -lines: The first one has two mandatory columns, the first of which contains -the text "TABLE", and the second contains the name of the table you want to -fill. The second line should contain as many columns as there are fields you -want to set. Not all the fields of the table need to have a corresponding -column if you want to set their contents to NULL (provided, of course, -that your schema allows it). For instance, we could add data for our -library example as such:: - - | TABLE | customers | | - | id | first | last | - |-------+-----------+--------| - | 1 | John | Smith | - | 2 | Alain | Dupont | - - | TABLE | books | | | | - | title | author | pages | published | borrowed_by | - |------------+---------+-------+------------+-------------| - | Art of War | Sun Tzu | 90 | 01-01-2000 | 1 | - | Ada RM | WRG | 250 | 01-07-2005 | | - -A few comments on the above: the `id` for `books` is not specified, -although the column is the primary key and therefore cannot be NULL. In fact, -since the type of the `id` was set to AUTOINCREMENT, GNATColl will -automatically assign valid values. We did not use this approach for the -id of `customers`, because we need to know this id to set the -`borrowed_by` field in the `books` table. - -There is another approach to setting the `borrowed_by` field, which -is to give the value of another field of the `customers` table. This -of course only work if you know this value is unique, but that will often -be the case in your initial fixtures. Here is an example:: - - | TABLE | dvds | | | - | title | author | region | borrowed_by(&last) | - |--------------+-----------+--------+--------------------| - | The Birds | Hitchcock | 1 | &Smith | - | The Dictator | Chaplin | 3 | &Dupont | - - -Here, the title of the column indicates that any value in this column might -be a reference to the `customers.last` value. Values which start -with an ampersand ("&") will therefore be looked up in `customers.last`, -and the `id` of the corresponding customer will be inserted in the -`dvds` table. It would still be valid to use directly customer ids -instead of references, this is just an extra flexibility that the references -give you to make your fixtures more readable. - -However, if we are using such references we need to provide the database -schema to `Load_Data` so that it can write the proper queries. This -is done by using other services of the `GNATCOLL.SQL.Inspect` package. - -The code for our example would be:: - - Load_Data - (DB, Create ("fixture.txt"), - New_Schema_IO (Create ("dbschema.txt")).Read_Schema); - -.. _Writing_queries: - -Writing queries -=============== - -The second part of the database support in GNATColl is a set -of Ada subprograms which help write SQL queries. Traditional ways to -write such queries have been through embedded SQL (which requires a -preprocessing phase and complicates the editing of source files in -Ada-aware editors), or through simple strings that are passed as is -to the server. In the latter case, the compiler can not do any -verification on the string, and errors such a missing parenthesis or -misspelled table or field names will not be detected until the code -executes the query. - -GNATColl tries to make sure that code that compiles contains -syntactically correct SQL queries and only reference existing tables -and fields. This of course does not ensure that the query is -semantically correct, but helps detect trivial errors as early as -possible. - -Such queries are thus written via calls to Ada subprograms, as in the -following example:: - - with GNATCOLL.SQL; use GNATCOLL.SQL; - with Database; use Database; - declare - Q : SQL_Query; - begin - Q := SQL_Select - (Fields => Max (Ticket_Priorities.Priority) - & Ticket_Priorities.Category, - From => Ticket_Priorities, - Where => Ticket_Priorities.Name /= "low", - Group_By => Ticket_Priorities.Category); - end; - -The above example will return, for each type of priority (internal or -customer) the highest possible value. The interest of this query is -left to the user... - -This is very similar to an actual SQL query. Field and table names come -from the package that was automatically generated by the -`gnatcoll_db2ada` tool, and therefore we know that our query is -only referencing existing fields. The syntactic correctness is ensured by -standard Ada rules. The `SQL_Select` accepts several parameters -corresponding to the usual SQL attributes like `GROUP BY`, -`HAVING`, `ORDER BY` and `LIMIT`. - -The `From` parameter could be a list of tables if we need to join -them in some ways. Such a list is created with the overridden `"&"` -operator, just as for fields which you can see in the above example. -GNATColl also provides a `Left_Join` function to join two -tables when the second might have no matching field (see the SQL -documentation). - -Similar functions exist for `SQL_Insert`, `SQL_Update` and -`SQL_Delete`. Each of those is extensively documented in the -:file:`gnatcoll-sql.ads` file. - -It is worth noting that we do not have to write the query all at once. -In fact, we could build it depending on some other criteria. For -instance, imagine we have a procedure that does the query above, and -omits the priority specified as a parameter, or shows all priorities -if the empty string is passed. Such a procedure could be written as:: - - procedure List_Priorities (Omit : String := "") is - Q : SQL_Query; - C : SQL_Criteria := No_Criteria; - begin - if Omit /= "" then - C := Ticket_Priorities.Name /= Omit; - end if; - Q := SQL_Select - (Fields => ..., -- as before - Where => C); - end; - -With such a code, it becomes easier to create queries on the fly -than it would be with directly writing strings. - -The above call has not sent anything to the database yet, only created -a data structure in memory (more precisely a tree). In fact, we could -be somewhat lazy when writing the query and rely on auto-completion, -as in the following example:: - - Q := SQL_Select - (Fields => Max (Ticket_Priorities.Priority) - & Ticket_Priorities.Category, - Where => Ticket_Priorities.Name /= "low"); - - Auto_Complete (Q); - -This query is exactly the same as before. However, we did not have to -specify the list of tables (which GNATColl can compute on its -own by looking at all the fields referenced in the query), nor the list -of fields in the `GROUP BY` clause, which once again can be computed -automatically by looking at those fields that are not used in a SQL -aggregate function. This auto-completion helps the maintenance of those -queries. - -There is another case where GNATColl makes it somewhat easier -to write the queries, and that is to handle joins between tables. If your -schema was build with foreign keys, GNATColl can take advantage -of those. - -Going back to our library example, let's assume we want to find out all -the books that were borrowed by the user "Smith". We need to involve two -tables (`Books` and `Customers`), and provide a join between them -so that the DBMS knows how to associate the rows from one with the rows from -the other. Here is a first example for such a query:: - - Q := SQL_Select - (Fields => Books.Title & Books.Pages, - From => Books & Customers, - Where => Books.Borrowed_By = Customers.Id - and Customers.Last = "Smith"); - -In fact, we could also use auto-completion, and let GNATColl find -out the involved tables on its own. We thus write the simpler:: - - Q := SQL_Select - (Fields => Books.Title & Books.Pages, - Where => Books.Borrowed_By = Customers.Id - and Customers.Last = "Smith"); - -There is one more things we can do to simplify the query and make it more -solid if the schema of the database changes. For instance, when a table -has a primary key made up of several fields, we need to make sure we always -have an "=" statement in the WHERE clause for all these fields between the -two tables. In our example above, we could at some point modify the schema -so that the primary key for `customers` is multiple (this is unlikely -in this example of course). To avoid this potential problems and make the -query somewhat easier to read, we can take advantage of the `FK` -subprograms generated by `gnatcoll_db2ada`. Using the Ada05 dotted -notation for the call, we can thus write:: - - Q := SQL_Select - (Fields => Books.Title & Books.Pages, - Where => Books.FK (Customers) - and Customers.Last = "Smith"); - -Regarding memory management, there is no need for explicitly freeing -memory in the above code. GNATColl will automatically do this when -the query is no longer needed. - -Executing queries -================= - -Once we have our query in memory, we need to pass it on to the database -server itself, and retrieve the results. - -Executing is done through the `GNATCOLL.SQL.Exec` package, as in the -following example:: - - declare - R : Forward_Cursor; - begin - R.Fetch (Connection => DB, Query => Q); - end; - -This reuses the connection we have established previously (`DB`) -(although now we are indeed connecting to the DBMS for the first time) -and sends it the query. The result of that query is then stored in -`R`, to be used later. - -Some SQL commands execute code on the DBMS, but do not return a result. -In this case, you can use `Execute` instead of `Fetch`. This -is the case when you execute an `INSERT` or `UPDATE` statement -for instance. Using `Execute` avoids the need to declare the local -variable `R`. - -If for some reason the connection to the database is no longer valid -(a transient network problem for instance), GNATColl will -attempt to reconnect and re-execute your query transparently, so that -your application does not need to handle this case. - -We'll describe later (:ref:`Getting_results`) how to analyze the result -of the query. - -Some versions of `Fetch` have an extra parameter `Use_Cache`, -set to `False` by default. If this parameter is true, and the exact same -query has already been executed before, its result will be reused -without even contacting the database server. The cache is automatically -invalidated every hour in any case. This cache is mostly useful for -tables that act like enumeration types. In this -case, the contents of the table changes very rarely, and the cache can -provide important speedups, whether the server is local or distant. -However, we recommend that you do actual measurements to know whether -this is indeed beneficial for you. You can always invalidate the -current cache with a call to `Invalidate_Cache` to force the -query to be done on the database server. - -If your query produces an error (whether it is invalid, or any other -reason), a flag is toggled in the `Connection` parameter, which -you can query through the `Success` subprogram. As a result, -a possible continuation of the above code is:: - - if Success (DB) then - ... - else - ... -- an error occurred - end if - -GNATColl also tries to be helpful in the way it handles SQL -transactions. Such transactions are a way to execute your query in a -sandbox, i.e. without affecting the database itself until you decide to -`COMMIT` the query. Should you decide to abort it (or -`ROLLBACK` as they say for SQL), then it is just as if nothing -happened. As a result, it is in general recommended to do all your changes -to the database from within a transaction. If one of the queries fail -because of invalid parameters, you just rollback and report the error -to the user. The database is still left in a consistent state. As an -additional benefit, executing within a transaction is sometimes faster, -as is the case for PostgreSQL for instance. - -To help with this, GNATColl will automatically start a -transaction the first time you edit the database. It is then your -responsibility to either commit or rollback the transaction when you -are done modifying. A lot of database engines (among which PostgreSQL) -will not accept any further change to the database if one command in -the transaction has failed. To take advantage of this, GNATColl -will therefore not even send the command to the server if it is in a -failure state. - -Here is code sample that modifies the database:: - - Execute (DB, SQL_Insert (...)); - -- Executed in the same transaction - - Commit_Or_Rollback (DB); - -- Commit if both insertion succeeded, rollback otherwise - -- You can still check Success(DB) afterward if needed - -.. _Prepared_queries: - -Prepared queries -================ - -The previous section showed how to execute queries and statements. But -these were in fact relatively inefficient. - -With most DBMS servers, it is possible to compile the query once on the -server, and then reuse that prepared query to significantly speed up -later searches when you reuse that prepared statement. - -.. highlight:: sql - -It is of course pretty rare to run exactly the same query or statement -multiple times with the same values. For instance, the following query -would not give much benefit if it was prepared, since you are unlikely -to reuse it exactly as is later on:: - - SELECT * FROM data WHERE id=1 - -SQL (and GNATColl) provide a way to parameterize queries. Instead -of hard-coding the value `1` in the example above, you would in fact -use a special character (unfortunately specific to the DBMS you are -interfacing to) to indicate that the value will be provided when the -query is actually executed. For instance, `sqlite` would use:: - - SELECT * FROM data WHERE id=? - -.. highlight:: ada - -You can write such a query in a DBMS-agnostic way by using GNATColl. -Assuming you have automatically generated :file:`database.ads` by using -`gnatcoll_db2ada`, here is the corresponding Ada code:: - - with Database; use Database; - - Q : constant SQL_Query := - SQL_Select - (Fields => Data.Id & Data.Name - From => Data, - Where => Data.Id = Integer_Param (1)); - -GNATColl provides a number of functions (one per type of -field) to indicate that the value is currently unbound. `Integer_Param`, -`Text_Param`, `Boolean_Param`,... All take a single argument, -which is the index of the corresponding parameter. A query might need -several parameters, and each should have a different index. On the other -hand, the same parameter could be used in several places in the query. - -Although the query above could be executed as is by providing the values -for the parameters, it is more efficient, as we mentioned at the beginning, -to compile it on the server. In theory, this preparation is done within the -context of a database connection (thus cannot be done for a global variable, -where we do not have connections yet, and where the query might be executed -by any connection later on). - -GNATColl will let you indicate that the query should be prepared. -This basically sets up some internal data, but does not immediately compile -it on the server. The first time the query is executed in a given -connection, though, it will first be compiled. The result of this compilation -will be reused for that connection from then on. If you are using a -second connection, it will do its own compilation of the query. - -So in our example we would add the following global variable:: - - P : constant Prepared_Statement := - Prepare (Q, On_Server => True); - -Two comments about this code: - -* You do not have to use global variables. You can prepare the - statement locally in a subprogram. A `Prepared_Statement` is a - reference counted type, that will automatically free the memory on the - server when it goes out of scope. - -* Here, we prepared the statement on the server. If we had specified - `On_Server => False`, we would still have sped things up, since Q - would be converted to a string that can be sent to the DBMS, and from - then on reused that string (note that this conversion is specific to - each DBMS, since they don't always represent things the same way, in - particular parameters, as we have seen above). Thus every time you use - P you save the time of converting from the GNATColl tree - representation of the query to a string for the DBMS. - -Now that we have a prepared statement, we can simply execute it. -If the statement does not require parameters, the usual `Fetch` -and `Execute` subprograms have versions that work exactly the same -with prepared statements. They also accept a `Params` parameter that -contains the parameter to pass to the server. A number of `"+"` -operators are provided to create those parameters:: - - declare - F : Forward_Cursor; - begin - F.Fetch (DB, P, Params => (1 => +2)); - F.Fetch (DB, P, Params => (1 => +3)); - end; - -Note that for string parameters, the `"+"` operator takes an -access to a string. This is for efficiency, to avoid allocating memory -and copying the string, and is safe because the parameters are only needed -while `Fetch` executes (even for a `Forward_Cursor`. - -Back to our library example. We showed earlier how to write a query that -retrieves the books borrowed by customer "Smith". We will now make this -query more general: given a customer name, return all the books he has -borrowed. Since we expect to use this often, we will prepare it on the -server (in real life, this query is of little interest since the customer -name is not unique, we would instead use a query that takes the id of the -customer). In general we would create a global variable with:: - - Borrowed : constant Prepared_Statement := Prepare - (SQL_Select - (Fields => Books.Title & Books.Pages, - Where => Books.FK (Customers) - and Customers.Last = Text_Param (1)); - Auto_Complete => True, - On_Server => True); - -Then when we need to execute this query, we would do:: - - declare - Name : aliased String := "Smith"; - begin - R.Fetch (DB, Borrowed, Params => (1 => +Smith'Access)); - end; - -There is one last property on `Prepared_Statement`s: when you -prepare them, you can pass a `Use_Cache => True` parameter. When this -is used, the result of the query will be cached by GNATColl, and -reuse when the query is executed again later. This is the fastest way -to get the query, but should be used with care, since it will not detect -changes in the database. The local cache is automatically invalidated -every hour, so the query will be performed again at most one hour later. -Local caching is disabled when you execute a query with parameters. In -this case, prepare the query on the server which will still be reasonably -fast. - -Finally, here are some examples of timings. The exact timing are -irrelevant, but it is interesting to look at the different between the -various scenarios. Each of them performs 100_000 simple queries similar -to the one used in this section:: - - Not preparing the query, using `Direct_Cursor`: - 4.05s - - Not preparing the query, using `Forward_Cursor`, and only - retrieving the first row: - 3.69s - - Preparing the query on the client (`On_Server => False`), - with a `Direct_Cursor`. This saves the whole `GNATCOLL.SQL` - manipulations and allocations: - 2.50s - - Preparing the query on the server, using `Direct_Cursor`: - 0.55s - - Caching the query locally (`Use_Cache => True`): - 0.13s - -.. _Getting_results: - -Getting results -=============== - -Once you have executed a `SELECT` query, you generally need to -examine the rows that were returned by the database server. This is done -in a loop, as in:: - - while Has_Row (R) loop - Put_Line ("Max priority=" & Integer_Value (R, 0)'Img - & " for category=" & Value (R, 1)); - Next (R); - end loop; - -You can only read one row at a time, and as soon as you have moved to the -next row, there is no way to access a previously fetched row. This is the -greatest common denominator between the various database systems. In -particular, it proves efficient, since only one row needs to be kept in -memory at any point in time. - -For each row, we then call one of the `Value` or `*Value` -functions which return the value in a specific row and a specific -column. - -We mentioned earlier there was no way to go back to a row you fetched -previously except by executing the query again. This is in fact only -true if you use a `Forward_Cursor` to fetch the results. - -But GNATColl provides another notion, a `Direct_Cursor`. In -this case, it fetches all the rows in memory when the query executes (thus -it needs to allocate more memory to save every thing, which can be costly -if the query is big). This behavior is supported natively by `PostgreSQL`, -but doesn't exist with `sqlite`, so GNATColl will simulate it -as efficiently as possible. But it will almost always be faster to use -a `Forward_Cursor`. - -In exchange for this extra memory overhead, you can now traverse the list -of results in both directions, as well as access a specific row directly. -It is also possible to know the number of rows that matched (something hard -to do with a `Forward_Cursor` since you would need to traverse the -list once to count, and then execute the query again if you need the rows -themselves). - -Direct_Cursor, produced from prepeared statements, could be indexed by the -specified field value and routine Find could set the cursor position to the row -with specified field value.:: - - -- Prepared statement should be declared on package level. - - Stmt : Prepared_Statement := - Prepare ("select Id, Name, Address from Contact order by Name" - Use_Cache => True, Index_By => Field_Index'First); - - procedure Show_Contact (Id : Integer) is - CI : Direct_Cursor; - begin - CI.Fetch (DB, Stmt); - CI.Find (Id); -- Find record by Id - - if CI.Has_Row then - Put_Line ("Name " & CI.Value (1) & " Address " & CI.Value (2)); - else - Put_Line ("Contact id not found."); - end if; - end Show_Contact; - -In general, the low-level DBMS C API use totally different approaches for -the two types of cursors (when they even provide them). By contrast, -GNATColl makes it very easy to change from one to the other just -by changing the type of a the result variable. So you would in general -start with a `Forward_Cursor`, and if you discover you in fact need -more advanced behavior you can pay the extra memory cost and use a -`Direct_Cursor`. - -For both types of cursors, GNATColl automatically manages memory -(both on the client and on the DBMS), thus providing major simplification of -the code compared to using the low-level APIs. - -Creating your own SQL types -=========================== - -GNATColl comes with a number of predefined types that you can use in -your queries. :file:`gnatcoll_db2ada` will generate a file using any of these -predefined types, based on what is defined in your actual database. - -But sometimes, it is convenient to define your own SQL types to better -represent the logic of your application. For instance, you might want to -define a type that would be for a `Character` field, rather than use -the general `SQL_Field_Text`, just so that you can write statements -like:: - - declare - C : Character := 'A'; - Q : SQL_Query; - begin - Q := SQL_Select (.., Where => Table.Field = C); - end - -This is fortunately easily achieved by instantiating one generic package, -as such:: - - with GNATCOLL.SQL_Impl; use GNATCOLL.SQL_Impl; - - function To_SQL (C : Character) return String is - begin - return "'" & C & "'"; - end To_SQL; - - package Character_Fields is new Field_Types (Character, To_SQL); - type SQL_Field_Character is new Character_Fields.Field - with null record; - - -This automatically makes available both the field type (which you can use in -your database description, as :file:`gnatcoll_db2ada` would do, but also -all comparison operators like `<`, `>`, `=`, and so on, both -to compare with another character field, or with `Character` Ada -variable. Likewise, this makes available the assignment operator `=` -so that you can create `INSERT` statements in the database. - -Finally, the package `Character_Fields` contain other generic -packages which you can instantiate to bind SQL operators and functions that -are either predefined in SQL and have no equivalent in GNATColl yet, -or that are functions that you have created yourself on your DBMS server. - -See the specs of `GNATCOLL.SQL_Impl` for more details. This package -is only really useful when writing your own types, since otherwise you -just have to use `GNATCOLL.SQL` to write the actual queries. - -See also `GNATCOLL.SQL_Fields` for an example on how to have a full -integration with other parts of `GNATCOLL.SQL`. - -Query logs -========== - -In :ref:`Logging_information` we discovered the logging module of -GNATColl. The database interface uses this module to log the -queries that are sent to the server. - -If you activate traces in your application, the user can then activate -one of the following trace handles to get more information on the -exchange that exists between the database and the application. As we saw -before, the output of these traces can be sent to the standard output, a -file, the system logs,... - -The following handles are provided: - -* SQL.ERROR - This stream is activated by default. Any error returned by the database - (connection issues, failed transactions,...) will be logged on this stream - -* SQL - This stream logs all queries that are not SELECT queries, ie mostly all - queries that actually modify the database - -* SQL.SELECT - This stream logs all select queries. It is separated from SQL because - very often you will be mostly interested in the queries that impact the - database, and logging all selects can generate a lot of output. - -In our library example, we would add the following code to see all SQL -statements executed on the server:: - - with GNATCOLL.Traces; use GNATCOLL.Traces; - procedure Main is - begin - GNATCOLL.Traces.Parse_Config_File (".gnatdebug"); - ... -- code as before - GNATCOLL.Traces.Finalize; -- reclaim memory - -and then create a .gnatdebug in the directory from which we launch our -executable. This file would contain a single line containing "+" to -activate all log streams, or the following to activate only the subset of -fields related to SQL:: - - SQL=yes - SQL.SELECT=yes - SQL.LITE=yes - -.. _Writing_your_own_cursors: - -Writing your own cursors -======================== - -The cursor interface we just saw is low-level, in that you get access to -each of the fields one by one. Often, when you design your own application, -it is better to abstract the database interface layer as much as possible. -As a result, it is often better to create record or other Ada types to -represent the contents of a row. - -Fortunately, this can be done very easily based on the API provided by -`GNATCOLL.SQL`. Note that `GNATCOLL.SQL.ORM` provides a similar -approach based on automatically generated code, so might be even better. -But it is still useful to understand the basics of providing your own -objects. - -Here is a code example that shows how this can be done:: - - type Customer is record - Id : Integer; - First, Last : Unbounded_String; - end record; - - type My_Cursor is new Forward_Cursor with null record; - function Element (Self : My_Cursor) return My_Row; - function Do_Query (DB, ...) return My_Cursor; - -The idea is that you create a function that does the query for you (based -on some parameters that are not shown here), and then returns a cursor over -the resulting set of rows. For each row, you can use the `Element` -function to get an Ada record for easier manipulation. - -Let's first see how these types would be used in practice:: - - declare - C : My_Cursor := Do_Query (DB, ...); - begin - while Has_Row (C) loop - Put_Line ("Id = " & Element (C).Id); - Next (C); - end loop; - end; - -So the loop itself is the same as before, except we no longer access each of -the individual fields directly. This means that if the query changes to -return more fields (or the same fields in a different order for instance), -the code in your application does not need to change. - -The specific implementation of the subprograms could be similar to the -following subprograms (we do not detail the writing of the SQL query itself, -which of course is specific to your application):: - - function Do_Query return My_Cursor is - Q : constant SQL_Query := ....; - R : My_Cursor; - begin - R.Fetch (DB, Q); - return R; - end Do_Query; - - function Element (Self : My_Cursor) return My_Row is - begin - return Customer' - (Id => Integer_Value (Self, 0), - First => To_Unbounded_String (Value (Self, 1)), - Last => To_Unbounded_String (Value (Self, 2))); - end Element; - - -There is one more complex case though. It might happen that an element -needs access to several rows to fill the Ada record. For instance, if we -are writing a CRM application and query the contacts and the companies they -work for, it is possible that a contact works for several companies. The -result of the SQL query would then look like this:: - - contact_id | company_id - 1 | 100 - 1 | 101 - 2 | 100 - - -The sample code shown above will not work in this case, since Element is -not allowed to modify the cursor. In such a case, we need to take a slightly -different approach:: - - type My_Cursor is new Forward_Cursor with null record; - function Do_Query return My_Cursor; -- as before - procedure Element_And_Next - (Self : in out My_Cursor; Value : out My_Row); - -where `Element_And_Next` will fill Value and call Next as many times -as needed. On exit, the cursor is left on the next row to be processed. The -usage then becomes:: - - while Has_Row (R) loop - Element_And_Next (R, Value); - end loop; - -To prevent the user from using Next incorrectly, you should probably override -`Next` with a procedure that does nothing (or raises a Program_Error -maybe). Make sure that in `Element_And_Next` you are calling the -inherited function, not the one you have overridden, though. - -There is still one more catch. The user might depend on the two subprograms -`Rows_Count` and `Processed_Rows` to find out how many rows there -were in the query. In practice, he will likely be interested in the number -of distinct contacts in the tables (2 in our example) rather than the number -of rows in the result (3 in the example). You thus need to also override -those two subprograms to return correct values. - -.. _The_object_relational_mapping_layer: - -The Object-Relational Mapping layer (ORM) -========================================= - -GNATColl provides a high-level interface to manipulate persistent -objects stored in a database, using a common paradigm called an -object-relational mapping. Such mappings exist for most programming -languages. In the design of GNATColl, we were especially inspired -by the python interface in `django` and `sqlalchemy`, although the -last two rely on dynamic run time introspection and GNATColl relies -on code generation instead. - -This API is still compatible with `GNATCOLL.SQL`. In fact, we'll -show below cases where the two are mixed. It can also be mixed with -`GNATCOLL.SQL.Exec`, although this might be more risky. Communication -with the DBMS is mostly transparent in the ORM, and it uses various caches -to optimize things and make sure that if you modify an element the next -querie(s) will also return it. If you use `GNATCOLL.SQL.Exec` directly -you are bypassing this cache so you risk getting inconsistent results in -some cases. - -In ORM, a table is not manipulated directly. Instead, you manipulate objects -that are read or written to a table. When we defined our database schema -(:ref:`Database_schema`), we gave two names on the first line of a table -definition. There was the name of the table in the database, and the name -of the object that each row represent. So for our library example we have -defined `Customer`, `Book` and `Dvd` objects. These objects -are declared in a package generated automatically by `gnatcoll_db2ada`. - -There is first one minor change we need to do to our library example. The -ORM currently does not handle properly cases where an abstract class has -foreign keys to other tables. So we remove the `borrowed_by` field -from the `Media` table, and change the `books` table to be:: - - - | TABLE (media) | books | book | | The books in the library | - | pages | INTEGER | | 100 | | - | borrowed_by | FK customers(borrowed_books) | NULL | | Who borrowed the media | - - -Let's thus start by generating this code. We can replace the command we -ran earlier (with the `-api` switch) with one that will also generate -the ORM API:: - - gnatcoll_db2ada -dbmode dbschema.txt -api Database -orm ORM - -The ORM provides a pool of database connections through the package -`GNATCOLL.SQL.Sessions`. A session therefore acts as a wrapper around -a connection, and provides a lot more advanced features that will be -described later. The first thing to do in the code is to configure the -session pool. The `Setup` procedure takes a lot of parameters to -make sessions highly configurable. Some of these parameters will be -described and used in this documentation, others are for special usage and -are only documented in :file:`gnatcoll-sql-sessions.ads`. Here will we -use only specify the mandatory parameters and leave the default value for -the other parameters:: - - GNATCOLL.SQL.Sessions.Setup - (Descr => GNATCOLL.SQL.Sqlite.Setup ("library.db"), - Max_Sessions => 2); - - -The first parameter is the same `Database_Description` we saw -earlier (:ref:`Connecting_to_the_database`), but it will be freed -automatically by the sessions package, so you should not free it -yourself. - -Once configure, we can now request a session. Through a session, we can -perform queries on the database, make objects persistent, write the -changes back to the database,.... We configured the session pool -to have at most 2 sessions. The first time we call `Get_New_Session`, -a new session will be created in the pool and marked as busy. While you -have a reference to it in your code (generally as a local variable), the -session belongs to this part of the code. When the session is no longer -in scope, it is automatically released to the pool to be reused for the -next call to `Get_New_Session`. If you call `Get_New_Session` -a second time while some part of your code holds a session (for instance -in a different task), a new session will be created. But if you do that -a third time while the other two are busy, the call to `Get_New_Session` -is blocking until one of the two sessions is released to the pool. - -This technics ensures optimal use of the resources: we avoid creating -a new session every time (with the performance cost of connecting to the -database), but also avoid creating an unlimited number of sessions which -could saturate the server. Since the sessions are created lazily the first -time they are needed, you can also configure the package with a large -number of sessions with a limited cost. - -Let's then take a new session in our code:: - - Session : constant Session_Type := Get_New_Session; - -and let's immediately write our first simple query. A customer comes at -the library, handles his card and we see his id (1). We need to look up -in the database to find out who he is. Fortunately, there is no SQL to -write for this:: - - C : ORM.Detached_Customer'Class := Get_Customer (Session, Id => 1); - -The call to `Get_Customer` performs a SQL query transparently, using -prepared statements for maximum efficiency. This results in a -`Customer` object. - -`ORM` is the package that was generated automatically by -`gnatcoll_db2ada`. For each table in the database, it generates a -number of types: - -* `Customer` - - This type represents a row of the `Customers` table. It comes with - a number of primitive operations, in particular one for each of the - fields in the table. Such an object is returned by a cursor, similarly - to what was described in the previous section (:ref:`Writing_your_own_cursors`). - This object is no longer valid as soon as the cursor moves to - the next row (in the currently implementation, the object will describe - the next row, but it is best not to rely on this). As a benefit, this - object is light weight and does not make a copy of the value of the - fields, only reference the memory that is already allocated for the cursor. - - This object redefines the equality operator ("=") to compare the - primary key fields to get expected results. - -* `Detached_Customer` - - A detached object is very similar to the `Customer` object, but it - will remain valid even if the cursor moves or is destroyed. In fact, the - object has made a copy of the value for all of its fields. This object - is heavier than a `Customer`, but sometimes easier to manager. If - you want to store an object in a data structure, you must always store - a detached object. - - A detached object also embeds a cache for its foreign keys. In the - context of our demo for instance, a `Book` object was borrowed by - a customer. When returning from a query, the book knows the id of that - customer. But if call `B.Borrowed_By` this returns a - `Detached_Customer` object which is cached (the first time, a query - is made to the DBMS to find the customer given his id, but the second - time this value is already cached). - - One cache create a `Detached_Customer` from a `Customer` by - calling the `Detach` primitive operation. - -* `Customer_List` - - This type extends a `Forward_Cursor` (:ref:`Getting_results`). In - addition to the usual `Has_Row` and `Next` operations, it also - provides an `Element` operation that returns a `Customer` for - easy manipulation of the results. - -* `Direct_Customer_List` - - This type extends a `Direct_Cursor`. It also adds a `Element` - operation that returns a `Customer` element. - -* `Customers_Managers` - - This type is the base type to perform queries on the DBMS. A manager - provides a number of primitive operations which end up creating a SQL - query operation in the background, without making that explicit. - - Let's first write a query that returns all books in the database:: - - declare - M : Books_Managers := All_Books; - BL : Book_List := M.Get (Session); - B : Book; - begin - while BL.Has_Row loop - B := BL.Element; - Put_Line ("Book: " & B.Title); - Put_Line (" Borrowed by: " & B.Borrowed_By.Last); - BL.Next; - end loop; - end; - - The manager `M` corresponds to a query that returns all the books - in the database. The second line then executes the query on the database, - and returns a list of books. We then traverse the list. Note how we access - the book's title by calling a function, rather than by the index of a - field as we did with `GNATCOLL.SQL.Exec` with Value(B, 0). The code - is much less fragile this way. - - The line that calls `Borrowed_By` will execute an additional SQL - query for each book. This might be inefficient if there is a large number - of books. We will show later how this can be optimized. - - The manager however has a lot more primitive operations that can be used - to alter the result. Each of these primitive operations returns a modified - copy of the manager, so that you can easily chain calls to those primitive - operations. Those operations are all declared in the package - `GNATCOLL.SQL.ORM.Impl` if you want to look at the documentation. - Here are those operations: - - * `Get` and `Get_Direct` - - As seen in the example above, these are the two functions that execute the - query on the database, and returns a list of objects (respectively a - `Customer_List` and a `Direct_Customer_List`). - - * `Distinct` - - Returns a copy of the manager that does not return twice a row with the - same data (in SQL, this is the "DISTINCT" operator) - - * `Limit` (Count : Natural; From : Natural := 0) - - Returns a copy of the manager that returns a subset of the results, for - instance the first `Count` ones. - - * `Order_By` (By : SQL_Field_List) - - Returns a copy of the manager that sorts the results according to a criteria. - The criteria is a list of field as was defined in `GNATCOLL.SQL`. - We can for instance returns the list of books sorted by title, and only the - first 5 books, by replacing `M` with the following:: - - M : Books_Managers := All_Books.Limit (5).Order_By (Books.Title); - - - * `Filter` - - Returns a subset of the result matching a criteria. There are currently - two versions of Filter: one is specialized for the table, and has one - parameter for each field in the table. We can for instance return all the - books by Alexandre Dumas by using:: - - M : Books_Managers := All_Books.Filter (Author => "Dumas"); - - - This version only provides the equality operator for the fields of the - table itself. If for instance we wanted all books with less than 50 pages, - we would use the second version of filter. This version takes a - `GNATCOLL.SQL.SQL_Criteria` similar to what was explained in previous - sections, and we would write:: - - M : Books_Managers := All_Books.Filter (Condition => Books.Pages < 50); - - More complex conditions are possible, involving other tables. Currently, - the ORM does not have a very user-friendly interface for those, but you - can always do this by falling back partially to SQL. For instance, if we - want to retrieve all the books borrowed by user "Smith", we need to - involve the `Customers` table, and thus make a join with the - `Books` table. In the future, we intend to make this join automatic, - but for now you will need to write:: - - M : Books_Managers := All_Books.Filter - (Books.FK (Customers) - and Customers.Last = "Smith"); - - -- SQL query: SELECT books.pages, books.borrowed_by, books.id, - -- books.title, books.author, books.published - -- FROM books, customers - -- WHERE books.borrowed_by=customers.id AND customers.last='Smith' - - This is still simpler code than we were writing with `GNATCOLL.SQL` - because we do not have to specify the fields or tables, and the results - are objects rather than fields with specific indexes. - - * `Select_Related` (Depth : Integer; Follow_Left_Join : Boolean) - - This function returns a new manager that will retrieve all related - objects. In the example we gave above, we mentioned that every time - `B.Borrowed_By` was called, this resulted in a call to the DBMS. - We can optimize this by making sure the manager will retrieve that - information. As a result, there will be a single query rather than lots. - Be careful however, since the query will return more data, so it might - sometimes be more efficient to perform multiple smaller queries. - - `Depth` indicates on how many levels the objects should be retrieved. - For instance, assume we change the schema such that a Book references - a Customer which references an Address. If we pass 1 for `Depth`, - the data for the book and the customer will be retrieved. If however you - then call `B.Borrowed_By.Address` this will result in a query. So - if you pass 2 for `Depth` the data for book, customers and addresses - will be retrieved. - - The second parameter related to efficiency. When a foreign key was mentioned - as `NOT NULL` in the schema, we know it is always pointing to an - existing object in another table. `Select_Related` will always - retrieve such objects. If, however, the foreign key can be null, i.e. there - isn't necessarily a corresponding object in the other table, the SQL - query needs to use a `LEFT JOIN`, which is less efficient. By default, - GNATColl will not retrieve such fields unless `Follow_Left_Join` - was set to True. - - In our example, a book is not necessarily borrowed by a customer, so we need - to follow the left joins:: - - M : Books_Managers := All_Books.Filter - (Books.FK (Customers) - and Customers.Last = "Smith") - .Select_Related (1, Follow_Left_Join => True); - - -- SQL query: SELECT books.pages, books.borrowed_by, books.id, - -- books.title, books.author, books.published, - -- customers.id, customers.first, customers.last - -- FROM (books LEFT JOIN customers ON books.borrowed_by=customers.id) - -- WHERE books.borrowed_by=customers.id AND customers.last='Smith' - -reverse relationships ---------------------- - -In fact, the query we wrote above could be written differently. Remember -we have already queries the `Customer` object for id 1 through a -call to `Get_Customer`. Since our schema specified a `reverse_name` -for the foreign key `borrowed_by` in the table `books`, we can -in fact simply use:: - - BL := C.Borrowed_Books.Get (Session); - - -- SQL: SELECT books.pages, books.borrowed_by, books.id, books.title, - -- books.author, books.published FROM books - -- WHERE books.borrowed_by=1 - - -`Borrowed_Books` is a function that was generated because there was -a `reverse_name`. It returns a `Books_Managers`, so we could -in fact further filter the list of borrowed books with the same primitive -operations we just saw. As you can see, the resulting SQL is optimital. - -Let's optimize further the initial query. We have hard-coded the -customer name, but in fact we could be using the same subprograms we -were using for prepared statements (:ref:`Prepared_queries`), and even -prepare the query on the server for maximum efficiency. Since our application -is likely to use this query a lot, let's create a global variable:: - - M : constant Books_Managers := All_Books.Filter - (Books.FK (Customers) - and Customers.Id = Integer_Param (1)) - .Select_Related (1, Follow_Left_Join => True); - - MP : constant ORM_Prepared_Statement := - M.Prepare (On_Server => True); - - ... later in the code - - Smith_Id : constant Natural := 1; - BL : Book_List := MP.Get (Session, Params => (1 => Smith_Id)); - - -The last call to `Get` is very efficient, with timing improvements -similar to the ones we discussed on the session about prepared statements -(:ref:`Prepared_queries`). - -Modifying objects in the ORM -============================ - -The ORM is much more than writing queries. Once the objects are persistent, -they can also be simplify modified, and they will be saved in the database -transparently. - -Let's start with a simple example. In the previous section, we retrieve an -object `C` representing a customer. Let's change his name, and make -sure the change is in the database:: - - C := Get_Customer (Session, 1); - C.Set_Last ("Smit"); - C.Set_First ("Andrew"); - Session.Commit; - -A reasonable way to modify the database. However, this opens a can of -complex issues that need to be dealt with. - -When we called `Set_Last`, this modify the objects in memory. At this -point, printing the value of `C.Last` would indeed print the new value -as expected. The object was also marked as modified. But no change was -made in the database. - -Such a change in the database might in fact be rejected, depending on -whether there are constraints on the field. For instance, say there existed -a constraint that `Last` must be the same `First` (bear with me, -this is just an example). If we call `Set_Last`, the constraint is -not satisfied until we also call `Set_First`. But if the former resulted -in an immediate change in the database, it would be rejected and we would not -even get a change to call `Set_First`. - -.. highlight:: sql - -Instead, the session keeps a pointer to all the objects that have been -modified. When it is committed, it traverses this list of objects, and -commits their changes into the database. In the example we gave above, the -call to `Commit` will thus commit the changes to `C` in the -database. For efficiency, it uses a single SQL statement for that, which also -ensures the constraint remains valid:: - - UPDATE customers SET first='Andrew', last='Smit' WHERE customers.id=1; - - -.. highlight:: ada - -We can create a new customer by using similar code:: - - C := New_Customer; - C.Set_First ("John"); - C.Set_Last ("Lee"); - Session.Persist (C); - - Session.Commit; - -`New_Customer` allocates a new object in memory. However, this object -is not persistent. You can call all the `Set_*` subprograms, but the -object will not be saved in the database until you add it explicitly to -a session with a call to `Persist`, and then `Commit` the -session as usual. - -Another issue can occur when objects can be modified in memory. Imagine -we retrieve a customer, modify it in memory but do not commit to the -database yet because there are other changes we want to do in the same -SQL transaction. We then retrieve the list of all customers. Of course, -the customer we just modified is part of this list, but the DBMS does not -know about the change which currently only exists in memory. - -Thankfully, -GNATColl takes care of this issue automatically: as we mentioned -before, all modified objects are stored in the session. When traversing -the list of results, the cursors will check whether the session already -contains an element with the same id that it sees in the result, and if -yes will return the existing (i.e. modified) element. For instance:: - - C := Get_Customer (Session, Id => 1); - C.Set_Last ("Lee"); - - CL : Customer_List := All_Customers.Get (Session); - while CL.Has_Row loop - Put_Line (CL.Element.Last); - CL.Next; - end loop; - -.. index:: Flush_Before_Query - -The above example uses `CL.Element`, which is a light-weight -`Customer` object. Such objects will only see the in-memory changes -if you have set `Flush_Before_Query` to true when you configured -the sessions in the call to `GNATCOLL.SQL.Sessions.Setup`. Otherwise, -it will always return what's really in the database. - -If the example was using `Detached_Customer` object (by calling -`CL.Element.Detach` for instance) then GNATColl looks up in -its internal cache and returns the cached element when possible. This is -a subtlety, but this is because an `Customer` only exists as long as -its cursor, and therefore cannot be cached in the session. In practice, the -`Flush_Before_Query` should almost always be true and there will be -not surprising results. - -Object factories in ORM -======================= - -Often, a database table is used to contain objects that are semantically -of a different kind. In this section, we will take a slightly different -example from the library. We no longer store the books and the DVDs in -separate tables. Instead, we have one single `media` table which -contains the title and the author, as well as a new field `kind` -which is either 0 for a book or 1 for a DVD. - -Let's now look at all the media borrowed by a customer:: - - C : constant Customer'Class := Get_Customer (Session, Id => 1); - ML : Media_List := C.Borrowed_Media.Get (Session); - - while ML.Has_Row loop - case ML.Element.Kind is - when 0 => - Put_Line ("A book " & ML.Element.Title); - when 1 => - Put_Line ("A DVD " & ML.Element.Title); - end case; - ML.Next; - end loop; - -This code works, but requires a case statement. Now, let's imagine -the check out procedure is different for a book and a DVD (for the latter -we need to check that the disk is indeed in the box). We would have two -subprograms `Checkout_Book` and `Checkout_DVD` and call them -from the case. This isn't object-oriented programming. - -Instead, we will declare two new types:: - - type My_Media is abstract new ORM.Detached_Media with private; - procedure Checkout (Self : My_Media) is abstract; - - type Detached_Book is new My_Media with private; - overriding Checkout (Self : Detached_Book); - - type Detached_DVD is new My_Media with private; - overriding Checkout (Self : Detached_DVD); - -We could manually declare a new Media_List and override `Element` so -that it returns either of the two types instead of a `Media`. -But then we would also need to override `Get` so that it returns our -new list. This is tedious. - -We will instead use an element factory in the session. This is a function -that gets a row of a table (in the form of a `Customer`), and returns -the appropriate type to use when the element is detached (by default, -the detached type corresponding to a `Customer` is a -`Detached_Customer`, and that's what we want to change). - -So let's create such a factory:: - - function Media_Factory - (From : Base_Element'Class; - Default : Detached_Element'Class) return Detached_Element'Class - is - begin - if From in Media'Class then - case Media (From).Kind is - when 0 => - return R : Detached_Book do null; end return; - when 1 => - return R : Detached_DVD do null; end return; - when others => - return Default; - end case; - end if; - return Default; - end Media_Factory; - - Session.Set_Factory (Media_Factory'Access); - -This function is a bit tricky. It is associated with a given session (although -we can also register a default factory that will be associated with all -sessions by default). For all queries done through this session (and for -all tables) it will be called. So we must first check whether we are dealing -with a row from the `Media` table. If not, we simply return the -suggested `Default` value (which has the right `Detached_*` kind -corresponding to the type of `From`). - -If we have a row from the `Media` table, we then retrieve its kind -(through the usual automatically generated function) to return an -instance of `Detached_Book` or `Detached_DVD`. We use the -Ada05 notation for extended return statements, but we could also use a -declare block with a local variable and return that variable. The returned -value does not need to be further initialized (the session will take care -of the rest of the initialization). - -We can now write our code as such:: - - C : constant Customer'Class := Get_Customer (Session, Id => 1); - ML : Media_List := C.Borrowed_Media.Get (Session); - - while ML.Has_Row loop - Checkout (ML.Element.Detach); -- Dispatching - ML.Next; - end loop; - -The loop is cleaner. Of course, we still have the case statement, but it -now only exists in the factory, no matter how many loops we have or how -many primitive operations of the media we want to define. - diff -Nru libgnatcoll-18/examples/base64_coder.adb libgnatcoll-19/examples/base64_coder.adb --- libgnatcoll-18/examples/base64_coder.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/examples/base64_coder.adb 2019-05-16 17:44:09.000000000 +0000 @@ -0,0 +1,132 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ +-- +-- This demo encodes/decodes to/from base64 from standard intput to standard +-- output. + +with Ada.Streams; use Ada.Streams; +with Ada.Command_Line; use Ada.Command_Line; +with Ada.Text_IO.Text_Streams; use Ada.Text_IO; +with GNATCOLL.Coders.Streams; use GNATCOLL.Coders; +with GNATCOLL.Coders.Base64; + +procedure Base64_Coder is + + Stream : aliased Streams.Stream_Type; + Encoder : aliased Base64.Encoder_Type; + Decoder : aliased Base64.Decoder_Type; + Buffer : Stream_Element_Array (1 .. 1024); + Last : Stream_Element_Offset; + Action : constant String := (if Argument_Count = 0 then "" + else Argument (1)); + Back_Input : access Root_Stream_Type'Class; + Back_Output : access Root_Stream_Type'Class; + Input : access Root_Stream_Type'Class; + Output : access Root_Stream_Type'Class; + Read_Coder : access Coder_Interface'Class; + Write_Coder : access Coder_Interface'Class; + Input_File : File_Type; + Input_Stream : access Root_Stream_Type'Class; + +begin + Encoder.Initialize (Wrap => 76); + Decoder.Initialize; + + if Argument_Count > 1 then + Open (Input_File, In_File, Argument (2)); + Input_Stream := Text_Streams.Stream (Input_File); + else + Input_Stream := Text_Streams.Stream (Current_Input); + end if; + + if Action = "" then + -- Encode, decode back, and print to output + + Back_Input := Input_Stream; + Back_Output := Text_Streams.Stream (Current_Output); + Input := Stream'Access; + Output := Stream'Access; + Read_Coder := Encoder'Unchecked_Access; + Write_Coder := Decoder'Unchecked_Access; + + elsif Action = "-" then + -- Decode, encode, and print to output + + Back_Input := Input_Stream; + Back_Output := Text_Streams.Stream (Current_Output); + Input := Stream'Access; + Output := Stream'Access; + Read_Coder := Decoder'Unchecked_Access; + Write_Coder := Encoder'Unchecked_Access; + + elsif Action = "er" then + -- Encode over read from stream + + Back_Input := Input_Stream; + Input := Stream'Access; + Output := Text_Streams.Stream (Current_Output); + Read_Coder := Encoder'Unchecked_Access; + + elsif Action = "dr" then + -- Decode over read from stream + + Back_Input := Input_Stream; + Input := Stream'Access; + Output := Text_Streams.Stream (Current_Output); + Read_Coder := Decoder'Unchecked_Access; + + elsif Action = "ew" then + -- Encode over write to stream + + Back_Output := Text_Streams.Stream (Current_Output); + Output := Stream'Access; + Input := Input_Stream; + Write_Coder := Encoder'Unchecked_Access; + + elsif Action = "dw" then + -- Decode over write to stream + + Back_Output := Text_Streams.Stream (Current_Output); + Output := Stream'Access; + Input := Input_Stream; + Write_Coder := Decoder'Unchecked_Access; + end if; + + Stream.Initialize + (Read_Coder => Read_Coder, + Read_From => Back_Input, + Write_Coder => Write_Coder, + Write_To => Back_Output, + Read_Ends_By => Streams.Partial_Read); + + loop + Input.Read (Buffer, Last); + Output.Write (Buffer (1 .. Last)); + exit when Last < Buffer'Last; + end loop; + + if Output = Stream'Access then + Stream.Flush (Finish); + end if; + +end Base64_Coder; diff -Nru libgnatcoll-18/examples/base64-demo libgnatcoll-19/examples/base64-demo --- libgnatcoll-18/examples/base64-demo 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/examples/base64-demo 2019-01-28 05:21:02.000000000 +0000 @@ -0,0 +1,18 @@ +# base64_coder is test and example of using the GNATCOLL.Coders.Base64. +# base64 utility is system provided base64 encoder/decoder. +# Encode original phrase few times and decode it the same number of times with +# system and ours encoder/decoder to be sure that they are working the same. +# Each encoding by our example decoded by system utility and vise versa. + +echo Deep coded $1 \ + | base64 | base64 | base64 | base64 | base64 | base64 | base64 | base64 \ + | ./base64_coder er | ./base64_coder er | ./base64_coder er \ + | ./base64_coder ew | ./base64_coder ew | ./base64_coder ew \ + | ./base64_coder er | ./base64_coder er | ./base64_coder er \ + | base64 | ./base64_coder - | ./base64_coder | base64 -d \ + | base64 -d | base64 -d | base64 -d \ + | base64 -d | base64 -d | base64 -d \ + | base64 -d | base64 -d | base64 -d \ + | ./base64_coder dr | ./base64_coder dr | ./base64_coder dr \ + | ./base64_coder dw | ./base64_coder dw | ./base64_coder dw \ + | ./base64_coder dr | ./base64_coder dw diff -Nru libgnatcoll-18/examples/examples.gpr libgnatcoll-19/examples/examples.gpr --- libgnatcoll-18/examples/examples.gpr 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/examples/examples.gpr 2019-05-16 17:44:08.000000000 +0000 @@ -2,8 +2,19 @@ project Examples is for Object_Dir use "obj"; for Exec_Dir use "."; - for Main use ("newclass.adb"); - for Source_Files use ("common.ads", "common.adb", - "textconsole.ads", "textconsole.adb", - "newclass.adb"); + for Main use ("newclass.adb", "base64_coder.adb"); + for Source_Dirs use ("."); + + package Compiler is + for Switches ("Ada") use ("-g", "-gnateE"); + end Compiler; + + package Linker is + for Switches ("Ada") use ("-g"); + end Linker; + + package Binder is + for Switches ("Ada") use ("-E"); + end Binder; + end Examples; diff -Nru libgnatcoll-18/gnatcoll.gpr libgnatcoll-19/gnatcoll.gpr --- libgnatcoll-18/gnatcoll.gpr 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/gnatcoll.gpr 2019-05-16 17:44:08.000000000 +0000 @@ -32,9 +32,6 @@ Mmap : Yes_No := External ("GNATCOLL_MMAP", "yes"); Madvise : Yes_No := External ("GNATCOLL_MADVISE", "yes"); - type Atomics_Kind is ("intrinsic", "mutex"); - Atomics : Atomics_Kind := External ("GNATCOLL_ATOMICS", "intrinsic"); - type Build_Type is ("DEBUG", "PROD"); Build : Build_Type := External ("BUILD"); @@ -53,7 +50,7 @@ type OS_Kind is ("windows", "unix", "osx"); OS : OS_Kind := External ("GNATCOLL_OS", "unix"); - Extra_Switches := (); + Extra_Switches := ("-DATOMIC_INTRINSICS"); Extra_Libs := (); case OS is when "windows" => @@ -85,13 +82,6 @@ for Library_Version use "lib" & Name & So_Ext & "." & Version; - case Atomics is - when "intrinsic" => - Extra_Switches := Extra_Switches & ("-DATOMIC_INTRINSICS"); - when "mutex" => - null; - end case; - case Library_Type is when "relocatable" => for Library_Options use Extra_Libs; @@ -165,15 +155,6 @@ for Implementation ("GNATCOLL.Plugins") use "gnatcoll-plugins__windows.adb"; end case; - - case Atomics is - when "intrinsic" => - for Implementation ("GNATCOLL.Atomic") - use "gnatcoll-atomic__intrinsic.ada"; - when "mutex" => - for Implementation ("GNATCOLL.Atomic") - use "gnatcoll-atomic__mutex.ada"; - end case; end Naming; package Linker is diff -Nru libgnatcoll-18/Makefile libgnatcoll-19/Makefile --- libgnatcoll-18/Makefile 2018-05-10 05:48:27.000000000 +0000 +++ libgnatcoll-19/Makefile 2018-07-19 04:20:17.000000000 +0000 @@ -47,8 +47,6 @@ # default is "yes"; has no effect on Windows # GNATCOLL_MADVISE : whether MADVISE is supported (yes/no) # default is "yes"; has no effect on Windows -# GNATCOLL_ATOMICS : atomic model (intrinsic/mutex) -# default is "intrinsic" # helper programs CAT := cat @@ -79,7 +77,6 @@ GNATCOLL_VERSION := $(shell $(CAT) $(SOURCE_DIR)/version_information) GNATCOLL_MMAP := yes GNATCOLL_MADVISE := yes -GNATCOLL_ATOMICS := intrinsic BUILD = PROD PROCESSORS = 0 @@ -107,7 +104,6 @@ GPR_VARS=-XGNATCOLL_MMAP=$(GNATCOLL_MMAP) \ -XGNATCOLL_MADVISE=$(GNATCOLL_MADVISE) \ - -XGNATCOLL_ATOMICS=$(GNATCOLL_ATOMICS) \ -XGNATCOLL_VERSION=$(GNATCOLL_VERSION) \ -XGNATCOLL_OS=$(GNATCOLL_OS) \ -XBUILD=$(BUILD) @@ -177,7 +173,6 @@ $(ECHO) "GNATCOLL_VERSION=$(GNATCOLL_VERSION)" >> makefile.setup $(ECHO) "GNATCOLL_MMAP=$(GNATCOLL_MMAP)" >> makefile.setup $(ECHO) "GNATCOLL_MADVISE=$(GNATCOLL_MADVISE)" >> makefile.setup - $(ECHO) "GNATCOLL_ATOMICS=$(GNATCOLL_ATOMICS)" >> makefile.setup # Let gprbuild handle parallelisation. In general, we don't support parallel # runs in this Makefile, as concurrent gprinstall processes may crash. diff -Nru libgnatcoll-18/README.md libgnatcoll-19/README.md --- libgnatcoll-18/README.md 2018-03-05 13:06:24.000000000 +0000 +++ libgnatcoll-19/README.md 2018-11-06 05:50:02.000000000 +0000 @@ -17,10 +17,8 @@ Dependencies ------------ -This module depends on the following external components, that should be -available on your system: - -- GPRbuild +GNATCOLL only depends on a recent GNAT compiler. Building it also requires +GPRbuild. Configuring the build process ----------------------------- @@ -51,7 +49,6 @@ effect on Windows * `GNATCOLL_MADVISE`: whether MADVISE is supported (yes/no) default is "yes"; has no effect on Windows -* `GNATCOLL_ATOMICS`: atomic model (intrinsic/mutex) default is "intrinsic" To use the default options: @@ -70,26 +67,18 @@ Building -------- -GNATcoll Core Module is built using a GPR project file, to build it is as -simple as: - -```sh -$ gprbuild gnatcoll.gpr -``` - -Though, to build all versions of the library (static, relocatable and -static-pic) it is simpler to use the provided Makefile: - -```sh -$ make -``` - -Then, to install it: +Building all versions of the GNATCOLL Core Packages (static, relocatable and +static-pic) is as easy as running `make` in the top directory. Then, to install +it: ```sh $ make install ``` +Note that underneath, this Makefile uses a GPR project file: `gnatcoll.gpr`. +You can build GNATCOLL using it with GPRbuild, but make sure to use the same +command-line options. + Bug reports ----------- diff -Nru libgnatcoll-18/src/executable_path.c libgnatcoll-19/src/executable_path.c --- libgnatcoll-18/src/executable_path.c 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/executable_path.c 2019-05-16 17:44:09.000000000 +0000 @@ -0,0 +1,69 @@ +/*---------------------------------------------------------------------------- +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ + +/* The function is the low level part of GNATCOLL.Utils.Executable_Path. */ + +#if defined (__APPLE__) +/* MacOS implementation */ +#include +#include +#include +int +c_executable_path (char *buffer, int size) +{ + int status; + uint32_t bufsize = (uint32_t) size; + status = _NSGetExecutablePath(buffer, &bufsize); + if (status == 0) { + return strlen(buffer); + } else { + return 0; + } +} + +#elif defined (__MINGW32__) || defined (__CYGWIN__) +/* Windows Implementation */ +#include +int +c_executable_path (char *buffer, int size) +{ + return (int) GetModuleFileNameA(NULL, buffer, (DWORD) size); +} + +#elif defined (__linux__) +/* Linux implementation */ +#include +int +c_executable_path (char *buffer, int size) +{ + return readlink("/proc/self/exe", buffer, (size_t) size); +} + +#else +/* Dummy implementation */ +int +c_executable_path (char *buffer, int size) +{ + return 0; +} +#endif diff -Nru libgnatcoll-18/src/gnatcoll-arg_lists.adb libgnatcoll-19/src/gnatcoll-arg_lists.adb --- libgnatcoll-18/src/gnatcoll-arg_lists.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-arg_lists.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -35,7 +35,8 @@ procedure Parse_Command_Line_String (CL : in out Arg_List; - Text : String); + Text : String) + with Pre => CL.Mode = Separate_Args; -- Factor code between variants of Parse_String. -- This processes Text as if it were passed on a command line (for instance -- the bash command line) and adds the arguments to CL. @@ -71,8 +72,11 @@ (CL : in out Arg_List; Text : String) is - function Process (A : String) return Argument_Type; - -- Post-process on each argument returned by Argument_String_To_List + function Process (A : String) return Argument_Type + with Pre => A'Length > 0; + -- Post-process on each argument returned by Argument_String_To_List. + -- Note that Argument_String_To_List_With_Triple_Quotes never returns + -- empty arguments. ------------- -- Process -- @@ -80,10 +84,6 @@ function Process (A : String) return Argument_Type is begin - if A = "" then - return (One_Arg, Null_Unbounded_String); - end if; - -- Argument_String_To_List does not remove single quotes around an -- argument: do this now. if A (A'First) = '"' and then A (A'Last) = '"' then @@ -99,27 +99,17 @@ (Argument_List, Argument_List_Access); begin - -- If we are parsing an argument in Separate_Args mode, get rid of the - -- leading spaces, as this would result in multiple arguments in - -- the call to Argument_String_To_List_With_Triple_Quotes - -- Also remove trailing spaces, since otherwise the last argument on - -- the command line, when surrounded with quotes, will be seen by - -- Process as ending with ASCII.LF, and therefore the quotes will not be - -- removed. - - if CL.Mode = Separate_Args then - Local_Args := Argument_String_To_List_With_Triple_Quotes - (Trim - (Text, - Left => To_Set (' ' & ASCII.LF & ASCII.HT), - Right => To_Set (' ' & ASCII.LF & ASCII.HT))); - else - Local_Args := Argument_String_To_List_With_Triple_Quotes (Text); - end if; - - if Local_Args = null then - return; - end if; + -- Get rid of the leading spaces, as this would result in multiple + -- arguments in the call to Argument_String_To_List_With_Triple_Quotes + -- Also remove trailing spaces, since otherwise the last argument on the + -- command line, when surrounded with quotes, will be seen by Process as + -- ending with ASCII.LF, and therefore the quotes will not be removed. + + Local_Args := Argument_String_To_List_With_Triple_Quotes + (Trim + (Text, + Left => To_Set (' ' & ASCII.LF & ASCII.HT), + Right => To_Set (' ' & ASCII.LF & ASCII.HT))); for J in Local_Args'Range loop CL.V.Append (Process (Local_Args (J).all)); @@ -344,7 +334,8 @@ procedure Substitute (CL : in out Arg_List; Char : Character; - Callback : Substitution_Function) + Callback : access function + (Param : String; Mode : Command_Line_Mode) return Arg_List) is New_CL : Arg_List; @@ -371,7 +362,7 @@ J := S'First; while J <= S'Last loop - if S (J) = Char then + if S (J) = Char and then J < S'Last then -- Skip to the next separator J := J + 1; Beg := J; diff -Nru libgnatcoll-18/src/gnatcoll-arg_lists.ads libgnatcoll-19/src/gnatcoll-arg_lists.ads --- libgnatcoll-18/src/gnatcoll-arg_lists.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-arg_lists.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -105,11 +105,14 @@ type Substitution_Function is access function (Param : String; Mode : Command_Line_Mode) return Arg_List; + -- This type is preserved for backwards compatibility: it used to be the + -- type of the Callback formal below. procedure Substitute (CL : in out Arg_List; Char : Character; - Callback : Substitution_Function); + Callback : access function + (Param : String; Mode : Command_Line_Mode) return Arg_List); -- Substitute all parameters that start with Char using the mechanisms -- specified in Callback. diff -Nru libgnatcoll-18/src/gnatcoll-asserts.adb libgnatcoll-19/src/gnatcoll-asserts.adb --- libgnatcoll-18/src/gnatcoll-asserts.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-asserts.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2005-2017, AdaCore -- +-- Copyright (C) 2005-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -187,7 +187,7 @@ and then not ("<" (Left, Right) or else "=" (Left, Right)) then Report.On_Assertion_Failed - (Details => Image (Left) & " = " & Image (Right), + (Details => Image (Left) & " <= " & Image (Right), Msg => Msg, Location => Location, Entity => Entity); @@ -208,7 +208,7 @@ and then "<" (Left, Right) then Report.On_Assertion_Failed - (Details => Image (Left) & " = " & Image (Right), + (Details => Image (Left) & " >= " & Image (Right), Msg => Msg, Location => Location, Entity => Entity); @@ -229,7 +229,7 @@ and then ("<" (Left, Right) or else "=" (Left, Right)) then Report.On_Assertion_Failed - (Details => Image (Left) & " = " & Image (Right), + (Details => Image (Left) & " > " & Image (Right), Msg => Msg, Location => Location, Entity => Entity); diff -Nru libgnatcoll-18/src/gnatcoll-atomic.adb libgnatcoll-19/src/gnatcoll-atomic.adb --- libgnatcoll-18/src/gnatcoll-atomic.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-atomic.adb 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,183 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2010-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with Interfaces; use Interfaces; + +package body GNATCOLL.Atomic is + + function Intrinsic_Sync_Bool_Compare_And_Swap + (Ptr : access Atomic_Counter; + Oldval : Atomic_Counter; + Newval : Atomic_Counter) return Boolean; + pragma Import (Intrinsic, Intrinsic_Sync_Bool_Compare_And_Swap, + External_Name => "__sync_bool_compare_and_swap_4"); + + function Intrinsic_Sync_Val_Compare_And_Swap + (Ptr : access Atomic_Counter; + Oldval : Atomic_Counter; + Newval : Atomic_Counter) return Atomic_Counter; + pragma Import (Intrinsic, Intrinsic_Sync_Val_Compare_And_Swap, + External_Name => "__sync_val_compare_and_swap_4"); + + function Intrinsic_Sync_Add_And_Fetch + (Ptr : access Atomic_Counter; + Value : Atomic_Counter) return Atomic_Counter; + pragma Import (Intrinsic, Intrinsic_Sync_Add_And_Fetch, + External_Name => "__sync_add_and_fetch_4"); + + function Intrinsic_Sync_Sub_And_Fetch + (Ptr : access Atomic_Counter; + Value : Atomic_Counter) return Atomic_Counter; + pragma Import (Intrinsic, Intrinsic_Sync_Sub_And_Fetch, + External_Name => "__sync_sub_and_fetch_4"); + + ------------------ + -- Is_Lock_Free -- + ------------------ + + function Is_Lock_Free return Boolean is (True); + + ------------------------ + -- Sync_Add_And_Fetch -- + ------------------------ + + function Sync_Add_And_Fetch + (Ptr : access Atomic_Counter; + Value : Atomic_Counter) return Atomic_Counter is + begin + return Intrinsic_Sync_Add_And_Fetch (Ptr, Value); + end Sync_Add_And_Fetch; + + procedure Sync_Add_And_Fetch + (Ptr : access Atomic_Counter; Value : Atomic_Counter) + is + Dummy : Atomic_Counter with Unreferenced; + begin + Dummy := Intrinsic_Sync_Add_And_Fetch (Ptr, Value); + end Sync_Add_And_Fetch; + + ------------------------ + -- Sync_Sub_And_Fetch -- + ------------------------ + + function Sync_Sub_And_Fetch + (Ptr : access Atomic_Counter; + Value : Atomic_Counter) return Atomic_Counter is + begin + return Intrinsic_Sync_Sub_And_Fetch (Ptr, Value); + end Sync_Sub_And_Fetch; + + procedure Sync_Sub_And_Fetch + (Ptr : access Atomic_Counter; Value : Atomic_Counter) + is + Dummy : Atomic_Counter with Unreferenced; + begin + Dummy := Intrinsic_Sync_Sub_And_Fetch (Ptr, Value); + end Sync_Sub_And_Fetch; + + --------------- + -- Increment -- + --------------- + + procedure Increment (Value : aliased in out Atomic_Counter) is + begin + System.Atomic_Counters.Increment (Value); + end Increment; + + --------------- + -- Decrement -- + --------------- + + procedure Decrement (Value : aliased in out Atomic_Counter) is + begin + System.Atomic_Counters.Decrement (Value); + end Decrement; + + function Decrement (Value : aliased in out Atomic_Counter) return Boolean is + begin + return System.Atomic_Counters.Decrement (Value); + end Decrement; + + ---------------------- + -- Unsafe_Increment -- + ---------------------- + + procedure Unsafe_Increment (Value : in out Atomic_Counter) is + begin + Value := Atomic_Counter'Succ (Value); + end Unsafe_Increment; + + ---------------------- + -- Unsafe_Decrement -- + ---------------------- + + function Unsafe_Decrement (Value : in out Atomic_Counter) return Boolean is + begin + Value := Atomic_Counter'Pred (Value); + return Value = 0; + end Unsafe_Decrement; + + -------------------------------- + -- Sync_Bool_Compare_And_Swap -- + -------------------------------- + + function Sync_Bool_Compare_And_Swap + (Ptr : access Element_Access; + Oldval : Element_Access; + Newval : Element_Access) return Boolean + is + function Intrinsic_Sync_Bool_And_Swap_Access + (Ptr : access Element_Access; + Oldval, Newval : Element_Access) return Interfaces.Integer_8; + pragma Import + (Intrinsic, Intrinsic_Sync_Bool_And_Swap_Access, + External_Name => "gnatcoll_sync_bool_compare_and_swap_access"); + begin + return Intrinsic_Sync_Bool_And_Swap_Access (Ptr, Oldval, Newval) /= 0; + end Sync_Bool_Compare_And_Swap; + + ---------------------------------------- + -- Sync_Bool_Compare_And_Swap_Counter -- + ---------------------------------------- + + function Sync_Bool_Compare_And_Swap_Counter + (Ptr : access Atomic_Counter; + Oldval : Atomic_Counter; + Newval : Atomic_Counter) return Boolean is + begin + return Intrinsic_Sync_Bool_Compare_And_Swap (Ptr, Oldval, Newval); + end Sync_Bool_Compare_And_Swap_Counter; + + --------------------------------------- + -- Sync_Val_Compare_And_Swap_Counter -- + --------------------------------------- + + function Sync_Val_Compare_And_Swap_Counter + (Ptr : access Atomic_Counter; + Oldval : Atomic_Counter; + Newval : Atomic_Counter) return Atomic_Counter is + begin + return Intrinsic_Sync_Val_Compare_And_Swap (Ptr, Oldval, Newval); + end Sync_Val_Compare_And_Swap_Counter; + +end GNATCOLL.Atomic; diff -Nru libgnatcoll-18/src/gnatcoll-atomic.ads libgnatcoll-19/src/gnatcoll-atomic.ads --- libgnatcoll-18/src/gnatcoll-atomic.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-atomic.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2010-2017, AdaCore -- +-- Copyright (C) 2010-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -92,6 +92,12 @@ -- 4 (thread 1 has read and incremented, then thread 2) -- If you use the other operations above, you always end up with 4. + function ">" (Left, Right : Atomic_Counter) return Boolean + is (System.Atomic_Counters.">" (Left, Right)); + -- Compare two counters. + -- Note that by the time this function returns, and in a multi threaded + -- application, either of the two counters might have changed. + function "=" (Left, Right : Atomic_Counter) return Boolean renames System.Atomic_Counters."="; diff -Nru libgnatcoll-18/src/gnatcoll-atomic__intrinsic.ada libgnatcoll-19/src/gnatcoll-atomic__intrinsic.ada --- libgnatcoll-18/src/gnatcoll-atomic__intrinsic.ada 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-atomic__intrinsic.ada 1970-01-01 00:00:00.000000000 +0000 @@ -1,183 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2010-2017, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - -with Interfaces; use Interfaces; - -package body GNATCOLL.Atomic is - - function Intrinsic_Sync_Bool_Compare_And_Swap - (Ptr : access Atomic_Counter; - Oldval : Atomic_Counter; - Newval : Atomic_Counter) return Boolean; - pragma Import (Intrinsic, Intrinsic_Sync_Bool_Compare_And_Swap, - External_Name => "__sync_bool_compare_and_swap_4"); - - function Intrinsic_Sync_Val_Compare_And_Swap - (Ptr : access Atomic_Counter; - Oldval : Atomic_Counter; - Newval : Atomic_Counter) return Atomic_Counter; - pragma Import (Intrinsic, Intrinsic_Sync_Val_Compare_And_Swap, - External_Name => "__sync_val_compare_and_swap_4"); - - function Intrinsic_Sync_Add_And_Fetch - (Ptr : access Atomic_Counter; - Value : Atomic_Counter) return Atomic_Counter; - pragma Import (Intrinsic, Intrinsic_Sync_Add_And_Fetch, - External_Name => "__sync_add_and_fetch_4"); - - function Intrinsic_Sync_Sub_And_Fetch - (Ptr : access Atomic_Counter; - Value : Atomic_Counter) return Atomic_Counter; - pragma Import (Intrinsic, Intrinsic_Sync_Sub_And_Fetch, - External_Name => "__sync_sub_and_fetch_4"); - - ------------------ - -- Is_Lock_Free -- - ------------------ - - function Is_Lock_Free return Boolean is (True); - - ------------------------ - -- Sync_Add_And_Fetch -- - ------------------------ - - function Sync_Add_And_Fetch - (Ptr : access Atomic_Counter; - Value : Atomic_Counter) return Atomic_Counter is - begin - return Intrinsic_Sync_Add_And_Fetch (Ptr, Value); - end Sync_Add_And_Fetch; - - procedure Sync_Add_And_Fetch - (Ptr : access Atomic_Counter; Value : Atomic_Counter) - is - Dummy : Atomic_Counter with Unreferenced; - begin - Dummy := Intrinsic_Sync_Add_And_Fetch (Ptr, Value); - end Sync_Add_And_Fetch; - - ------------------------ - -- Sync_Sub_And_Fetch -- - ------------------------ - - function Sync_Sub_And_Fetch - (Ptr : access Atomic_Counter; - Value : Atomic_Counter) return Atomic_Counter is - begin - return Intrinsic_Sync_Sub_And_Fetch (Ptr, Value); - end Sync_Sub_And_Fetch; - - procedure Sync_Sub_And_Fetch - (Ptr : access Atomic_Counter; Value : Atomic_Counter) - is - Dummy : Atomic_Counter with Unreferenced; - begin - Dummy := Intrinsic_Sync_Sub_And_Fetch (Ptr, Value); - end Sync_Sub_And_Fetch; - - --------------- - -- Increment -- - --------------- - - procedure Increment (Value : aliased in out Atomic_Counter) is - begin - System.Atomic_Counters.Increment (Value); - end Increment; - - --------------- - -- Decrement -- - --------------- - - procedure Decrement (Value : aliased in out Atomic_Counter) is - begin - System.Atomic_Counters.Decrement (Value); - end Decrement; - - function Decrement (Value : aliased in out Atomic_Counter) return Boolean is - begin - return System.Atomic_Counters.Decrement (Value); - end Decrement; - - ---------------------- - -- Unsafe_Increment -- - ---------------------- - - procedure Unsafe_Increment (Value : in out Atomic_Counter) is - begin - Value := Atomic_Counter'Succ (Value); - end Unsafe_Increment; - - ---------------------- - -- Unsafe_Decrement -- - ---------------------- - - function Unsafe_Decrement (Value : in out Atomic_Counter) return Boolean is - begin - Value := Atomic_Counter'Pred (Value); - return Value = 0; - end Unsafe_Decrement; - - -------------------------------- - -- Sync_Bool_Compare_And_Swap -- - -------------------------------- - - function Sync_Bool_Compare_And_Swap - (Ptr : access Element_Access; - Oldval : Element_Access; - Newval : Element_Access) return Boolean - is - function Intrinsic_Sync_Bool_And_Swap_Access - (Ptr : access Element_Access; - Oldval, Newval : Element_Access) return Interfaces.Integer_8; - pragma Import - (Intrinsic, Intrinsic_Sync_Bool_And_Swap_Access, - External_Name => "gnatcoll_sync_bool_compare_and_swap_access"); - begin - return Intrinsic_Sync_Bool_And_Swap_Access (Ptr, Oldval, Newval) /= 0; - end Sync_Bool_Compare_And_Swap; - - ---------------------------------------- - -- Sync_Bool_Compare_And_Swap_Counter -- - ---------------------------------------- - - function Sync_Bool_Compare_And_Swap_Counter - (Ptr : access Atomic_Counter; - Oldval : Atomic_Counter; - Newval : Atomic_Counter) return Boolean is - begin - return Intrinsic_Sync_Bool_Compare_And_Swap (Ptr, Oldval, Newval); - end Sync_Bool_Compare_And_Swap_Counter; - - --------------------------------------- - -- Sync_Val_Compare_And_Swap_Counter -- - --------------------------------------- - - function Sync_Val_Compare_And_Swap_Counter - (Ptr : access Atomic_Counter; - Oldval : Atomic_Counter; - Newval : Atomic_Counter) return Atomic_Counter is - begin - return Intrinsic_Sync_Val_Compare_And_Swap (Ptr, Oldval, Newval); - end Sync_Val_Compare_And_Swap_Counter; - -end GNATCOLL.Atomic; diff -Nru libgnatcoll-18/src/gnatcoll-atomic__mutex.ada libgnatcoll-19/src/gnatcoll-atomic__mutex.ada --- libgnatcoll-18/src/gnatcoll-atomic__mutex.ada 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-atomic__mutex.ada 1970-01-01 00:00:00.000000000 +0000 @@ -1,196 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2010-2017, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - -pragma Ada_2012; - -with GNAT.Task_Lock; - -package body GNATCOLL.Atomic is - - ------------------ - -- Is_Lock_Free -- - ------------------ - - function Is_Lock_Free return Boolean is (False); - - ------------------------ - -- Sync_Add_And_Fetch -- - ------------------------ - - function Sync_Add_And_Fetch - (Ptr : access Atomic_Counter; - Value : Atomic_Counter) return Atomic_Counter - is - Result : Atomic_Counter; - begin - GNAT.Task_Lock.Lock; - Ptr.all := Atomic_Counter (Natural (Ptr.all) + Natural (Value)); - Result := Ptr.all; - -- ??? Should use a memory barriere here - GNAT.Task_Lock.Unlock; - return Result; - end Sync_Add_And_Fetch; - - procedure Sync_Add_And_Fetch - (Ptr : access Atomic_Counter; Value : Atomic_Counter) - is - Dummy : Atomic_Counter; - pragma Unreferenced (Dummy); - begin - Dummy := Sync_Add_And_Fetch (Ptr, Value); - end Sync_Add_And_Fetch; - - ------------------------ - -- Sync_Sub_And_Fetch -- - ------------------------ - - function Sync_Sub_And_Fetch - (Ptr : access Atomic_Counter; - Value : Atomic_Counter) return Atomic_Counter - is - Result : Atomic_Counter; - begin - GNAT.Task_Lock.Lock; - Ptr.all := Atomic_Counter (Natural (Ptr.all) - Natural (Value)); - Result := Ptr.all; - -- ??? Should use a memory barriere here - GNAT.Task_Lock.Unlock; - return Result; - end Sync_Sub_And_Fetch; - - procedure Sync_Sub_And_Fetch - (Ptr : access Atomic_Counter; Value : Atomic_Counter) - is - Dummy : Atomic_Counter; - pragma Unreferenced (Dummy); - begin - Dummy := Sync_Sub_And_Fetch (Ptr, Value); - end Sync_Sub_And_Fetch; - - --------------- - -- Increment -- - --------------- - - procedure Increment (Value : aliased in out Atomic_Counter) is - begin - Sync_Add_And_Fetch (Value'Unrestricted_Access, 1); - end Increment; - - --------------- - -- Decrement -- - --------------- - - procedure Decrement (Value : aliased in out Atomic_Counter) is - begin - Sync_Sub_And_Fetch (Value'Unrestricted_Access, 1); - end Decrement; - - function Decrement (Value : aliased in out Atomic_Counter) return Boolean is - begin - return Sync_Sub_And_Fetch (Value'Unrestricted_Access, 1) = 0; - end Decrement; - - ---------------------- - -- Unsafe_Increment -- - ---------------------- - - procedure Unsafe_Increment (Value : in out Atomic_Counter) is - begin - Value := Atomic_Counter (Natural (Value) + 1); - end Unsafe_Increment; - - ---------------------- - -- Unsafe_Decrement -- - ---------------------- - - function Unsafe_Decrement (Value : in out Atomic_Counter) return Boolean is - begin - Value := Atomic_Counter (Natural (Value) - 1); - return Value = 0; - end Unsafe_Decrement; - - -------------------------------- - -- Sync_Bool_Compare_And_Swap -- - -------------------------------- - - function Sync_Bool_Compare_And_Swap - (Ptr : access Element_Access; - Oldval : Element_Access; - Newval : Element_Access) return Boolean is - begin - GNAT.Task_Lock.Lock; - if Ptr.all = Oldval then - Ptr.all := Newval; - GNAT.Task_Lock.Unlock; - return True; - else - GNAT.Task_Lock.Unlock; - return False; - end if; - end Sync_Bool_Compare_And_Swap; - - -------------------------------- - -- Sync_Bool_Compare_And_Swap -- - -------------------------------- - - function Sync_Bool_Compare_And_Swap_Counter - (Ptr : access Atomic_Counter; - Oldval : Atomic_Counter; - Newval : Atomic_Counter) return Boolean - is - begin - GNAT.Task_Lock.Lock; - if Ptr.all = Oldval then - Ptr.all := Newval; - GNAT.Task_Lock.Unlock; - return True; - else - GNAT.Task_Lock.Unlock; - return False; - end if; - end Sync_Bool_Compare_And_Swap_Counter; - - ------------------------------- - -- Sync_Val_Compare_And_Swap -- - ------------------------------- - - function Sync_Val_Compare_And_Swap_Counter - (Ptr : access Atomic_Counter; - Oldval : Atomic_Counter; - Newval : Atomic_Counter) return Atomic_Counter - is - Initial : Atomic_Counter; - begin - GNAT.Task_Lock.Lock; - Initial := Ptr.all; - if Ptr.all = Oldval then - Ptr.all := Newval; - GNAT.Task_Lock.Unlock; - return Initial; - else - GNAT.Task_Lock.Unlock; - return Initial; - end if; - end Sync_Val_Compare_And_Swap_Counter; - -end GNATCOLL.Atomic; diff -Nru libgnatcoll-18/src/gnatcoll-coders.adb libgnatcoll-19/src/gnatcoll-coders.adb --- libgnatcoll-18/src/gnatcoll-coders.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-coders.adb 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,128 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +package body GNATCOLL.Coders is + + ----------- + -- Flush -- + ----------- + + procedure Flush + (Coder : in out Coder_Interface'Class; + Out_Data : out Stream_Element_Array; + Out_Last : out Stream_Element_Offset; + Flush : Flush_Mode) + is + No_Data : constant Stream_Element_Array := (1 .. 0 => 0); + Last : Stream_Element_Offset; + begin + Transcode (Coder, No_Data, Last, Out_Data, Out_Last, Flush); + end Flush; + + ----------- + -- Write -- + ----------- + + procedure Write + (Coder : in out Coder_Interface'Class; + Item : Stream_Element_Array; + Flush : Flush_Mode := No_Flush) + is + Buffer : Stream_Element_Array (1 .. Buffer_Size); + In_Last : Stream_Element_Offset; + Out_Last : Stream_Element_Offset; + In_First : Stream_Element_Offset := Item'First; + begin + if Item'Length = 0 and Flush = No_Flush then + return; + end if; + + loop + Transcode + (Coder => Coder, + In_Data => Item (In_First .. Item'Last), + In_Last => In_Last, + Out_Data => Buffer, + Out_Last => Out_Last, + Flush => Flush); + + if Out_Last >= Buffer'First then + Write (Buffer (1 .. Out_Last)); + end if; + + exit when In_Last = Item'Last or Finished (Coder); + + In_First := In_Last + 1; + end loop; + end Write; + + ---------- + -- Read -- + ---------- + + procedure Read + (Coder : in out Coder_Interface'Class; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset; + Flush : Flush_Mode := No_Flush) + is + In_Last : Stream_Element_Offset; + Item_First : Stream_Element_Offset := Item'First; + V_Flush : Flush_Mode := Flush; + + begin + pragma Assert (Rest_First in Buffer'First .. Buffer'Last + 1); + pragma Assert (Rest_Last in Buffer'First - 1 .. Buffer'Last); + + loop + if Rest_Last = Buffer'First - 1 then + V_Flush := Finish; + + elsif Rest_First > Rest_Last then + Read (Buffer, Rest_Last); + Rest_First := Buffer'First; + + if Rest_Last < Buffer'First then + V_Flush := Finish; + end if; + end if; + + Transcode + (Coder => Coder, + In_Data => Buffer (Rest_First .. Rest_Last), + In_Last => In_Last, + Out_Data => Item (Item_First .. Item'Last), + Out_Last => Last, + Flush => V_Flush); + + Rest_First := In_Last + 1; + + exit when Finished (Coder) + or else Last = Item'Last + or else (Last >= Item'First and then Allow_Read_Some); + + Item_First := Last + 1; + end loop; + end Read; + +end GNATCOLL.Coders; diff -Nru libgnatcoll-18/src/gnatcoll-coders.ads libgnatcoll-19/src/gnatcoll-coders.ads --- libgnatcoll-18/src/gnatcoll-coders.ads 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-coders.ads 2019-05-16 17:44:09.000000000 +0000 @@ -0,0 +1,147 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This package declares the interface for different types of coders, such +-- as compressors/decompressors, encoders/decoders, and any other kind of +-- streaming data transformation. + +with Ada.Streams; use Ada.Streams; + +package GNATCOLL.Coders is + + type Coder_Interface is limited interface; + + type Coder_Access is access all Coder_Interface'Class; + + type Flush_Mode is + (No_Flush, + -- Regular way for coding, no flush + + Sync_Flush, + -- All pending output is flushed to the output buffer and the output + -- is aligned on a byte boundary, so that the decoder can get all + -- input data available so far. (In particular In_Last = In_Data'Last + -- after the call to Transcode if enough output space has been provided + -- before the call). Flushing may degrade compression for some + -- compression algorithms and so it should be used only when necessary. + + Full_Flush, + -- All output is flushed as with Synch_Flush, and the coding state is + -- reset so that decoding can restart from this point if previous + -- compressed data has been damaged or if random access is desired. + -- Using Full_Flush too often can seriously degrade the compression kind + -- of coding. + + Finish); + -- Just to tell the coder that input data is complete + + function Is_Open (Coder : Coder_Interface) return Boolean is abstract; + -- Indicates that coder is ready to transcode data. + -- Initialization procedure has to be implemented in the descendant with + -- parameters appropriate to the transcoding algorithm. + + procedure Transcode + (Coder : in out Coder_Interface; + In_Data : Stream_Element_Array; + In_Last : out Stream_Element_Offset; + Out_Data : out Stream_Element_Array; + Out_Last : out Stream_Element_Offset; + Flush : Flush_Mode) is abstract; + -- Transcodes data from In_Data to Out_Date. + -- In_Last is the index of last element from In_Data accepted by + -- the Coder. + -- Out_Last is the index of the last element written to the Out_Data. + -- To tell the Coder that incoming data is complete, pass Finish as the + -- Flush parameter and call Transcoder with empty In_Data until Finished + -- routine indicates end of stream. + + procedure Flush + (Coder : in out Coder_Interface'Class; + Out_Data : out Stream_Element_Array; + Out_Last : out Stream_Element_Offset; + Flush : Flush_Mode) with Inline; + -- Flushes the data from coder + + function Total_In + (Coder : Coder_Interface) return Stream_Element_Count is abstract; + -- Returns total amount of input data sent into the coder + + function Total_Out + (Coder : Coder_Interface) return Stream_Element_Count is abstract; + -- Returns total amount of output data taken from the coder + + function Finished (Coder : Coder_Interface) return Boolean is abstract; + -- Indicates that incoming data stream finished and all internally + -- processed data is out of coder. + + procedure Close (Coder : in out Coder_Interface) is abstract; + -- Frees all internal coder memory allocations + +private + + -------------------------------------------------------------------------- + -- Generic Read/Write routines helpers to implement streaming interface -- + -------------------------------------------------------------------------- + + generic + with procedure Write (Item : Stream_Element_Array); + -- User should provide this routine to accept transcoded data + + Buffer_Size : Stream_Element_Offset; + -- Buffer size for Write user routine + + procedure Write + (Coder : in out Coder_Interface'Class; + Item : Stream_Element_Array; + Flush : Flush_Mode := No_Flush); + -- Transcodes data from Item and put it to the generic parameter procedure + -- Write. Output buffer size could be set in Buffer_Size generic parameter. + + generic + with procedure Read + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + -- User should provide data to transcode thru this routine + + Buffer : in out Stream_Element_Array; + -- Buffer to keep remaining data from the previous back read + + Rest_First, Rest_Last : in out Stream_Element_Offset; + -- Rest_First have to be initialized to Buffer'Last + 1 + -- Rest_Last have to be initialized to Buffer'Last + -- before usage. + + Allow_Read_Some : Boolean := False; + -- Is it allowed to return Last < Item'Last before end of data + + procedure Read + (Coder : in out Coder_Interface'Class; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset; + Flush : Flush_Mode := No_Flush); + -- Transcodes data from generic parameter procedure Read to the Item. + -- User should provide Buffer and initialized Rest_First, Rest_Last + -- indicators. If Allow_Read_Some is True, Read routines could return + -- Last < Item'Last only at end of stream. + +end GNATCOLL.Coders; diff -Nru libgnatcoll-18/src/gnatcoll-coders-base64.adb libgnatcoll-19/src/gnatcoll-coders-base64.adb --- libgnatcoll-18/src/gnatcoll-coders-base64.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-coders-base64.adb 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,347 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +package body GNATCOLL.Coders.Base64 is + + -- The base64 character set + + Base64 : constant array (Base64_Mode) of aliased Base64_Encode_Array := + (MIME => + ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '+', '/'), + URL => + ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '-', '_')); + + Shift_1_2 : constant array (1 .. 2, 1 .. 2) of Integer := + (1 => (1 => 4, 2 => 4), 2 => (1 => 2, 2 => 6)); + -- Shifts for 1 and 2 states of the decoding + + type Decoder_Array is array (Stream_Element) of Unsigned_8; + + function Make_Decoder return Decoder_Array; + + ------------------ + -- Make_Decoder -- + ------------------ + + function Make_Decoder return Decoder_Array is + begin + return Result : Decoder_Array := (others => Unsigned_8'Last) do + for J in Base64 (MIME)'Range loop + Result (Character'Pos (Base64 (MIME) (J))) := J; + end loop; + + for J in Base64_Encode_Array'Last - 1 .. Base64_Encode_Array'Last loop + Result (Character'Pos (Base64 (URL) (J))) := J; + end loop; + end return; + end Make_Decoder; + + Decoder : constant Decoder_Array := Make_Decoder; + + ---------------- + -- Initialize -- + ---------------- + + procedure Initialize + (Coder : in out Encoder_Type; + Wrap : Natural := 0; + Mode : Base64_Mode := MIME) is + begin + Coder := Encoder_Type'(others => <>); + Coder.To_Char := Base64 (Mode)'Access; + Coder.Align := Mode = MIME; + Coder.Wrap := (if Wrap > 0 then Wrap + 1 else 0); + end Initialize; + + --------------- + -- Transcode -- + --------------- + + overriding procedure Transcode + (Coder : in out Encoder_Type; + In_Data : Stream_Element_Array; + In_Last : out Stream_Element_Offset; + Out_Data : out Stream_Element_Array; + Out_Last : out Stream_Element_Offset; + Flush : Flush_Mode) + is + procedure Append (Item : Unsigned_16) with Inline; + procedure Append (Item : Character); + procedure Append_EOL; + + ------------ + -- Append -- + ------------ + + procedure Append (Item : Character) is + begin + Out_Last := Out_Last + 1; + Out_Data (Out_Last) := Character'Pos (Item); + Coder.Out_Count := Coder.Out_Count + 1; + end Append; + + procedure Append (Item : Unsigned_16) is + begin + Append (Coder.To_Char (Unsigned_8 (Item))); + end Append; + + procedure Append_EOL is + begin + Out_Last := Out_Last + 1; + Out_Data (Out_Last) := Character'Pos (ASCII.LF); + Coder.Lines := Coder.Lines + 1; + end Append_EOL; + + begin + Out_Last := Out_Data'First - 1; + In_Last := In_Data'First - 1; + + while Out_Last < Out_Data'Last loop + if Coder.Wrap > 0 and then Coder.Out_Count > 0 + and then (Coder.Out_Count + Coder.Lines) + rem Stream_Element_Count (Coder.Wrap) = 0 + then + Append_EOL; + + elsif Coder.Left_Bits >= 6 then + Coder.Left_Bits := Coder.Left_Bits - 6; + Append (Shift_Right (Coder.Left, Coder.Left_Bits) and 16#3F#); + + elsif Coder.Finish and then Coder.Left_Bits = 0 then + if not Coder.Align + or else Coder.Out_Count rem 4 not in 2 .. 3 + then + if Coder.Wrap > 0 then + Append_EOL; + Coder.Wrap := 0; + end if; + + exit; + end if; + + Append ('='); + + elsif In_Last = In_Data'Last then + exit when Coder.Finish or else Flush /= Finish; + Coder.Finish := True; + + case Coder.Left_Bits is + when 0 => null; + when 2 => Append (Shift_Left (Coder.Left and 3, 4)); + when 4 => Append (Shift_Left (Coder.Left and 16#F#, 2)); + when others => + raise Program_Error with "invalid Base64 encoder state"; + end case; + + Coder.Left_Bits := 0; + + elsif Coder.Left_Bits < 6 then + In_Last := In_Last + 1; + Coder.Left_Bits := Coder.Left_Bits + 8; + Coder.Left := Shift_Left (Coder.Left, 8) + or Unsigned_16 (In_Data (In_Last)); + end if; + end loop; + end Transcode; + + ------------- + -- Is_Open -- + ------------- + + overriding function Is_Open (Coder : Encoder_Type) return Boolean is + begin + return Coder.To_Char /= null; + end Is_Open; + + -------------- + -- Total_In -- + -------------- + + overriding function Total_In + (Coder : Coder_Type) return Stream_Element_Count is + begin + return Coder.In_Count; + end Total_In; + + --------------- + -- Total_Out -- + --------------- + + overriding function Total_Out + (Coder : Encoder_Type) return Stream_Element_Count is + begin + return Coder.Out_Count + Coder.Lines - 1; + end Total_Out; + + -------------- + -- Finished -- + -------------- + + overriding function Finished (Coder : Encoder_Type) return Boolean is + begin + return Coder.Finish and then Coder.Left_Bits = 0 and then Coder.Wrap = 0 + and then (not Coder.Align or else Coder.Out_Count rem 4 not in 2 .. 3); + end Finished; + + ----------- + -- Close -- + ----------- + + overriding procedure Close (Coder : in out Encoder_Type) is + begin + Coder.To_Char := null; + end Close; + + ---------------- + -- Initialize -- + ---------------- + + procedure Initialize (Coder : in out Decoder_Type) is + begin + Coder := Decoder_Type'(others => <>); + Coder.Open := True; + end Initialize; + + --------------- + -- Transcode -- + --------------- + + overriding procedure Transcode + (Coder : in out Decoder_Type; + In_Data : Stream_Element_Array; + In_Last : out Stream_Element_Offset; + Out_Data : out Stream_Element_Array; + Out_Last : out Stream_Element_Offset; + Flush : Flush_Mode) + is + Bits : Unsigned_8; + State : Integer; + + procedure Append (Item : Unsigned_8); + + ------------ + -- Append -- + ------------ + + procedure Append (Item : Unsigned_8) is + begin + Out_Last := Out_Last + 1; + Out_Data (Out_Last) := Stream_Element (Item); + Coder.Out_Count := Coder.Out_Count + 1; + end Append; + + begin + Out_Last := Out_Data'First - 1; + In_Last := In_Data'First - 1; + + while Out_Last < Out_Data'Last loop + if In_Last = In_Data'Last then + exit when Flush /= Finish or else Coder.Finish; + + Coder.Finish := True; + + if Coder.Has then + Append (Coder.Bits); + Coder.Has := False; + end if; + + exit; + + else + In_Last := In_Last + 1; + Bits := Decoder (In_Data (In_Last)); + end if; + + if Bits /= Unsigned_8'Last then + State := Integer (Coder.In_Count rem 4); + + case State is + when 0 => + Coder.Bits := Shift_Left (Bits, 2); + Coder.Has := True; + + when 1 | 2 => + Append + (Coder.Bits or Shift_Right (Bits, Shift_1_2 (State, 1))); + + Coder.Bits := Shift_Left (Bits, Shift_1_2 (State, 2)); + Coder.Has := False; + + when others => + Append (Coder.Bits or Bits); + Coder.Has := False; + end case; + + Coder.In_Count := Coder.In_Count + 1; + end if; + end loop; + end Transcode; + + ------------- + -- Is_Open -- + ------------- + + overriding function Is_Open (Coder : Decoder_Type) return Boolean is + begin + return Coder.Open; + end Is_Open; + + --------------- + -- Total_Out -- + --------------- + + overriding function Total_Out + (Coder : Decoder_Type) return Stream_Element_Count is + begin + return Coder.Out_Count; + end Total_Out; + + -------------- + -- Finished -- + -------------- + + overriding function Finished (Coder : Decoder_Type) return Boolean is + begin + return Coder.Finish and not Coder.Has; + end Finished; + + ----------- + -- Close -- + ----------- + + overriding procedure Close (Coder : in out Decoder_Type) is + begin + Coder.Open := False; + end Close; + +end GNATCOLL.Coders.Base64; diff -Nru libgnatcoll-18/src/gnatcoll-coders-base64.ads libgnatcoll-19/src/gnatcoll-coders-base64.ads --- libgnatcoll-18/src/gnatcoll-coders-base64.ads 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-coders-base64.ads 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,137 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This package provides Base64 encoding/decoding + +with Interfaces; + +package GNATCOLL.Coders.Base64 is + + type Base64_Mode is (MIME, URL); + -- Base64 encoding variants for encoding routines, + -- RFC4648 + -- MIME - section 4 + -- URL - section 5 + + type Coder_Type is abstract new Coder_Interface with private; + -- Common code and data for base64 encoder/decoder + + overriding function Total_In + (Coder : Coder_Type) return Stream_Element_Count; + -- Returns total amount of input data sent into the coder + + type Encoder_Type is new Coder_Type with private; + -- Base64 encoder + + procedure Initialize + (Coder : in out Encoder_Type; + Wrap : Natural := 0; + Mode : Base64_Mode := MIME); + -- Initialize base64 encoder. + -- Wrap defines line length in encoded output. + -- Mode MIME mean base64 encoding defined in RFC 2045 section 6.8. + -- Mode URL mean base64 encoding defined in RFC 4648 section 4. + + overriding procedure Transcode + (Coder : in out Encoder_Type; + In_Data : Stream_Element_Array; + In_Last : out Stream_Element_Offset; + Out_Data : out Stream_Element_Array; + Out_Last : out Stream_Element_Offset; + Flush : Flush_Mode); + -- Encode data to base64 from In_Data to Out_Date. + -- In_Last is the index of last element from In_Data accepted by + -- the Coder. + -- Out_Last is the index of the last element written to the Out_Data. + + overriding function Is_Open (Coder : Encoder_Type) return Boolean; + -- Indicates that encoder is ready for data processing + + overriding function Total_Out + (Coder : Encoder_Type) return Stream_Element_Count; + -- Returns total amount of output data taken from the coder + + overriding function Finished (Coder : Encoder_Type) return Boolean; + -- Indicates that incoming data stream finished and all internally + -- processed data is out of coder. + + overriding procedure Close (Coder : in out Encoder_Type); + -- Close encoding + + type Decoder_Type is new Coder_Type with private; + -- Base64 decoder + + procedure Initialize (Coder : in out Decoder_Type); + -- Initialize base64 decoder + + overriding procedure Transcode + (Coder : in out Decoder_Type; + In_Data : Stream_Element_Array; + In_Last : out Stream_Element_Offset; + Out_Data : out Stream_Element_Array; + Out_Last : out Stream_Element_Offset; + Flush : Flush_Mode); + -- Decode base64 data from In_Data to Out_Date. + + overriding function Is_Open (Coder : Decoder_Type) return Boolean; + -- Indicates that decoder is ready for data processing + + overriding function Total_Out + (Coder : Decoder_Type) return Stream_Element_Count; + -- Returns total amount of output data taken from the decoder + + overriding function Finished (Coder : Decoder_Type) return Boolean; + -- Indicates that incoming data stream finished and all internally + -- processed data is out of decoder. + + overriding procedure Close (Coder : in out Decoder_Type); + -- Close decoding + +private + + use Interfaces; + + type Base64_Encode_Array is array (Unsigned_8 range 0 .. 63) of Character; + + type Coder_Type is abstract new Coder_Interface with record + In_Count : Stream_Element_Count := 0; + Out_Count : Stream_Element_Count := 0; + Finish : Boolean := False; + end record; + + type Encoder_Type is new Coder_Type with record + To_Char : access constant Base64_Encode_Array; + Lines : Stream_Element_Count := 1; -- Number of lines + Left : Unsigned_16 := 0; + Left_Bits : Integer := 0; + Align : Boolean := False; + Wrap : Natural; + end record; + + type Decoder_Type is new Coder_Type with record + Bits : Unsigned_8 := 0; + Has : Boolean := False; + Open : Boolean := False; + end record; + +end GNATCOLL.Coders.Base64; diff -Nru libgnatcoll-18/src/gnatcoll-coders-streams.adb libgnatcoll-19/src/gnatcoll-coders-streams.adb --- libgnatcoll-18/src/gnatcoll-coders-streams.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-coders-streams.adb 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,235 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +package body GNATCOLL.Coders.Streams is + + ---------- + -- Read -- + ---------- + + overriding procedure Read + (Stream : in out Stream_Type; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) + is + Buffer : constant access Stream_Element_Array := + Stream.Buffer.Reference.Element; + + procedure Read_Stream + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + + ----------------- + -- Read_Stream -- + ----------------- + + procedure Read_Stream + (Item : out Stream_Element_Array; + Last : out Stream_Element_Offset) is + begin + Stream.Read_From.Read (Item, Last); + + if (Stream.Read_Ends = Partial_Read and then Last < Item'Last) + or else (Stream.Read_Ends = Empty_Read and then Last < Item'First) + then + Stream.End_Of_Read := True; + end if; + end Read_Stream; + + procedure Read_Over is new Coders.Read + (Read => Read_Stream, + Buffer => Buffer.all, + Rest_First => Stream.Rest_First, + Rest_Last => Stream.Rest_Last); + + begin + Read_Over + (Stream.Read_Coder.all, Item, Last, + Flush => (if Stream.End_Of_Read then Finish else No_Flush)); + end Read; + + ------------------ + -- End_Of_Input -- + ------------------ + + procedure End_Of_Input (Stream : in out Stream_Type) is + begin + Stream.End_Of_Read := True; + end End_Of_Input; + + function End_Of_Input (Stream : Stream_Type) return Boolean is + begin + return Stream.End_Of_Read; + end End_Of_Input; + + ----------- + -- Write -- + ----------- + + overriding procedure Write + (Stream : in out Stream_Type; Item : Stream_Element_Array) + is + procedure Write_Stream (Item : Stream_Element_Array); + + ----------- + -- Write -- + ----------- + + procedure Write_Stream (Item : Stream_Element_Array) is + begin + Stream.Write_To.Write (Item); + end Write_Stream; + + procedure Write_Over is new Coders.Write + (Write => Write_Stream, Buffer_Size => Stream.Buffer_Size); + + begin + Write_Over (Stream.Write_Coder.all, Item, No_Flush); + end Write; + + ----------- + -- Flush -- + ----------- + + procedure Flush + (Stream : in out Stream_Type; + Mode : Flush_Mode := Sync_Flush) + is + Buffer : Stream_Element_Array (1 .. Stream.Buffer_Size); + Last : Stream_Element_Offset; + begin + loop + Stream.Write_Coder.Flush (Buffer, Last, Mode); + + Stream.Write_To.Write (Buffer (1 .. Last)); + + exit when Last < Buffer'Last; + end loop; + end Flush; + + ---------------- + -- Flush_Read -- + ---------------- + + procedure Flush_Read + (Stream : in out Stream_Type; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset; + Mode : Flush_Mode := Sync_Flush) is + begin + Stream.Read_Coder.Flush (Item, Last, Mode); + end Flush_Read; + + ------------------- + -- Read_Total_In -- + ------------------- + + function Read_Total_In + (Stream : Stream_Type) return Stream_Element_Count is + begin + return (if Stream.Read_Coder = null then 0 + else Stream.Read_Coder.Total_In); + end Read_Total_In; + + -------------------- + -- Read_Total_Out -- + -------------------- + + function Read_Total_Out + (Stream : Stream_Type) return Stream_Element_Count is + begin + return (if Stream.Read_Coder = null then 0 + else Stream.Read_Coder.Total_Out); + end Read_Total_Out; + + -------------------- + -- Write_Total_In -- + -------------------- + + function Write_Total_In + (Stream : Stream_Type) return Stream_Element_Count is + begin + return (if Stream.Write_Coder = null then 0 + else Stream.Write_Coder.Total_In); + end Write_Total_In; + + --------------------- + -- Write_Total_Out -- + --------------------- + + function Write_Total_Out + (Stream : Stream_Type) return Stream_Element_Count is + begin + return (if Stream.Write_Coder = null then 0 + else Stream.Write_Coder.Total_Out); + end Write_Total_Out; + + ---------------- + -- Initialize -- + ---------------- + + procedure Initialize + (Stream : in out Stream_Type; + Read_Coder : access Coder_Interface'Class := null; + Write_Coder : access Coder_Interface'Class := null; + Read_From : access Root_Stream_Type'Class := null; + Write_To : access Root_Stream_Type'Class := null; + Read_Ends_By : End_Of_Input_Method := Empty_Read; + Read_Buffer_Size : Stream_Element_Count := Default_Buffer_Size; + Write_Buffer_Size : Stream_Element_Count := Default_Buffer_Size) + is + begin + if (Read_Coder = null) /= (Read_From = null) then + raise Constraint_Error with + "Read coder and stream have to be either null or not null together"; + end if; + + if (Write_Coder = null) /= (Write_To = null) then + raise Constraint_Error with + "Write coder and stream have to be either null or not null" & + " together"; + end if; + + if Write_To = null and then Read_From = null then + raise Constraint_Error with + "Either write or read coders and streams have to be defined"; + end if; + + Stream.Read_Coder := Read_Coder; + Stream.Write_Coder := Write_Coder; + Stream.Read_From := Read_From; + Stream.Write_To := Write_To; + Stream.Read_Ends := Read_Ends_By; + Stream.End_Of_Read := False; + + if Read_Coder /= null then + Stream.Buffer := SEA_Holders.To_Holder ((1 .. Read_Buffer_Size => 0)); + + Stream.Rest_First := Read_Buffer_Size + 1; + Stream.Rest_Last := Read_Buffer_Size; + end if; + + Stream.Buffer_Size := Write_Buffer_Size; + end Initialize; + +end GNATCOLL.Coders.Streams; diff -Nru libgnatcoll-18/src/gnatcoll-coders-streams.ads libgnatcoll-19/src/gnatcoll-coders-streams.ads --- libgnatcoll-18/src/gnatcoll-coders-streams.ads 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-coders-streams.ads 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,136 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This package provides Ada stream interface to the coders implemented the +-- parent package abstraction Coder_Interface. Example of using this package +-- can be found in examples/base64_coder.adb. + +with Ada.Containers.Indefinite_Holders; + +package GNATCOLL.Coders.Streams is + + type Stream_Type is new Root_Stream_Type with private; + + type Stream_Access is access all Root_Stream_Type'Class; + + type End_Of_Input_Method is (Empty_Read, Partial_Read, Explicit); + -- Method to determine end of Read_From stream (See Initialize parameters + -- below). + -- Empty_Read means that the end of input stream is determined by last + -- read from Read_From stream giving an empty result. + -- Partial_Read means that the end of input stream is determined by last + -- read from Read_From stream giving Partial result (Last < Item'Last). + -- Explicit means that the end of input stream is determined by explicitly + -- calling End_Of_Input. Note that a call to End_Of_Input procedure + -- indicates the end of input in any case, independent of Read_Ends_By + -- parameter of Initialize routine. + + Default_Buffer_Size : constant := 4096; + -- Default buffer size for Read and Write operations. + + overriding procedure Read + (Stream : in out Stream_Type; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset); + + overriding procedure Write + (Stream : in out Stream_Type; Item : Stream_Element_Array); + + procedure Initialize + (Stream : in out Stream_Type; + Read_Coder : access Coder_Interface'Class := null; + Write_Coder : access Coder_Interface'Class := null; + Read_From : access Root_Stream_Type'Class := null; + Write_To : access Root_Stream_Type'Class := null; + Read_Ends_By : End_Of_Input_Method := Empty_Read; + Read_Buffer_Size : Stream_Element_Count := Default_Buffer_Size; + Write_Buffer_Size : Stream_Element_Count := Default_Buffer_Size); + -- Sets read and/or write streams and coders for them. + -- If Read pair is defined then Read operation is available. + -- If Write pair is defined then Write operation is available. + + procedure Flush + (Stream : in out Stream_Type; Mode : Flush_Mode := Sync_Flush); + -- Flushes the written data to the Write_To stream, + -- All data placed to the Write_Coder is flushed to the Write_To stream. + -- Should not be used unless necessary, as it may e.g. degrade the + -- compression quality in case when coder is compressor. + + procedure Flush_Read + (Stream : in out Stream_Type; + Item : out Stream_Element_Array; + Last : out Stream_Element_Offset; + Mode : Flush_Mode := Sync_Flush); + -- Flushes read data from the Read_Coder and returns it in Item and Last + -- out parameters. + + function Read_Total_In + (Stream : Stream_Type) return Stream_Element_Count with Inline; + -- Returns the total number of bytes read from Read_From stream so far + + function Read_Total_Out + (Stream : Stream_Type) return Stream_Element_Count with Inline; + -- Returns the total number of bytes read so far + + function Write_Total_In + (Stream : Stream_Type) return Stream_Element_Count with Inline; + -- Returns the total number of bytes written so far + + function Write_Total_Out + (Stream : Stream_Type) return Stream_Element_Count with Inline; + -- Returns the total number of bytes written to the Write_To stream + + procedure End_Of_Input (Stream : in out Stream_Type); + -- Declares that input data is completed. Read routine is not going to + -- read more data from Read_From stream. + + function End_Of_Input (Stream : Stream_Type) return Boolean; + -- Returns True if data from Read_From stream is finished. + +private + + package SEA_Holders is + new Ada.Containers.Indefinite_Holders (Stream_Element_Array); + + type Stream_Type is new Root_Stream_Type with record + Read_Coder : access Coder_Interface'Class; + Write_Coder : access Coder_Interface'Class; + Read_From : access Root_Stream_Type'Class; + Write_To : access Root_Stream_Type'Class; + Read_Ends : End_Of_Input_Method := Empty_Read; + End_Of_Read : Boolean := False; + + Buffer : SEA_Holders.Holder; + Rest_First : Stream_Element_Offset; + Rest_Last : Stream_Element_Offset; + -- Buffer for Read operation. + -- We need to have this buffer in the record because all read data + -- from Read_From stream may not be processed during the read operation. + + Buffer_Size : Stream_Element_Offset; + -- Buffer size for write operation. + -- We do not need to have this buffer in the record because all data + -- can be processed in the write operation. + end record; + +end GNATCOLL.Coders.Streams; diff -Nru libgnatcoll-18/src/gnatcoll-config.ads libgnatcoll-19/src/gnatcoll-config.ads --- libgnatcoll-18/src/gnatcoll-config.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-config.ads 2019-05-16 17:44:08.000000000 +0000 @@ -34,7 +34,7 @@ -- considered in that order: -- -- 1- comment --- 2- assigment +-- 2- assignment -- 3- section declaration -- -- Thus for example: diff -Nru libgnatcoll-18/src/gnatcoll-email.adb libgnatcoll-19/src/gnatcoll-email.adb --- libgnatcoll-18/src/gnatcoll-email.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-email.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2006-2018, AdaCore -- +-- Copyright (C) 2006-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -88,7 +88,9 @@ function Clone_Headers (Ref : Header_List.List) return Header_List.List; -- Return a deep copy of the given list of headers. - Encoding_Names : constant array (Encoding_Type) of access constant String := + type Constant_String_Access is access constant String; + + Encoding_Names : constant array (Encoding_Type) of Constant_String_Access := (Encoding_7bit => new String'("7bit"), Encoding_8bit => new String'("8bit"), Encoding_Binary => new String'("binary"), @@ -99,7 +101,7 @@ -- "=" -- --------- - function "=" (Addr1, Addr2 : Email_Address) return Boolean is + overriding function "=" (Addr1, Addr2 : Email_Address) return Boolean is begin return To_Lower (To_String (Addr1.Address)) = To_Lower (To_String (Addr2.Address)); @@ -438,7 +440,7 @@ -- Adjust -- ------------ - procedure Adjust (Msg : in out Message) is + overriding procedure Adjust (Msg : in out Message) is begin if Msg.Contents /= null then Msg.Contents.Ref_Count := Msg.Contents.Ref_Count + 1; @@ -449,7 +451,7 @@ -- Finalize -- -------------- - procedure Finalize (Msg : in out Message) is + overriding procedure Finalize (Msg : in out Message) is procedure Unchecked_Free is new Ada.Unchecked_Deallocation (Message_Record, Message_Access); Contents : Message_Access := Msg.Contents; @@ -2169,7 +2171,7 @@ -- Adjust -- ------------ - procedure Adjust (H : in out Header) is + overriding procedure Adjust (H : in out Header) is begin if H.Contents /= null then H.Contents.Ref_Count := H.Contents.Ref_Count + 1; @@ -2180,7 +2182,7 @@ -- Finalize -- -------------- - procedure Finalize (H : in out Header) is + overriding procedure Finalize (H : in out Header) is procedure Unchecked_Free is new Ada.Unchecked_Deallocation (Header_Record, Header_Access); begin diff -Nru libgnatcoll-18/src/gnatcoll-email.ads libgnatcoll-19/src/gnatcoll-email.ads --- libgnatcoll-18/src/gnatcoll-email.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-email.ads 2019-05-16 17:44:08.000000000 +0000 @@ -43,7 +43,7 @@ end record; Null_Charset_String : constant Charset_String; -- This type represents a string and its charset. Contents must be - -- interpreted relatively to Charset, ie characters above 127 must be + -- interpreted relatively to Charset, i.e. characters above 127 must be -- read from that charset. For instance character 161 is an inverted -- exclamation mark in iso-8859-1, but a latin letter A with ogonek in -- iso-8859-2. @@ -155,13 +155,13 @@ -- used for the Content-Type header, to store the file name, or the -- boundary for instance. They appear as: -- Content-Type: text/plain; charset="iso-8859-1" - -- If such a parameter is already set, it is replaced in-place, ie the + -- If such a parameter is already set, it is replaced in-place, i.e. the -- order of parameters is preserved. function Get_Param (H : Header'Class; Param_Name : String) return String; -- Get the value for one of H's parameters, or "" if there is no such -- param. - -- This automatically handles continuation headers, ie cases where the + -- This automatically handles continuation headers, i.e. cases where the -- value of the parameter was split onto several lines, as in: -- filename*0="value1"; -- filename*1="value2" @@ -276,7 +276,7 @@ -- converted to a string. If it returns True, that part is displayed. -- When the filter is unspecified to To_String, all payloads are output. -- This filter only applies in the case of multipart messages, and only to - -- the toplevel attachments (ie if an attachment is itself a message with + -- the toplevel attachments (i.e. if an attachment is itself a message with -- other attachments, the filter will not be applied for these). procedure To_String @@ -314,7 +314,7 @@ -- Set the "From " line used for the envelope of the message function Date_From_Envelope (Msg : Message'Class) return Ada.Calendar.Time; - -- Return the date read in the envelope of the message. It is recommanded + -- Return the date read in the envelope of the message. It is recommended -- that you get the date from the 'Date:' header when available instead. function Sender_From_Envelope (Msg : Message'Class) return String; @@ -541,7 +541,7 @@ procedure Set_Preamble (Msg : in out Message'Class; Preamble : String); -- Set the preamble of the MIME message. - -- This text will be inserted before the first boundary, ie the first + -- This text will be inserted before the first boundary, i.e. the first -- attached file. -- Normally, in MIME aware mailers, this preamble will not be visible. It -- will only be visible by viewing the full text of the message. @@ -558,10 +558,10 @@ Payload : Message; First : Boolean := False); -- Add a new part to a multipart message. Msg is first converted to - -- multipart if necessary. Payload itself is stored in Msg, ie modifying + -- multipart if necessary. Payload itself is stored in Msg, i.e. modifying -- Payload later on will impact Msg. This procedure cannot be used when -- attaching a real mail message, see Attach_Msg instead. - -- If First is True, then add the new part at the begining. Otherwise, + -- If First is True, then add the new part at the beginning. Otherwise, -- add it at the end. procedure Attach_Msg diff -Nru libgnatcoll-18/src/gnatcoll-email-mailboxes.adb libgnatcoll-19/src/gnatcoll-email-mailboxes.adb --- libgnatcoll-18/src/gnatcoll-email-mailboxes.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-email-mailboxes.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2006-2017, AdaCore -- +-- Copyright (C) 2006-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -140,7 +140,7 @@ -- First -- ----------- - function First (Self : Mbox) return Cursor'Class is + overriding function First (Self : Mbox) return Cursor'Class is begin declare Cur : Cursor'Class := Mbox_Cursor' @@ -159,7 +159,7 @@ -- Has_Element -- ----------------- - function Has_Element (Self : Mbox_Cursor) return Boolean is + overriding function Has_Element (Self : Mbox_Cursor) return Boolean is begin return Self.Stop <= Self.Max; end Has_Element; @@ -168,7 +168,7 @@ -- Get_Message -- ----------------- - procedure Get_Message + overriding procedure Get_Message (Self : in out Mbox_Cursor; Box : Mailbox'Class; Msg : out Message) @@ -202,7 +202,7 @@ -- Next -- ---------- - procedure Next + overriding procedure Next (Self : in out Mbox_Cursor; Box : Mailbox'Class) is @@ -310,7 +310,7 @@ -- Finalize -- -------------- - procedure Finalize (Self : in out Mailbox) is + overriding procedure Finalize (Self : in out Mailbox) is pragma Unreferenced (Self); begin null; @@ -320,7 +320,7 @@ -- Finalize -- -------------- - procedure Finalize (Self : in out Mbox) is + overriding procedure Finalize (Self : in out Mbox) is begin if Self.On_Close /= null and then Self.Fp /= null then Self.On_Close (Self.Fp); @@ -381,7 +381,7 @@ -- First -- ----------- - function First (Self : Stored_Mailbox) return Cursor'Class is + overriding function First (Self : Stored_Mailbox) return Cursor'Class is begin return First (Self, Recurse => False); end First; @@ -445,7 +445,7 @@ -- Has_Element -- ----------------- - function Has_Element + overriding function Has_Element (Self : Stored_Mailbox_Cursor) return Boolean is begin @@ -456,7 +456,7 @@ -- Get_Message -- ----------------- - procedure Get_Message + overriding procedure Get_Message (Self : in out Stored_Mailbox_Cursor; Box : Mailbox'Class; Msg : out Message) @@ -489,7 +489,7 @@ -- Next -- ---------- - procedure Next + overriding procedure Next (Self : in out Stored_Mailbox_Cursor; Box : Mailbox'Class) is diff -Nru libgnatcoll-18/src/gnatcoll-email-mailboxes.ads libgnatcoll-19/src/gnatcoll-email-mailboxes.ads --- libgnatcoll-18/src/gnatcoll-email-mailboxes.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-email-mailboxes.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2006-2017, AdaCore -- +-- Copyright (C) 2006-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -257,7 +257,7 @@ -- Cache the current message end record; - procedure Finalize (Self : in out Mailbox); + overriding procedure Finalize (Self : in out Mailbox); pragma Finalize_Storage_Only (Mailbox); type Mbox is new Mailbox with record diff -Nru libgnatcoll-18/src/gnatcoll-email-parser.ads libgnatcoll-19/src/gnatcoll-email-parser.ads --- libgnatcoll-18/src/gnatcoll-email-parser.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-email-parser.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2006-2017, AdaCore -- +-- Copyright (C) 2006-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -42,12 +42,12 @@ -- the message. procedure Parse_No_Payload (Str : String; Msg : out Message); - -- Parse the message, but store its body unparsed (ie nested parts are + -- Parse the message, but store its body unparsed (i.e. nested parts are -- not analyzed). procedure Parse_No_Payload_Minimal_Headers (Str : String; Msg : out Message); - -- Parse the message, but store its body unparsed (ie nested parts are + -- Parse the message, but store its body unparsed (i.e. nested parts are -- not analyzed). Ignore headers that are generally not useful to -- manipulate a message. @@ -71,7 +71,7 @@ -- stored. If Store_Headers is False, no header is stored. -- If Store_Payload is False, then the payload is not analyzed nor parsed, -- simply ignored. When the payload is stored, it can additionally be - -- parsed, ie when it is a multipart message, each of the part is + -- parsed, i.e. when it is a multi-part message, each of the part is -- extracted separately. To save time, they are not MIME-decoded though. procedure Full_Parse_From_File diff -Nru libgnatcoll-18/src/gnatcoll-email-utils.adb libgnatcoll-19/src/gnatcoll-email-utils.adb --- libgnatcoll-18/src/gnatcoll-email-utils.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-email-utils.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2006-2018, AdaCore -- +-- Copyright (C) 2006-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -27,9 +27,10 @@ with Ada.Calendar.Time_Zones; use Ada.Calendar.Time_Zones; with Ada.Calendar.Formatting; use Ada.Calendar.Formatting; with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Streams; with Ada.Strings.Hash_Case_Insensitive; +with GNATCOLL.Coders.Base64; use GNATCOLL.Coders; with GNATCOLL.Utils; use GNATCOLL.Utils; -with Interfaces; use Interfaces; with System.WCh_Con; use System.WCh_Con; with GNAT.Decode_String; @@ -174,34 +175,6 @@ 'a' => 10, 'b' => 11, 'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, others => -1); - type Byte is mod 256; - Base64_Convert : constant array (Character) of Byte := - ('+' => 62, '/' => 63, '0' => 52, '1' => 53, '2' => 54, '3' => 55, - '4' => 56, '5' => 57, '6' => 58, '7' => 59, '8' => 60, '9' => 61, - 'A' => 0, 'B' => 1, 'C' => 2, 'D' => 3, 'E' => 4, 'F' => 5, - 'G' => 6, 'H' => 7, 'I' => 8, 'J' => 9, 'K' => 10, 'L' => 11, - 'M' => 12, 'N' => 13, 'O' => 14, 'P' => 15, 'Q' => 16, 'R' => 17, - 'S' => 18, 'T' => 19, 'U' => 20, 'V' => 21, 'W' => 22, 'X' => 23, - 'Y' => 24, 'Z' => 25, 'a' => 26, 'b' => 27, 'c' => 28, 'd' => 29, - 'e' => 30, 'f' => 31, 'g' => 32, 'h' => 33, 'i' => 34, 'j' => 35, - 'k' => 36, 'l' => 37, 'm' => 38, 'n' => 39, 'o' => 40, 'p' => 41, - 'q' => 42, 'r' => 43, 's' => 44, 't' => 45, 'u' => 46, 'v' => 47, - 'w' => 48, 'x' => 49, 'y' => 50, 'z' => 51, others => -1); - - type Mod64 is mod 2 ** 6; - To_Base64 : constant array (Mod64) of Character := - (00 => 'A', 1 => 'B', 2 => 'C', 3 => 'D', 4 => 'E', 5 => 'F', - 6 => 'G', 7 => 'H', 8 => 'I', 9 => 'J', 10 => 'K', 11 => 'L', - 12 => 'M', 13 => 'N', 14 => 'O', 15 => 'P', 16 => 'Q', 17 => 'R', - 18 => 'S', 19 => 'T', 20 => 'U', 21 => 'V', 22 => 'W', 23 => 'X', - 24 => 'Y', 25 => 'Z', 26 => 'a', 27 => 'b', 28 => 'c', 29 => 'd', - 30 => 'e', 31 => 'f', 32 => 'g', 33 => 'h', 34 => 'i', 35 => 'j', - 36 => 'k', 37 => 'l', 38 => 'm', 39 => 'n', 40 => 'o', 41 => 'p', - 42 => 'q', 43 => 'r', 44 => 's', 45 => 't', 46 => 'u', 47 => 'v', - 48 => 'w', 49 => 'x', 50 => 'y', 51 => 'z', 52 => '0', 53 => '1', - 54 => '2', 55 => '3', 56 => '4', 57 => '5', 58 => '6', 59 => '7', - 60 => '8', 61 => '9', 62 => '+', 63 => '/'); - Hex_Chars : constant array (0 .. 15) of Character := "0123456789ABCDEF"; ------------------------ @@ -1513,162 +1486,92 @@ Where : Region := Text; Result : out Unbounded_String) is - Block_Prefix : constant String := - (if Where in Any_Header then "=?" & Charset & "?b?" else ""); - Block_Suffix : constant String := - (if Where in Any_Header then "?=" else ""); - Block_Separator : constant String := - (if Where in Any_Header then " " else (1 => ASCII.LF)); - -- In Text, use a soft line break as line separator + procedure Put_Parts (Part : String); - Max : constant Natural := - 4 * Integer'Max - (1, - (Integer'Min (Max_Block_Len, - (if Where in Any_Header then 75 else 76)) - - Block_Prefix'Length - - Block_Suffix'Length) / 4); - -- Maximum length of encoded data within an encoded block (must be - -- a non-null multiple of 4). Note: block separator does not contain - -- any printable character, so does not count against the limit. - - Encoded_Len : constant Integer := (Str'Length + 2) / 3 * 4; - -- Each group of 3 input bytes yields 4 output bytes, including a - -- trailing incomplete group. - - Blocks : constant Integer := (Encoded_Len + Max - 1) / Max; - - Encoded_Block_Len : constant Integer := - Block_Prefix'Length + Max + Block_Suffix'Length - + Block_Separator'Length; - -- Allocation size for each block - - Len : constant Integer := - Blocks * Encoded_Block_Len; - -- Pre-allocation length. This is sufficient to accomodate the entire - -- encoded data, split into blocks, except if some blocks need to be - -- flushed early (while incomplete) in order to avoid incorrect - -- splitting of multi-byte sequences. - - Output : Ada.Strings.Unbounded.String_Access := new String (1 .. Len); - Index : Integer := Output'First; - Left : Unsigned_16 := 0; - Leftbits : Natural := 0; - Ch : Mod64; - Current : Integer := 0; + procedure Put_Parts (Part : String) is + begin + Append (Result, Part); + end Put_Parts; - procedure Append (Ch : Character); - -- Append a new character to the output, splitting lines as necessary + begin + Result := Null_Unbounded_String; + Base64_Encode (Str, Charset, Max_Block_Len, Where, Put_Parts'Access); + end Base64_Encode; - ------------ - -- Append -- - ------------ + procedure Base64_Encode + (Str : String; + Charset : String; + Max_Block_Len : Integer := Integer'Last; + Where : Region := Text; + Put_Parts : not null access procedure (Part : String)) + is + use Ada.Streams; - procedure Append (Ch : Character) is - New_Output : Ada.Strings.Unbounded.String_Access; - begin - if Current = 0 then - -- Make sure that the string has sufficient space for the - -- full new encoded block - - if Output'Last - Index + 1 < Encoded_Block_Len then - New_Output := - new String (1 .. Output'Length + Encoded_Block_Len); - New_Output (1 .. Index - 1) := Output (1 .. Index - 1); - Free (Output); - Output := New_Output; - end if; + Block_Prefix : constant String := "=?" & Charset & "?b?"; + Block_Suffix : constant String := "?="; + Block_Separator : constant String := " "; + + In_Bytes : Stream_Element_Array (Stream_Element_Offset (Str'First) + .. Stream_Element_Offset (Str'Last)) + with Import; + for In_Bytes'Address use Str'Address; - Output (Index .. Index + Block_Prefix'Length - 1) := - Block_Prefix; - Index := Index + Block_Prefix'Length; - end if; - - Output (Index) := Ch; - Index := Index + 1; - Current := Current + 1; - - if Current = Max then - -- Append suffix and separator - Output (Index .. Index - + Block_Suffix'Length - + Block_Separator'Length - 1) := - Block_Suffix & Block_Separator; - Index := Index + Block_Suffix'Length + Block_Separator'Length; + Max : constant Natural := + Integer'Max + (1, + (Integer'Min (Max_Block_Len, 75) + - Block_Prefix'Length - Block_Suffix'Length) / 4) * 3; + -- Length of the original data producing output of Max_Block_Len. + -- Divide by 4 and multiply by 3 because base64 encoder takes 3 + -- original bytes (i.e. 24 bits) and produces 4 6-bit-coded characters. + -- Another effect of length adjustment by 3/4 is that most of the blocks + -- in headers are not going to be aligned by '=' character. + -- Note: block separator does not contain any printable character, so + -- does not count against the limit. - Current := 0; - end if; - end Append; + Coder : Base64.Encoder_Type; - procedure Encode_Append (Str : String); + procedure Encode_Append + (First, Last : Stream_Element_Offset; Last_One : Boolean); -- Encode Str and append result to output, splitting if necessary. -- If Where is Any_Header, then never split Str across two different -- blocks. - procedure Flush; - -- Flush pending bits, outputting padding characters if necessary - - procedure Encode_Append (Str : String) is - Out_Chars : constant Integer := (Leftbits + Str'Length * 8 + 5) / 6; + ------------------- + -- Encode_Append -- + ------------------- + + procedure Encode_Append + (First, Last : Stream_Element_Offset; Last_One : Boolean) + is + In_Last : Stream_Element_Offset; + Out_Last : Stream_Element_Offset; + Out_Chars : String (1 .. (Str'Length + 2) * 4 / 3); + Out_Bytes : Stream_Element_Array (1 .. Out_Chars'Length) with Import; + for Out_Bytes'Address use Out_Chars'Address; begin - -- Force flushing now if in header mode and encoded sequence would - -- exceed maximum length. + Put_Parts (Block_Prefix); - if Where in Any_Header and then Current + Out_Chars > Max then - Flush; - end if; + Coder.Initialize; - for J in Str'Range loop - Left := Shift_Left (Left, 8) or Character'Pos (Str (J)); - Leftbits := Leftbits + 8; - - while Leftbits >= 6 loop - Ch := - Mod64 ((Shift_Right (Left, Leftbits - 6)) and 16#3f#); - Leftbits := Leftbits - 6; - Append (To_Base64 (Ch)); - end loop; - end loop; - end Encode_Append; + Coder.Transcode + (In_Bytes (First .. Last), In_Last, Out_Bytes, Out_Last, Finish); - ----------- - -- Flush -- - ----------- + Coder.Close; - procedure Flush is - begin - case Leftbits is - when 0 => - null; - - when 2 => - Ch := Mod64 (Shift_Left (Left and 3, 4)); - Append (To_Base64 (Ch)); - Append ('='); - Append ('='); - - when 4 => - Ch := Mod64 (Shift_Left (Left and 16#F#, 2)); - Append (To_Base64 (Ch)); - Append ('='); - - when others => - raise Program_Error with "invalid Base64 encoder state"; - end case; - - Left := 0; - Leftbits := 0; - end Flush; + Put_Parts + (Out_Chars (1 .. Natural (Out_Last)) & Block_Suffix + & (if Last_One then "" else Block_Separator)); + end Encode_Append; - Start, Next : Integer; + Start, Next, Fit : Integer; -- Start of current encoded sequence, -- start of next encoded sequence, -- last element of previous encoded sequence. - Next_Char : constant Next_Char_Acc := - (if Where in Any_Header - then Next_Char_For_Charset (Charset) - else Single_Byte_Next_Char'Access); + Index : Stream_Element_Offset := In_Bytes'First; + + Next_Char : constant Next_Char_Acc := Next_Char_For_Charset (Charset); -- In message bodies, multi-byte encodings can be -- split across multiple lines; in headers, they can't -- be split across multiple encoded words. @@ -1676,36 +1579,59 @@ -- Start of processing for Base64_Encode begin - Next := Str'First; - loop - Start := Next; - exit when Start > Str'Last; + Fit := Str'First; - -- Find end of possibly multibyte sequence starting at Start + if Where in Any_Header then + while Fit <= Str'Last loop + Start := Fit; + Next := Fit; - Next := Start; - Next_Char_Ignore_Invalid (Next_Char, Str, Next); + while Next - Start <= Max loop + Fit := Next; - Encode_Append (Str (Start .. Next - 1)); - end loop; - Flush; + exit when Fit > Str'Last; - if Current = 0 then - -- Remove last separator - Index := Index - Block_Separator'Length; - elsif Current > 0 then - Output (Index .. Index + Block_Suffix'Length - 1) := - Block_Suffix; - Index := Index + Block_Suffix'Length; - end if; + Next_Char_Ignore_Invalid (Next_Char, Str, Next); + end loop; + + Encode_Append + (First => Stream_Element_Offset (Start), + Last => Stream_Element_Offset (Fit - 1), + Last_One => Fit > Str'Last); + end loop; - if Output'Last /= Index - 1 then - Set_Unbounded_String (Result, Output (1 .. Index - 1)); else - Set_Unbounded_String (Result, Output.all); - end if; + Coder.Initialize; + + loop + declare + Out_Last : Stream_Element_Offset; + Text : String (1 .. Integer'Min (Max_Block_Len, 76)); + Buffer : Stream_Element_Array (1 .. Text'Length) with Import; + for Buffer'Address use Text'Address; + Flush : constant Flush_Mode := + (if Index > In_Bytes'Last - Text'Length * 3 / 4 + 1 + then Finish else No_Flush); + First : constant Boolean := Index = In_Bytes'First; + begin + Coder.Transcode + (In_Bytes (Index .. In_Bytes'Last), Index, Buffer, Out_Last, + Flush => Flush); + + if 1 <= Out_Last then + Put_Parts + ((if First then "" else (1 => ASCII.LF)) + & Text (1 .. Natural (Out_Last))); + end if; - Free (Output); + exit when Flush = Finish; + + Index := Index + 1; + end; + end loop; + + Coder.Close; + end if; end Base64_Encode; ------------------- @@ -1716,61 +1642,39 @@ (Str : String; Result : out Unbounded_String) is - type Phase_Type is mod 4; - -- We must use the heap rather than the stack here. In some - -- cases, we'll be able to avoid a copy of the string anyway, - -- and in case where this code is run in a multi-threaded - -- application, the stack size is generally too small anyway - Output : Ada.Strings.Unbounded.String_Access := - new String (1 .. Str'Length * 6 / 8); - Index : Integer := Output'First; - - Phase : Phase_Type := 0; - D, Dlast : Byte := 0; - - begin - for S in Str'First .. Str'Last loop - if Str (S) = ASCII.LF - or else Str (S) = ASCII.CR - then - Phase := 0; - Dlast := 0; - - else - D := Base64_Convert (Str (S)); - if D /= -1 then - case Phase is - when 0 => - Phase := Phase + 1; - when 1 => - Output (Index) := Character'Val - (Dlast * 4 or ((D and 16#30#) / 16)); - Index := Index + 1; - Phase := Phase + 1; - when 2 => - Output (Index) := Character'Val - (((Dlast and 16#F#) * 16) or ((D and 16#3C#) / 4)); - Index := Index + 1; - Phase := Phase + 1; - when 3 => - Output (Index) := Character'Val - (((Dlast and 16#3#) * 64) or D); - Index := Index + 1; - Phase := 0; - end case; + use Ada.Streams; + Decoder : Base64.Decoder_Type; + Src : Stream_Element_Array (1 .. Str'Length) with Import; + for Src'Address use Str'Address; + Index : Stream_Element_Offset := Src'First; + Dest : Stream_Element_Array (1 .. 4096); + Last : Stream_Element_Offset; + Text : String (1 .. Dest'Length); + for Text'Address use Dest'Address; + Flush : Flush_Mode := No_Flush; + begin + Decoder.Initialize; + Result := Null_Unbounded_String; - Dlast := D; - end if; + while Index <= Src'Last loop + if Index > Src'Last - Dest'Length then + Flush := Finish; end if; - end loop; - if Index - 1 = Output'Last then - Set_Unbounded_String (Result, Output.all); - else - Set_Unbounded_String (Result, Output (Output'First .. Index - 1)); - end if; + Decoder.Transcode + (In_Data => Src (Index .. Src'Last), + In_Last => Index, + Out_Data => Dest, + Out_Last => Last, + Flush => Flush); + + Append (Result, Text (1 .. Integer (Last))); + exit when Flush = Finish; + + Index := Index + 1; + end loop; - Free (Output); + Decoder.Close; end Base64_Decode; ------------ diff -Nru libgnatcoll-18/src/gnatcoll-email-utils.ads libgnatcoll-19/src/gnatcoll-email-utils.ads --- libgnatcoll-18/src/gnatcoll-email-utils.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-email-utils.ads 2019-05-16 17:44:08.000000000 +0000 @@ -59,7 +59,7 @@ Show_Time : Boolean := True; Show_Seconds : Boolean := True; Show_Day : Boolean := True) return String; - -- Format the date as a RFC 2822 string, eg: + -- Format the date as a RFC 2822 string, e.g.: -- Fri, 09 Nov 2001 01:08:47 -0000 -- If Use_GMT is true, the time stamp is rendered in UTC, and the time zone @@ -123,7 +123,7 @@ -- addresses of Separator has its default value. -- If Address_Only is true, then the real names are never shown in the -- string. - -- Charset is passed to Format_Address to format indivudual addresses. + -- Charset is passed to Format_Address to format individual addresses. function Get_Recipients (Msg : Message'Class; Include_From : Boolean := False) @@ -164,7 +164,7 @@ function Login_From_Address (Email : String) return String; function Login_From_Address (Email : Email_Address) return String; - -- Return the login name from the given email address, ie the part before + -- Return the login name from the given email address, i.e. the part before -- the '@'. In the first case, Email must only contain the address, not the -- real name. @@ -191,8 +191,8 @@ Where : Region := Text; Result : out Unbounded_String); -- Encode Str in quoted-printable format, as per RFC 2045/2047. - -- This should be used for ascii-like charsets, like all iso-8859-* - -- charsets, ie when most of the characters are already in the ASCII + -- This should be used for ASCII-like charsets, like all ISO-8859-* + -- charsets, i.e. when most of the characters are already in the ASCII -- charset (0 through 127). procedure Quoted_Printable_Decode @@ -201,7 +201,7 @@ Where : Region := Text); -- Decode Str as a quoted-printable encoded string as per RFC 2045. -- The returned value may contain non - ASCII characters, their - -- interpretation is left to the called (ie the charset is unknown). + -- interpretation is left to the called (i.e. the charset is unknown). -- If the optional argument header is present and true, underscore will be -- decoded as space. This is used to decode "Q" encoded headers as -- described in RFC 2047: "MIME (Multipurpose Internet Mail Extensions) @@ -215,7 +215,16 @@ Result : out Unbounded_String); -- Encode Str in base64 format, as defined by RFC 2045. -- This should be used for charsets that have little similarity with - -- ASCII, for instance asian charsets. + -- ASCII, for instance Asian charsets. + + procedure Base64_Encode + (Str : String; + Charset : String; + Max_Block_Len : Integer := Integer'Last; + Where : Region := Text; + Put_Parts : not null access procedure (Part : String)); + -- Encode Str in base64 format like above but returning result part by part + -- over Put_Parts routine to be able to use another kind of output. procedure Base64_Decode (Str : String; diff -Nru libgnatcoll-18/src/gnatcoll-formatters.ads libgnatcoll-19/src/gnatcoll-formatters.ads --- libgnatcoll-18/src/gnatcoll-formatters.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-formatters.ads 2019-05-16 17:44:08.000000000 +0000 @@ -57,7 +57,7 @@ -- Width is the width limit of the output. -- Put_Line is the callback routine to take output line by line. -- Pad is the character filling the space after words to have same size in - -- column for next column to be alligned. + -- column for next column to be aligned. -- Delimiter is string delimiting the columns. generic diff -Nru libgnatcoll-18/src/gnatcoll-geometry.ads libgnatcoll-19/src/gnatcoll-geometry.ads --- libgnatcoll-18/src/gnatcoll-geometry.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-geometry.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2010-2017, AdaCore -- +-- Copyright (C) 2010-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -21,7 +21,7 @@ -- -- ------------------------------------------------------------------------------ --- A set of planar geometric utilites (intersections of segments, etc). +-- A set of planar geometric utilities (intersections of segments, etc). with Ada.Numerics.Generic_Elementary_Functions; diff -Nru libgnatcoll-18/src/gnatcoll-io.ads libgnatcoll-19/src/gnatcoll-io.ads --- libgnatcoll-18/src/gnatcoll-io.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-io.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -22,6 +22,8 @@ ------------------------------------------------------------------------------ with Ada.Calendar; +with Ada.Strings.Unbounded; + with GNAT.OS_Lib; with GNAT.Strings; with GNATCOLL.Strings; use GNATCOLL.Strings; @@ -174,7 +176,8 @@ procedure Open_Write (File : not null access File_Record; Append : Boolean := False; - FD : out GNAT.OS_Lib.File_Descriptor) is abstract; + FD : out GNAT.OS_Lib.File_Descriptor; + Error : out Ada.Strings.Unbounded.Unbounded_String) is abstract; -- Opens a file for writing. Return a file descriptor used to actually -- write. -- /!\ Do not call close directly on FD, but use the method below instead. diff -Nru libgnatcoll-18/src/gnatcoll-io-native.adb libgnatcoll-19/src/gnatcoll-io-native.adb --- libgnatcoll-18/src/gnatcoll-io-native.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-io-native.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -21,9 +21,10 @@ -- -- ------------------------------------------------------------------------------ -with System; -with Ada.Unchecked_Deallocation; with Ada.Directories; +with Ada.Exceptions; +with Ada.Unchecked_Deallocation; +with System; with Ada.Calendar.Formatting; use Ada.Calendar; with Ada.Calendar.Time_Zones; use Ada.Calendar.Time_Zones; @@ -60,7 +61,7 @@ -- Dispatching_Create -- ------------------------ - function Dispatching_Create + overriding function Dispatching_Create (Ref : not null access Native_File_Record; Full_Path : FS_String) return File_Access is @@ -73,7 +74,7 @@ -- To_UTF8 -- ------------- - function To_UTF8 + overriding function To_UTF8 (Ref : not null access Native_File_Record; Path : FS_String) return String is @@ -86,7 +87,7 @@ -- From_UTF8 -- --------------- - function From_UTF8 + overriding function From_UTF8 (Ref : not null access Native_File_Record; Path : String) return FS_String is @@ -235,7 +236,7 @@ -- Is_Local -- -------------- - function Is_Local (File : Native_File_Record) return Boolean is + overriding function Is_Local (File : Native_File_Record) return Boolean is pragma Unreferenced (File); begin return True; @@ -245,7 +246,7 @@ -- Get_FS -- ------------ - function Get_FS + overriding function Get_FS (File : not null access Native_File_Record) return FS_Type is pragma Unreferenced (File); @@ -257,7 +258,7 @@ -- Resolve_Symlinks -- ---------------------- - procedure Resolve_Symlinks + overriding procedure Resolve_Symlinks (File : not null access Native_File_Record) is Is_Dir_Path : Boolean; @@ -309,7 +310,7 @@ -- Is_Regular_File -- --------------------- - function Is_Regular_File + overriding function Is_Regular_File (File : not null access Native_File_Record) return Boolean is begin return GNAT.OS_Lib.Is_Regular_File (String (File.Full.all)); @@ -319,7 +320,7 @@ -- Size -- ---------- - function Size + overriding function Size (File : not null access Native_File_Record) return Long_Integer is Fd : constant GNAT.OS_Lib.File_Descriptor := GNAT.OS_Lib.Open_Read @@ -337,7 +338,7 @@ -- Is_Directory -- ------------------ - function Is_Directory + overriding function Is_Directory (File : not null access Native_File_Record) return Boolean is begin if GNAT.OS_Lib.Directory_Separator = '\' @@ -369,7 +370,7 @@ -- Is_Symbolic_Link -- ---------------------- - function Is_Symbolic_Link + overriding function Is_Symbolic_Link (File : not null access Native_File_Record) return Boolean is begin return GNAT.OS_Lib.Is_Symbolic_Link (String (File.Full.all)); @@ -383,7 +384,7 @@ -- Time zone cache, assuming that the OS will not change time zones while -- this partition is running. - function File_Time_Stamp + overriding function File_Time_Stamp (File : not null access Native_File_Record) return Ada.Calendar.Time is T : constant GNAT.OS_Lib.OS_Time := @@ -418,7 +419,7 @@ -- Is_Readable -- ----------------- - function Is_Readable + overriding function Is_Readable (File : not null access Native_File_Record) return Boolean is begin return GNAT.OS_Lib.Is_Readable_File (String (File.Full.all)); @@ -428,7 +429,7 @@ -- Is_Writable -- ----------------- - function Is_Writable + overriding function Is_Writable (File : not null access Native_File_Record) return Boolean is begin return GNAT.OS_Lib.Is_Writable_File (String (File.Full.all)); @@ -438,7 +439,7 @@ -- Set_Writable -- ------------------ - procedure Set_Writable + overriding procedure Set_Writable (File : not null access Native_File_Record; State : Boolean) is @@ -456,7 +457,7 @@ -- Set_Readable -- ------------------ - procedure Set_Readable + overriding procedure Set_Readable (File : not null access Native_File_Record; State : Boolean) is @@ -474,7 +475,7 @@ -- Rename -- ------------ - procedure Rename + overriding procedure Rename (From : not null access Native_File_Record; Dest : not null access Native_File_Record; Success : out Boolean) @@ -492,7 +493,7 @@ -- Copy -- ---------- - procedure Copy + overriding procedure Copy (From : not null access Native_File_Record; Dest : FS_String; Success : out Boolean) @@ -511,7 +512,7 @@ -- Delete -- ------------ - procedure Delete + overriding procedure Delete (File : not null access Native_File_Record; Success : out Boolean) is @@ -523,7 +524,7 @@ -- Read_Whole_File -- --------------------- - function Read_Whole_File + overriding function Read_Whole_File (File : not null access Native_File_Record) return GNAT.Strings.String_Access is @@ -539,7 +540,7 @@ -- Read_Whole_File -- --------------------- - function Read_Whole_File + overriding function Read_Whole_File (File : not null access Native_File_Record) return GNATCOLL.Strings.XString is @@ -555,34 +556,53 @@ -- Open_Write -- ---------------- - procedure Open_Write + overriding procedure Open_Write (File : not null access Native_File_Record; Append : Boolean := False; - FD : out GNAT.OS_Lib.File_Descriptor) + FD : out GNAT.OS_Lib.File_Descriptor; + Error : out Ada.Strings.Unbounded.Unbounded_String) is + use type GNAT.OS_Lib.File_Descriptor; + begin if Append then FD := GNAT.OS_Lib.Open_Read_Write (String (File.Full.all), Fmode => GNAT.OS_Lib.Binary); - GNAT.OS_Lib.Lseek - (FD, 0, GNAT.OS_Lib.Seek_End); else FD := GNAT.OS_Lib.Create_File (String (File.Full.all), Fmode => GNAT.OS_Lib.Binary); end if; + if FD = GNAT.OS_Lib.Invalid_FD then + Error := + Ada.Strings.Unbounded.To_Unbounded_String + (GNAT.OS_Lib.Errno_Message); + + else + Error := Ada.Strings.Unbounded.Null_Unbounded_String; + end if; + + if Append then + GNAT.OS_Lib.Lseek (FD, 0, GNAT.OS_Lib.Seek_End); + -- It is impossible to obtain return value of lseek to check for + -- errors. + end if; + exception - when others => - FD := GNAT.OS_Lib.Invalid_FD; + when E : others => + FD := GNAT.OS_Lib.Invalid_FD; + Error := + Ada.Strings.Unbounded.To_Unbounded_String + (Ada.Exceptions.Exception_Information (E)); end Open_Write; ----------- -- Close -- ----------- - procedure Close + overriding procedure Close (File : not null access Native_File_Record; FD : GNAT.OS_Lib.File_Descriptor; Success : out Boolean) @@ -602,7 +622,7 @@ -- Change_Dir -- ---------------- - function Change_Dir + overriding function Change_Dir (Dir : not null access Native_File_Record) return Boolean is @@ -619,7 +639,7 @@ -- Read_Dir -- -------------- - function Read_Dir + overriding function Read_Dir (Dir : not null access Native_File_Record; Dirs_Only : Boolean := False; Files_Only : Boolean := False) return GNAT.Strings.String_List @@ -687,7 +707,7 @@ -- Make_Dir -- -------------- - function Make_Dir + overriding function Make_Dir (Dir : not null access Native_File_Record; Recursive : Boolean) return Boolean is begin @@ -708,7 +728,7 @@ -- Remove_Dir -- ---------------- - procedure Remove_Dir + overriding procedure Remove_Dir (Dir : not null access Native_File_Record; Recursive : Boolean; Success : out Boolean) @@ -726,7 +746,7 @@ -- Copy_Dir -- -------------- - procedure Copy_Dir + overriding procedure Copy_Dir (From : not null access Native_File_Record; Dest : FS_String; Success : out Boolean) diff -Nru libgnatcoll-18/src/gnatcoll-io-native.ads libgnatcoll-19/src/gnatcoll-io-native.ads --- libgnatcoll-18/src/gnatcoll-io-native.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-io-native.ads 2019-05-16 17:44:09.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -70,7 +70,7 @@ (File : not null access Native_File_Record); overriding function Is_Regular_File (File : not null access Native_File_Record) return Boolean; - function Size + overriding function Size (File : not null access Native_File_Record) return Long_Integer; overriding function Is_Directory (File : not null access Native_File_Record) return Boolean; @@ -108,7 +108,8 @@ overriding procedure Open_Write (File : not null access Native_File_Record; Append : Boolean := False; - FD : out GNAT.OS_Lib.File_Descriptor); + FD : out GNAT.OS_Lib.File_Descriptor; + Error : out Ada.Strings.Unbounded.Unbounded_String); overriding procedure Close (File : not null access Native_File_Record; FD : GNAT.OS_Lib.File_Descriptor; diff -Nru libgnatcoll-18/src/gnatcoll-io-remote.adb libgnatcoll-19/src/gnatcoll-io-remote.adb --- libgnatcoll-18/src/gnatcoll-io-remote.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-io-remote.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -340,7 +340,7 @@ -- Dispatching_Create -- ------------------------ - function Dispatching_Create + overriding function Dispatching_Create (Ref : not null access Remote_File_Record; Full_Path : FS_String) return File_Access is @@ -352,7 +352,7 @@ -- To_UTF8 -- ------------- - function To_UTF8 + overriding function To_UTF8 (Ref : not null access Remote_File_Record; Path : FS_String) return String is @@ -365,7 +365,7 @@ -- From_UTF8 -- --------------- - function From_UTF8 + overriding function From_UTF8 (Ref : not null access Remote_File_Record; Path : String) return FS_String is @@ -378,7 +378,7 @@ -- Is_Local -- -------------- - function Is_Local (File : Remote_File_Record) return Boolean is + overriding function Is_Local (File : Remote_File_Record) return Boolean is pragma Unreferenced (File); begin return False; @@ -388,7 +388,7 @@ -- Get_FS -- ------------ - function Get_FS + overriding function Get_FS (File : not null access Remote_File_Record) return FS_Type is begin @@ -401,7 +401,7 @@ -- Resolve_Symlinks -- ---------------------- - procedure Resolve_Symlinks + overriding procedure Resolve_Symlinks (File : not null access Remote_File_Record) is begin @@ -421,7 +421,7 @@ -- Is_Regular_File -- --------------------- - function Is_Regular_File + overriding function Is_Regular_File (File : not null access Remote_File_Record) return Boolean is begin @@ -466,7 +466,7 @@ -- Is_Directory -- ------------------ - function Is_Directory + overriding function Is_Directory (File : not null access Remote_File_Record) return Boolean is begin @@ -489,7 +489,7 @@ -- Is_Symbolic_Link -- ---------------------- - function Is_Symbolic_Link + overriding function Is_Symbolic_Link (File : not null access Remote_File_Record) return Boolean is begin @@ -512,7 +512,7 @@ -- File_Time_Stamp -- --------------------- - function File_Time_Stamp + overriding function File_Time_Stamp (File : not null access Remote_File_Record) return Ada.Calendar.Time is begin @@ -557,7 +557,7 @@ -- Is_Writable -- ----------------- - function Is_Writable + overriding function Is_Writable (File : not null access Remote_File_Record) return Boolean is begin Ensure_Initialized (File); @@ -579,7 +579,7 @@ -- Set_Writable -- ------------------ - procedure Set_Writable + overriding procedure Set_Writable (File : not null access Remote_File_Record; State : Boolean) is @@ -605,7 +605,7 @@ -- Set_Readable -- ------------------ - procedure Set_Readable + overriding procedure Set_Readable (File : not null access Remote_File_Record; State : Boolean) is @@ -631,7 +631,7 @@ -- Rename -- ------------ - procedure Rename + overriding procedure Rename (From : not null access Remote_File_Record; Dest : not null access Remote_File_Record; Success : out Boolean) @@ -662,7 +662,7 @@ -- Copy -- ---------- - procedure Copy + overriding procedure Copy (From : not null access Remote_File_Record; Dest : FS_String; Success : out Boolean) @@ -687,7 +687,7 @@ -- Delete -- ------------ - procedure Delete + overriding procedure Delete (File : not null access Remote_File_Record; Success : out Boolean) is @@ -713,7 +713,7 @@ -- Read_Whole_File -- --------------------- - function Read_Whole_File + overriding function Read_Whole_File (File : not null access Remote_File_Record) return GNAT.Strings.String_Access is @@ -737,7 +737,7 @@ -- Read_Whole_File -- --------------------- - function Read_Whole_File + overriding function Read_Whole_File (File : not null access Remote_File_Record) return GNATCOLL.Strings.XString is @@ -761,11 +761,15 @@ -- Open_Write -- ---------------- - procedure Open_Write + overriding procedure Open_Write (File : not null access Remote_File_Record; Append : Boolean := False; - FD : out GNAT.OS_Lib.File_Descriptor) + FD : out GNAT.OS_Lib.File_Descriptor; + Error : out Ada.Strings.Unbounded.Unbounded_String) is + pragma Unreferenced (Error); + -- Error diagnostics is not implemented for remote files. + Tmp_Dir : File_Access := GNATCOLL.IO.Native.Get_Tmp_Directory; Cur_Dir : File_Access := @@ -777,9 +781,8 @@ GNATCOLL.Path.Ensure_Directory (Cur_Dir.Get_FS, Cur_Dir.Full.all); Content : GNAT.Strings.String_Access; - Dead : Boolean; Written : Integer; - pragma Unreferenced (Dead, Written); + pragma Unreferenced (Written); begin Ensure_Initialized (File); @@ -813,7 +816,7 @@ -- Close -- ----------- - procedure Close + overriding procedure Close (File : not null access Remote_File_Record; FD : GNAT.OS_Lib.File_Descriptor; Success : out Boolean) @@ -855,7 +858,7 @@ -- Change_Dir -- ---------------- - function Change_Dir + overriding function Change_Dir (Dir : not null access Remote_File_Record) return Boolean is begin @@ -878,7 +881,7 @@ -- Read_Dir -- -------------- - function Read_Dir + overriding function Read_Dir (Dir : not null access Remote_File_Record; Dirs_Only : Boolean := False; Files_Only : Boolean := False) return GNAT.Strings.String_List @@ -905,7 +908,7 @@ -- Make_Dir -- -------------- - function Make_Dir + overriding function Make_Dir (Dir : not null access Remote_File_Record; Recursive : Boolean) return Boolean is @@ -929,7 +932,7 @@ -- Remove_Dir -- ---------------- - procedure Remove_Dir + overriding procedure Remove_Dir (Dir : not null access Remote_File_Record; Recursive : Boolean; Success : out Boolean) @@ -954,7 +957,7 @@ -- Copy_Dir -- -------------- - procedure Copy_Dir + overriding procedure Copy_Dir (From : not null access Remote_File_Record; Dest : FS_String; Success : out Boolean) diff -Nru libgnatcoll-18/src/gnatcoll-io-remote.ads libgnatcoll-19/src/gnatcoll-io-remote.ads --- libgnatcoll-18/src/gnatcoll-io-remote.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-io-remote.ads 2019-05-16 17:44:09.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -108,7 +108,8 @@ overriding procedure Open_Write (File : not null access Remote_File_Record; Append : Boolean := False; - FD : out GNAT.OS_Lib.File_Descriptor); + FD : out GNAT.OS_Lib.File_Descriptor; + Error : out Ada.Strings.Unbounded.Unbounded_String); overriding procedure Close (File : not null access Remote_File_Record; FD : GNAT.OS_Lib.File_Descriptor; diff -Nru libgnatcoll-18/src/gnatcoll-json.adb libgnatcoll-19/src/gnatcoll-json.adb --- libgnatcoll-18/src/gnatcoll-json.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-json.adb 2019-05-16 17:44:08.000000000 +0000 @@ -23,6 +23,7 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Containers; use Ada.Containers; +with Ada.Exceptions; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; with Ada.Unchecked_Deallocation; @@ -33,9 +34,15 @@ package body GNATCOLL.JSON is type Text_Position is record - Index : Natural := 0; - Line : Natural := 0; + Index : Natural := 0; + -- Array index in the input string. For valid positions, this is + -- positive. + + Line : Natural := 0; + -- Logical line number. For valid positions, this is positive. + Column : Natural := 0; + -- Logical column number. For valid positions, this is positive. end record; -- Record to represent position in a given text @@ -59,19 +66,15 @@ -- a J_NUMBER token that "might" be represented as an integer. Special -- token J_EOF means that end of stream has been reached. - function Is_Value (TK : Token_Kind) return Boolean; - pragma Inline (Is_Value); - -- Return True if the token kind is a JSON value: null, false, true, - -- a string, a number, an array or an object. + subtype Value_Token is Token_Kind range J_NULL .. J_OBJECT; + -- Subset of token kinds for JSON values: null, false, true, a string, a + -- number, an array or an object. procedure Free is new Ada.Unchecked_Deallocation (JSON_Array_Internal, JSON_Array_Access); procedure Free is new Ada.Unchecked_Deallocation (JSON_Object_Internal, JSON_Object_Access); - procedure Report_Error (File : String; Line, Col : Natural; Msg : String); - pragma No_Return (Report_Error); - procedure Write (Item : JSON_Value; Compact : Boolean; @@ -79,38 +82,61 @@ Ret : in out Unbounded_String); -- Auxiliary write function - function Read - (Strm : String; + procedure Read + (Result : in out Read_Result; + Strm : String; Pos : in out Text_Position; Kind : out Token_Kind; - Filename : String; Check_EOF : Boolean := False) - return JSON_Value; - -- Internal function that reads a JSON stream. + with Pre => Result.Success; + -- Read and decode a JSON value. On success, this returns a Read_Result + -- with Success => True, otherwise it returns an error with a Success => + -- False record. + -- + -- If Check_EOF is true, return an error if we haven't reached the end of + -- the input string upon returning. If Check_EOF if false and no value + -- could be decoded but we still managed to read a token, just skip this + -- token: in that case, a null JSON value is returned. -- -- Strm is the content to decode, - -- Pos is the current position in the Strm, + -- + -- Pos is the position in Strm from which we start reading. It is updated + -- to point past that token. + -- -- Kind is set to the last read token kind, - -- Filename is the filename of corresponding to the content Strm (used for - -- for error reporting only). - -- If Check_EOF is set to True, check before returning the JSON value that - -- we have reached the end of the stream. + -- + -- Note that we use an IN OUT parameter instead of a mere return value for + -- the result to avoid a noticeable runtime penalty, probably due to + -- the secondary stack management involved. + + type Read_Token_Result (Success : Boolean := True) is record + case Success is + when True => + Kind : Token_Kind; + when False => + Error : Parsing_Error; + end case; + end record; function Read_Token (Strm : String; - Filename : String; Pos : in out Text_Position; Token_Start : out Text_Position; Token_End : out Text_Position) - return Token_Kind; - -- Read a token + return Read_Token_Result; + -- Read a token. -- -- Strm is the content to decode, - -- Filename is the filename of the decoded content (error reporting) - -- Pos is the current position in Strm - -- Token_Start are Token_End are respectively the position of the first and - -- last character of the token (outside boundaries of Strm if the return - -- token is J_EOF). + -- + -- Pos is the position in Strm from which the token is read. It is updated + -- to point past that token. + -- + -- Token_Start are Token_End are set respectively to the position of the + -- first and last character of the token (outside boundaries of Strm if the + -- return token is J_EOF). + -- + -- If a parsing error is detected, this returns a Read_Token_Error record + -- with Success => False, including the relevant parsing error information. ------------ -- Append -- @@ -135,42 +161,19 @@ end case; end Is_Empty; - -------------- - -- Is_Value -- - -------------- - function Is_Value (TK : Token_Kind) return Boolean is + -------------------------- + -- Format_Parsing_Error -- + -------------------------- + + function Format_Parsing_Error (Error : Parsing_Error) return String is + L : constant String := Error.Line'Img; + C : constant String := Error.Column'Img; begin - return TK = J_NULL or else - TK = J_TRUE or else - TK = J_FALSE or else - TK = J_STRING or else - TK = J_ARRAY or else - TK = J_OBJECT or else - TK = J_INTEGER or else - TK = J_NUMBER; - end Is_Value; - - ------------------ - -- Report_Error -- - ------------------ - - procedure Report_Error (File : String; Line, Col : Natural; Msg : String) is - L : constant String := Line'Img; - C : constant String := Col'Img; - begin - Ada.Text_IO.New_Line; - - if File = "" then - Ada.Text_IO.Put (":"); - else - Ada.Text_IO.Put (File & ":"); - end if; - - Ada.Text_IO.Put_Line - (L (L'First + 1 .. L'Last) & ":" & C (C'First + 1 .. C'Last) & ": " & - Msg); - raise Invalid_JSON_Stream with Msg; - end Report_Error; + return + (L (L'First + 1 .. L'Last) & ":" + & C (C'First + 1 .. C'Last) & ": " + & To_String (Error.Message)); + end Format_Parsing_Error; ---------------- -- Read_Token -- @@ -178,40 +181,53 @@ function Read_Token (Strm : String; - Filename : String; Pos : in out Text_Position; Token_Start : out Text_Position; Token_End : out Text_Position) - return Token_Kind + return Read_Token_Result is procedure Next_Char; - -- Update Pos to point to next char + -- Update Pos to point to next character in Strm - function Is_Whitespace return Boolean; - pragma Inline (Is_Whitespace); - -- Return True of current character is a whitespace - - function Is_Structural_Token return Boolean; - pragma Inline (Is_Structural_Token); - -- Return True if current character is one of the structural tokens - - function Is_Token_Sep return Boolean; - pragma Inline (Is_Token_Sep); - -- Return True if current character is a token separator - - procedure Error (Msg : String); - pragma No_Return (Error); - - procedure Delimit_Keyword (Kw : String); - -- Helper function to parse tokens such as null, false and true + function Next_Char (Result : Token_Kind) return Read_Token_Result + with Inline; + -- Shortcut to call the Next_Char procedure after returning Result + + function Is_Whitespace return Boolean with Inline; + -- Return True of current character is a whitespace: line feed, carriage + -- return, space or horizontal tabulation. + + function Is_Structural_Token return Boolean with Inline; + -- Return True if current character is one of the structural tokens: + -- brackets, parens, comma or colon. + + function Is_Token_Sep return Boolean with Inline; + -- Return True if at least of of the following is true: + -- + -- * we reached the end of input string; + -- * the current character is a whitespace; + -- * the current character is a structural token. + + function Error (Msg : String) return Read_Token_Result; + -- Return a parsing error for the current position and the given error + -- message. + + function Delimit_Keyword + (Kw : String; Kind : Token_Kind) return Read_Token_Result; + -- Advance Pos until we reach the next token separator, updating + -- Token_End to designate the last character. Return the resulting token + -- if it matches Kw/Kind, otherwise raise an error. ----------- -- Error -- ----------- - procedure Error (Msg : String) is + function Error (Msg : String) return Read_Token_Result is begin - Report_Error (Filename, Pos.Line, Pos.Column, Msg); + return (Success => False, + Error => (Line => Pos.Line, + Column => Pos.Column, + Message => To_Unbounded_String (Msg))); end Error; --------------- @@ -231,17 +247,21 @@ end if; end Next_Char; + function Next_Char (Result : Token_Kind) return Read_Token_Result is + begin + Next_Char; + return (Success => True, Kind => Result); + end Next_Char; + ------------------- -- Is_Whitespace -- ------------------- function Is_Whitespace return Boolean is begin - return Pos.Index <= Strm'Last and then - (Strm (Pos.Index) = ASCII.LF or else - Strm (Pos.Index) = ASCII.CR or else - Strm (Pos.Index) = ASCII.HT or else - Strm (Pos.Index) = ' '); + return + (Pos.Index <= Strm'Last + and then Strm (Pos.Index) in ASCII.LF | ASCII.CR | ASCII.HT | ' '); end Is_Whitespace; ------------------------- @@ -250,13 +270,9 @@ function Is_Structural_Token return Boolean is begin - return Pos.Index <= Strm'Last and then - (Strm (Pos.Index) = '[' or else - Strm (Pos.Index) = ']' or else - Strm (Pos.Index) = '{' or else - Strm (Pos.Index) = '}' or else - Strm (Pos.Index) = ',' or else - Strm (Pos.Index) = ':'); + return + (Pos.Index <= Strm'Last + and then Strm (Pos.Index) in '[' | ']' | '{' | '}' | ',' | ':'); end Is_Structural_Token; ------------------ @@ -265,167 +281,195 @@ function Is_Token_Sep return Boolean is begin - return Pos.Index > Strm'Last or else - Is_Whitespace or else - Is_Structural_Token; + return (Pos.Index > Strm'Last + or else Is_Whitespace + or else Is_Structural_Token); end Is_Token_Sep; --------------------- -- Delimit_Keyword -- --------------------- - procedure Delimit_Keyword (Kw : String) is + function Delimit_Keyword + (Kw : String; Kind : Token_Kind) return Read_Token_Result is begin while not Is_Token_Sep loop Token_End := Pos; Next_Char; end loop; if Strm (Token_Start.Index .. Token_End.Index) /= Kw then - Error ("invalid keyword starting with: " & - Strm (Token_Start.Index .. Token_End.Index)); + return Error ("invalid keyword starting with: " + & Strm (Token_Start.Index .. Token_End.Index)); + else + return (Success => True, Kind => Kind); end if; end Delimit_Keyword; - CC : Character; + CC : Character; + -- Buffer for the currently analyzed character + Can_Be_Integer : Boolean := True; + -- When reading a number token, this is true if that number can be an + -- integer: otherwise, it must be interpreted as a decimal number. begin -- Skip leading whitespaces + while Is_Whitespace loop Next_Char; end loop; -- Initialize token delimiters + Token_Start := Pos; Token_End := Pos; - -- End of stream reached + -- If we reached the end of the input string, just return a EOF token + if Pos.Index > Strm'Last then - return J_EOF; + return (Success => True, Kind => J_EOF); end if; + -- Otherwise, all depends on the first non-whitespace character to read + -- next... + CC := Strm (Pos.Index); + case CC is + + -- Structual tokens are unambiguously designated by standalone + -- characters. + + when '[' => return Next_Char (J_ARRAY); + when ']' => return Next_Char (J_ARRAY_END); + when '{' => return Next_Char (J_OBJECT); + when '}' => return Next_Char (J_OBJECT_END); + when ',' => return Next_Char (J_COMMA); + when ':' => return Next_Char (J_COLON); + + -- Only named value tokens can start with a letter + + when 'n' => return Delimit_Keyword ("null", J_NULL); + when 'f' => return Delimit_Keyword ("false", J_FALSE); + when 't' => return Delimit_Keyword ("true", J_TRUE); + + when '"' => + + -- We expect a string. + -- + -- Just scan till the end the of the string but do not attempt to + -- decode it. This means that even if we get a string token it might + -- not be a valid string from the ECMA 404 point of view. - if CC = '[' then - Next_Char; - return J_ARRAY; - elsif CC = ']' then - Next_Char; - return J_ARRAY_END; - elsif CC = '{' then - Next_Char; - return J_OBJECT; - elsif CC = '}' then - Next_Char; - return J_OBJECT_END; - elsif CC = ',' then - Next_Char; - return J_COMMA; - elsif CC = ':' then - Next_Char; - return J_COLON; - elsif CC = 'n' then - Delimit_Keyword ("null"); - return J_NULL; - elsif CC = 'f' then - Delimit_Keyword ("false"); - return J_FALSE; - elsif CC = 't' then - Delimit_Keyword ("true"); - return J_TRUE; - elsif CC = '"' then - -- We expect a string - -- Just scan till the end the of the string but do not attempt - -- to decode it. This means that even if we get a string token - -- it might not be a valid string from the ECMA 404 point of - -- view. Next_Char; while Pos.Index <= Strm'Last and then Strm (Pos.Index) /= '"' loop - if Strm (Pos.Index) in ASCII.NUL .. ASCII.US then - Error ("control character not allowed in string"); + CC := Strm (Pos.Index); + + if CC in ASCII.NUL .. ASCII.US then + return Error ("control character not allowed in string"); end if; - if Strm (Pos.Index) = '\' then + if CC = '\' then + + -- This is an escape sequence. Make sure we have at least one + -- more character to read. + Next_Char; + if Pos.Index > Strm'Last then - Error ("non terminated string token"); + return Error ("non terminated string"); end if; case Strm (Pos.Index) is when 'u' => + -- This is a unicode escape sequence ("\uXXXX") for Idx in 1 .. 4 loop Next_Char; - if Pos.Index > Strm'Last or else - (Strm (Pos.Index) not in 'a' .. 'f' and then - Strm (Pos.Index) not in 'A' .. 'F' and then - Strm (Pos.Index) not in '0' .. '9') + if Pos.Index > Strm'Last then + return Error ("non terminated string"); + elsif Strm (Pos.Index) not in + 'a' .. 'f' | 'A' .. 'F' | '0' .. '9' then - Error ("invalid unicode escape sequence"); + return Error ("invalid unicode escape sequence"); end if; - end loop; when '\' | '/' | '"' | 'b' | 'f' | 'n' | 'r' | 't' => + -- This is a single-character escape sequence null; + when others => - Error ("invalid escape sequence"); + return Error ("invalid escape sequence"); end case; end if; Next_Char; end loop; - -- No quote found report and error + -- We could not find a closing quote before the end of the input + -- string: this is an error. + if Pos.Index > Strm'Last then - Error ("non terminated string token"); + return Error ("non terminated string"); end if; Token_End := Pos; - -- Go to next char and ensure that this is separator. Indeed - -- construction such as "string1""string2" are not allowed + -- Go to next char and ensure that this is separator. Indeed, + -- construction such as "string1""string2" are not allowed. + Next_Char; if not Is_Token_Sep then - Error ("invalid syntax"); + return Error ("invalid syntax"); end if; - return J_STRING; - elsif CC = '-' or else CC in '0' .. '9' then - -- We expect a number + return (Success => True, Kind => J_STRING); + + when '-' | '0' .. '9' => + + -- We expect a number. If it's a negative one, just discard the + -- leading dash. + if CC = '-' then Next_Char; + if Pos.Index > Strm'Last then + return Error ("invalid number"); + end if; end if; - if Pos.Index > Strm'Last then - Error ("invalid number"); - end if; + -- Parse the integer part of a number. Leading zeros (except a mere + -- "0" of course) are not allowed. - -- Parse integer part of a number. Superfluous leading zeros are not - -- allowed. - if Strm (Pos.Index) = '0' then + case Strm (Pos.Index) is + when '0' => Token_End := Pos; Next_Char; - elsif Strm (Pos.Index) in '1' .. '9' then + + when '1' .. '9' => Token_End := Pos; Next_Char; - while Pos.Index <= Strm'Last and then - Strm (Pos.Index) in '0' .. '9' + while Pos.Index <= Strm'Last + and then Strm (Pos.Index) in '0' .. '9' loop Token_End := Pos; Next_Char; end loop; - else - Error ("invalid number"); - end if; + + when others => + return Error ("invalid number"); + end case; if Is_Token_Sep then - -- Valid integer number - return J_INTEGER; - elsif Strm (Pos.Index) /= '.' and then - Strm (Pos.Index) /= 'e' and then - Strm (Pos.Index) /= 'E' - then - Error ("invalid number"); + + -- The token stops here, so we have a valid integer number + + return (Success => True, Kind => J_INTEGER); + + elsif Strm (Pos.Index) not in '.' | 'e' | 'E' then + + -- At this point, we allow only an exponent or a decimal number + + return Error ("invalid number"); end if; - -- Check for a fractional part + -- If present, handle the decimals + if Strm (Pos.Index) = '.' then Can_Be_Integer := False; Token_End := Pos; @@ -433,7 +477,7 @@ if Pos.Index > Strm'Last or else Strm (Pos.Index) not in '0' .. '9' then - Error ("invalid number"); + return Error ("invalid number"); end if; while Pos.Index <= Strm'Last and then @@ -445,34 +489,38 @@ end if; - -- Check for exponent part - if Pos.Index <= Strm'Last and then - (Strm (Pos.Index) = 'e' or else Strm (Pos.Index) = 'E') - then + -- If present, handle the exponent + + if Pos.Index <= Strm'Last and then Strm (Pos.Index) in 'e' | 'E' then Token_End := Pos; Next_Char; if Pos.Index > Strm'Last then - Error ("invalid number"); + return Error ("invalid number"); end if; - if Strm (Pos.Index) = '-' then - -- Also a few corner cases can lead to an integer, assume that - -- the number is not an integer. - Can_Be_Integer := False; - end if; + -- Skip the sign, if present - if Strm (Pos.Index) = '-' or else Strm (Pos.Index) = '+' then - Next_Char; - end if; + case Strm (Pos.Index) is + when '-' => - if Pos.Index > Strm'Last or else - Strm (Pos.Index) not in '0' .. '9' + -- The exponent is negative. Even though several corner + -- cases (such as having "1" as the prefix) can lead to an + -- integer, assume that the number is not an integer. + + Can_Be_Integer := False; + Next_Char; + + when '+' => Next_Char; + when others => null; + end case; + + if Pos.Index > Strm'Last or else Strm (Pos.Index) not in '0' .. '9' then - Error ("invalid number"); + return Error ("invalid number"); end if; - while Pos.Index <= Strm'Last and then - Strm (Pos.Index) in '0' .. '9' + while Pos.Index <= Strm'Last + and then Strm (Pos.Index) in '0' .. '9' loop Token_End := Pos; Next_Char; @@ -480,146 +528,297 @@ end if; if Is_Token_Sep then - -- Valid decimal number - if Can_Be_Integer then - return J_INTEGER; - else - return J_NUMBER; - end if; + + -- The token stops here, so we have a valid integer number + + return + (Success => True, + Kind => (if Can_Be_Integer then J_INTEGER else J_NUMBER)); else - Error ("invalid number"); + return Error ("invalid number"); end if; - else - Error ("Unexpected character '" & CC & '''); - end if; + + when others => + return Error ("Unexpected character '" & CC & '''); + end case; end Read_Token; ---------- -- Read -- ---------- - function Read - (Strm : String; + procedure Read + (Result : in out Read_Result; + Strm : String; Pos : in out Text_Position; Kind : out Token_Kind; - Filename : String; Check_EOF : Boolean := False) - return JSON_Value is - procedure Error (Msg : String); - pragma No_Return (Error); + function Error (Msg : String) return Read_Result; + -- Return a parsing error for the current position and the given error + -- message. + + function Error (Result : Read_Token_Result) return Read_Result + with Pre => not Result.Success; + -- Transform a parsing error from Read_Token into a Read_Result ----------- -- Error -- ----------- - procedure Error (Msg : String) is + function Error (Msg : String) return Read_Result is begin - Report_Error (Filename, Pos.Line, Pos.Column, Msg); + return (Success => False, + Error => (Line => Pos.Line, + Column => Pos.Column, + Message => To_Unbounded_String (Msg))); + end Error; + + function Error (Result : Read_Token_Result) return Read_Result is + begin + return (Success => False, Error => Result.Error); end Error; Token_Start, Token_End : Text_Position; - TK : Token_Kind; - Result : JSON_Value; + -- Boundaries for the currently analyzed token + + Token_Result : Read_Token_Result; + -- Buffer for token reads begin - TK := Read_Token (Strm, Filename, Pos, Token_Start, Token_End); - if TK = J_EOF then - Error ("empty stream"); + -- The first token we get determines the kind of JSON value to return + + Token_Result := Read_Token (Strm, Pos, Token_Start, Token_End); + if not Token_Result.Success then + Result := Error (Token_Result); + Kind := J_EOF; + return; end if; + Kind := Token_Result.Kind; - Kind := TK; + case Kind is + when J_EOF => + Result := Error ("empty stream"); + return; - case TK is when J_NULL => - Result := Create; + Result.Value := Create; + when J_FALSE => - Result := Create (False); + Result.Value := Create (False); + when J_TRUE => - Result := Create (True); + Result.Value := Create (True); + when J_STRING => - Result := Create (Utility.Un_Escape_String - (Strm, Token_Start.Index, Token_End.Index)); + begin + declare + Str_Value : constant UTF8_XString := Utility.Un_Escape_String + (Strm, Token_Start.Index, Token_End.Index); + begin + Result.Value := Create (Str_Value); + end; + exception + when Exc : Invalid_JSON_Stream => + Result := Error (Ada.Exceptions.Exception_Message (Exc)); + return; + end; + when J_ARRAY => declare - Arr : constant JSON_Array_Access := new JSON_Array_Internal; - ST : Token_Kind; - Element : JSON_Value; + -- In order to avoid the costly array copy in Create + -- (JSON_Array), we use an aggregate below in order to build + -- the result, so directly allocate the JSON_Array_Access here. + + Arr : JSON_Array_Access := new JSON_Array_Internal; + + ST : Token_Kind; + -- Buffer for the kind of tokens we read + + Element : Read_Result; + -- Buffer for the JSON values that constitute array elements + Is_First : Boolean := True; + -- True if we are still reading the first array element. False + -- afterwards. begin + -- Read all elements in the array until we reach the closing + -- token ("]"). + loop - Element := Read (Strm, Pos, ST, Filename); - if Is_First and then ST = J_ARRAY_END then - exit; - elsif Is_Value (ST) then - Append (Arr.Arr, Element); - Element := Read (Strm, Pos, ST, Filename); - if ST = J_ARRAY_END then - exit; - elsif ST /= J_COMMA then - Error ("comma expected"); - end if; - else - Error ("syntax error"); + Read (Element, Strm, Pos, ST); + if not Element.Success then + Free (Arr); + Result := Element; + return; end if; + + case ST is + when J_ARRAY_END => + exit when Is_First; + Free (Arr); + Result := Error ("syntax error"); + return; + + when Value_Token => + -- We got a new array element: append it + + Append (Arr.Arr, Element.Value); + + -- Now see what is next: the end of the array or a comma + -- (hence another array element after). + + Read (Element, Strm, Pos, ST); + if not Element.Success then + Free (Arr); + Result := Element; + return; + end if; + + case ST is + when J_ARRAY_END => + exit; + + when J_COMMA => + -- We have a comma, so we expect another element in + -- the array. Continue reading. + + null; + + when others => + Free (Arr); + Result := Error ("comma expected"); + return; + end case; + + when others => + Free (Arr); + Result := Error ("syntax error"); + return; + end case; + Is_First := False; end loop; - Result := (Ada.Finalization.Controlled with - Data => (Kind => JSON_Array_Type, Arr_Value => Arr)); + + Result.Value := + (Ada.Finalization.Controlled with + Data => (Kind => JSON_Array_Type, Arr_Value => Arr)); end; + when J_OBJECT => declare - Is_First : Boolean := True; - ST : Token_Kind; - Ret : JSON_Value; - Key, Value : JSON_Value; - Key_Str : UTF8_XString; + Is_First : Boolean := True; + -- True if we are still reading the first object member. False + -- afterwards. + + ST : Token_Kind; + -- Buffer for the kind of tokens we read + + Key, Value : Read_Result; + -- Buffer for the JSON values that constitute keys and member + -- values. begin - -- Allocate internal container - Ret.Data := (Kind => JSON_Object_Type, - Obj_Value => new JSON_Object_Internal); + -- Allocate internal container for the result + + Result.Value := + (Ada.Finalization.Controlled with + Data => (Kind => JSON_Object_Type, + Obj_Value => new JSON_Object_Internal)); + + -- Read all members for this object until we reach the closing + -- token ("}"). + loop - Key := Read (Strm, Pos, ST, Filename); - if Is_First and then ST = J_OBJECT_END then - exit; - elsif ST = J_STRING then - Value := Read (Strm, Pos, ST, Filename); - if ST /= J_COLON then - Error ("colon expected"); + -- First try to read the key for the next member + + Read (Key, Strm, Pos, ST); + if not Key.Success then + Result := Key; + return; + end if; + + case ST is + when J_OBJECT_END => + exit when Is_First; + Result := Error ("string value expected"); + return; + + when J_STRING => + -- Consume the colon token, then get the member value + + Read (Value, Strm, Pos, ST); + if not Value.Success then + Result := Value; + return; + elsif ST /= J_COLON then + Result := Error ("colon expected"); + return; end if; - Value := Read (Strm, Pos, ST, Filename); - if not Is_Value (ST) then - Error ("non expected token"); + + Read (Value, Strm, Pos, ST); + if not Value.Success then + Result := Value; + return; + elsif ST not in Value_Token then + Result := Error ("non expected token"); + return; end if; - Key_Str := Get (Key); - Set_Field (Ret, Key_Str, Value); - Value := Read (Strm, Pos, ST, Filename); - if ST = J_OBJECT_END then - exit; - elsif ST /= J_COMMA then - Error ("comma expected"); + -- Register this new member. + -- + -- As we checked above that reading Key parsed a string + -- token, we know that coercing Key to a string cannot + -- fail. + + declare + Key_Str : constant UTF8_XString := Get (Key.Value); + begin + Set_Field (Result.Value, Key_Str, Value.Value); + end; + + -- Now see what is next: the end of the object or a comma + -- (hence another object member after). + + Read (Value, Strm, Pos, ST); + if not Value.Success then + Result := Value; + return; end if; - else - Error ("string value expected"); - end if; + case ST is + when J_OBJECT_END => + exit; + + when J_COMMA => + -- We have a comma, so we expect another member in the + -- object. Continue reading. + + null; + + when others => + Result := Error ("comma expected"); + return; + end case; + + when others => + Result := Error ("string value expected"); + return; + end case; Is_First := False; end loop; - Result := Ret; end; + when J_NUMBER | J_INTEGER => - -- This is a number declare - Number_Str : constant String := - Strm (Token_Start.Index .. Token_End.Index); + Number_Str : constant String := + Strm (Token_Start.Index .. Token_End.Index); Has_Integer : Boolean := False; begin - if TK = J_INTEGER then + if Kind = J_INTEGER then declare Result_Int : Long_Long_Integer; begin Result_Int := Long_Long_Integer'Value (Number_Str); - Result := Create (Result_Int); + Result.Value := Create (Result_Int); Has_Integer := True; exception when Constraint_Error => @@ -629,27 +828,32 @@ if not Has_Integer then begin - Result := Create (Long_Float'Value (Number_Str)); + Result.Value := Create (Long_Float'Value (Number_Str)); exception when Constraint_Error => - Error ("cannot convert JSON number to Long_Float"); + Result := Error + ("cannot convert JSON number to Long_Float"); + return; end; end if; end; + when others => if Check_EOF then - Error ("invalid JSON stream"); + Result := Error ("invalid JSON stream"); + return; else - Result := Create; + Result.Value := Create; end if; end case; - if Check_EOF and then - Read_Token (Strm, Filename, Pos, Token_Start, Token_End) /= J_EOF - then - Error ("additional data after end of JSON stream"); + if Check_EOF then + Token_Result := Read_Token (Strm, Pos, Token_Start, Token_End); + if not Token_Result.Success or else Token_Result.Kind /= J_EOF then + Result := Error ("additional data after end of JSON stream"); + return; + end if; end if; - return Result; end Read; function Read @@ -664,10 +868,38 @@ (Strm : String; Filename : String := "") return JSON_Value is - Pos : Text_Position := (Strm'First, 1, 1); - Kind : Token_Kind; + Result : constant Read_Result := Read (Strm); begin - return Read (Strm, Pos, Kind, Filename, Check_EOF => True); + if Result.Success then + return Result.Value; + else + Ada.Text_IO.New_Line; + + if Filename = "" then + Ada.Text_IO.Put (":"); + else + Ada.Text_IO.Put (Filename & ":"); + end if; + + Ada.Text_IO.Put_Line (Format_Parsing_Error (Result.Error)); + raise Invalid_JSON_Stream with To_String (Result.Error.Message); + end if; + end Read; + + function Read + (Strm : Ada.Strings.Unbounded.Unbounded_String) return Read_Result + is + begin + return Read (To_String (Strm)); + end Read; + + function Read (Strm : String) return Read_Result is + Pos : Text_Position := (Strm'First, 1, 1); + Kind : Token_Kind; + Result : Read_Result := (Success => True, others => <>); + begin + Read (Result, Strm, Pos, Kind, Check_EOF => True); + return Result; end Read; ----------- diff -Nru libgnatcoll-18/src/gnatcoll-json.ads libgnatcoll-19/src/gnatcoll-json.ads --- libgnatcoll-18/src/gnatcoll-json.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-json.ads 2019-05-16 17:44:09.000000000 +0000 @@ -21,6 +21,33 @@ -- -- ------------------------------------------------------------------------------ +-- GNATCOLL.JSON exposes an API to parse and serialize data using the JSON +-- (JavaScript Object Notation) format. +-- +-- Parsing JSON is as easy as calling the Read function:: +-- +-- Data : JSON_Value := Read ("[1, ""foo"", {""foo"": null}]"); +-- +-- Encoding to JSON is not any more complex:: +-- +-- JSON_String : String := Write (Data); +-- +-- JSON trees (JSON_Value) are available for both inspection and +-- modification:: +-- +-- Float_Number : JSON_Value := Create (Float'(1.0)); +-- -- Mere float number +-- +-- Object : JSON_Value := Get (Get (Data), 3); +-- -- JSON object from Data: {"foo": null} +-- +-- Some_Array : JSON_Value := +-- Create (Float_Number & Object & Create (False)); +-- -- Synthetic JSON array: [1.0, {"foo": null}, False] +-- +-- -- Modify Data in place +-- Data.Append (Some_Array); + with Ada.Finalization; with Ada.Strings.Unbounded; with GNATCOLL.Strings; @@ -32,12 +59,38 @@ type JSON_Value_Type is (JSON_Null_Type, + -- Null value: all such JSON values are equivalent + JSON_Boolean_Type, + -- Boolean value: either true or false + JSON_Int_Type, + -- Integer value, encoded as an Ada Long_Long_Integer + JSON_Float_Type, + -- Float value, encoded as an Ada Long_Float + JSON_String_Type, + -- UTF-8 encoded string + JSON_Array_Type, - JSON_Object_Type); + -- Array of JSON values + + JSON_Object_Type + -- Sequence of fields. Each field has a unique name and maps to a + -- JSON value. Depending on the context, this sequence can be processed + -- as a mapping, because each field name is unique, but iterating on + -- fields is deterministic because it is a sequence underneath. + ); + -- Each JSON value (JSON_Value below) has a specific kind... + + subtype JSON_Elementary_Value_Type is JSON_Value_Type range + JSON_Null_Type .. JSON_String_Type; + -- Some are atoms... + + subtype JSON_Container_Value_Type is JSON_Value_Type range + JSON_Array_Type .. JSON_Object_Type; + -- While others are containers for other values Invalid_JSON_Stream : exception; @@ -47,20 +100,18 @@ subtype UTF8_Unbounded_String is Ada.Strings.Unbounded.Unbounded_String; subtype UTF8_XString is GNATCOLL.Strings.XString; - subtype JSON_Elementary_Value_Type is JSON_Value_Type range - JSON_Null_Type .. JSON_String_Type; - subtype JSON_Container_Value_Type is JSON_Value_Type range - JSON_Array_Type .. JSON_Object_Type; - type JSON_Value is tagged private; - -- Stores a JSON value, which can be either a simple type (integer, - -- string, ...) or an object with multiple fields, or an array. + -- Store a JSON value, which can be either a simple type (integer, string, + -- ...) or an object with multiple fields, or an array (see JSON_Value_Type + -- above). + -- + -- This type has by-reference semantics, so using the standard assignment + -- operator as in:: -- - -- This type works by reference. Using the standard assignment operator - -- as in -- A := B; - -- means that modifying B will also modify A (and modifying A will of - -- course modify B). + -- + -- just creates an alias. This means that modifying B will also modify A + -- (and modifying A will of course modify B). -- -- If you want to create a separate copy, you must use the Clone function. @@ -71,36 +122,77 @@ JSON_Null : constant JSON_Value; Empty_Array : constant JSON_Array; - -- Array handling + -------------------- + -- Array handling -- + -------------------- + function Is_Empty (Arr : JSON_Array) return Boolean; + -- Return whether Arr is an empty array + function Length (Arr : JSON_Array) return Natural; + -- Return the number of elements in Arr + function Get (Arr : JSON_Array; Index : Positive) return JSON_Value; + -- If Arr has at least Index elements, return the element at that index. + -- Raise a Constraint_Error otherwise. + procedure Append (Arr : in out JSON_Array; Val : JSON_Value); + -- Append Val as a new element at the end of the Arr array + procedure Prepend (Arr : in out JSON_Array; Val : JSON_Value); + -- Insert Val as the first element of the Arr array + procedure Clear (Arr : in out JSON_Array); + -- Remove all elements in Arr + procedure Sort - (Arr : in out JSON_Array; + (Arr : in out JSON_Array; Less : access function (Left, Right : JSON_Value) return Boolean); - -- Reorders the elements of array such that the elements are sorted - -- smallest first as determined by the strict comparison provided by - -- function Less. + -- Reorder the elements in Arr such that they are sorted smallest first + -- according to the strict comparison that Less implements. procedure Set_Element (Arr : in out JSON_Array; Index : Positive; Item : JSON_Value); - -- If Index is not in the array index range, then Constraint_Error is - -- propagated. Otherwise Set_Element assigns the value New_Item to the - -- element at position Index. + -- If Arr has at least Index elements, replace the element at that index + -- with Item. Raise a Constraint_Error otherwise. + + -- Both functions below are less efficient than Append because they + -- result in an extra copy of the array, but they are easier to use when + -- manipulating small arrays. function "&" (Arr : JSON_Array; Value : JSON_Value) return JSON_Array; + -- Return a new array that appends Value to Arr + function "&" (Value1, Value2 : JSON_Value) return JSON_Array; - -- Create a new array. This is less efficient than Append because it - -- results in an extra copy of the array, but is easier to use when - -- manipulating small arrays. + -- Return a new array that contains Value1 and Value2 function Is_Empty (Val : JSON_Value) return Boolean; - -- Returns True if Val is empty array, empty object or null value + -- Return True if Val is empty array, empty object or null value. Return + -- False in all other cases. - -- Read or write JSON values into strings + ---------------------------------------------- + -- Serialization/deserialization primitives -- + ---------------------------------------------- + + type Parsing_Error is record + Line, Column : Positive; + -- Line and column numbers at which a parsing error is detected + + Message : UTF8_Unbounded_String; + -- Short description of the parsing error + end record; + + function Format_Parsing_Error (Error : Parsing_Error) return String; + -- Return a human-readable string to describe Error + + type Read_Result (Success : Boolean := True) is record + case Success is + when True => + Value : JSON_Value; + when False => + Error : Parsing_Error; + end case; + end record; function Read (Strm : Ada.Strings.Unbounded.Unbounded_String; @@ -108,255 +200,272 @@ function Read (Strm : String; Filename : String := "") return JSON_Value; + -- Parse the JSON document in Strm and return it. On parsing error, print + -- an error message referencing Filename on the standard output and raise + -- an Invalid_JSON_Stream exception. + + function Read + (Strm : Ada.Strings.Unbounded.Unbounded_String) return Read_Result; + function Read (Strm : String) return Read_Result; + -- Parse the JSON document in Strm and return it. If there is a parsing + -- error, return the corresponding error information. + function Write (Item : JSON_Value; Compact : Boolean := True) return String; function Write (Item : JSON_Value; Compact : Boolean := True) return Ada.Strings.Unbounded.Unbounded_String; + -- Return a string that encodes Item in JSON. Unless Compact is True, this + -- creates an indented multi-line representation. - -- Creation of JSON values - - function Create return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Null_Type); - -- Creates a 'null' JSON value - - function Create (Val : Boolean) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Boolean_Type); - -- Creates a boolean-typed JSON value - - function Create (Val : Integer) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Int_Type); - function Create (Val : Long_Integer) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Int_Type); - function Create (Val : Long_Long_Integer) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Int_Type); - -- Creates an integer-typed JSON value - - function Create (Val : Float) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Float_Type); - -- Creates a float-typed JSON value - - function Create (Val : Long_Float) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Float_Type); - - function Create (Val : UTF8_String) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_String_Type); - -- Creates a string-typed JSON value - - function Create (Val : UTF8_Unbounded_String) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_String_Type); - -- Creates a string-typed JSON value - - function Create (Val : UTF8_XString) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_String_Type); - -- Creates a string-typed JSON value - - function Create (Val : JSON_Array) return JSON_Value; - pragma Postcondition (Kind (Create'Result) = JSON_Array_Type); - -- Creates a JSON value from the JSON array - - function Create_Object return JSON_Value; - pragma Postcondition (Kind (Create_Object'Result) = JSON_Object_Type); - -- Creates an empty object. Values need to be added using the below - -- Set_Field methods + ----------------------------- + -- Creation of JSON values -- + ----------------------------- + + function Create return JSON_Value + with Post => Create'Result.Kind = JSON_Null_Type; + -- Create a 'null' JSON value + + function Create (Val : Boolean) return JSON_Value + with Post => Create'Result.Kind = JSON_Boolean_Type; + -- Create a boolean-typed JSON value + + function Create (Val : Integer) return JSON_Value + with Post => Create'Result.Kind = JSON_Int_Type; + function Create (Val : Long_Integer) return JSON_Value + with Post => Create'Result.Kind = JSON_Int_Type; + function Create (Val : Long_Long_Integer) return JSON_Value + with Post => Create'Result.Kind = JSON_Int_Type; + -- Create an integer-typed JSON value + + function Create (Val : Float) return JSON_Value + with Post => Create'Result.Kind = JSON_Float_Type; + -- Create a float-typed JSON value + + function Create (Val : Long_Float) return JSON_Value + with Post => Create'Result.Kind = JSON_Float_Type; + + function Create (Val : UTF8_String) return JSON_Value + with Post => Create'Result.Kind = JSON_String_Type; + -- Create a string-typed JSON value + + function Create (Val : UTF8_Unbounded_String) return JSON_Value + with Post => Create'Result.Kind = JSON_String_Type; + -- Create a string-typed JSON value + + function Create (Val : UTF8_XString) return JSON_Value + with Post => Create'Result.Kind = JSON_String_Type; + -- Create a string-typed JSON value + + function Create (Val : JSON_Array) return JSON_Value + with Post => Create'Result.Kind = JSON_Array_Type; + -- Create a JSON value from the JSON array + + function Create_Object return JSON_Value + with Post => Create_Object'Result.Kind = JSON_Object_Type; + -- Create an empty object. Values need to be added using the below + -- Set_Field methods. procedure Sort - (Val : in out JSON_Value; + (Val : in out JSON_Value; Less : access function (Left, Right : JSON_Value) return Boolean); - -- Reorders the elements of array or fields of object such that the - -- values are sorted smallest first as determined by the strict comparision - -- provided by function Less. - - procedure Append (Arr : JSON_Value; Item : JSON_Value); - pragma Precondition (Arr.Kind = JSON_Array_Type); - -- Append Arr only in case of it is an array, raise Constraint_Error - -- otherwise. + -- If Val is a JSON array or a JSON object, reorder its elements/fields + -- such that they are sorted smallest first according to the strict + -- comparison that Less implements. Note that for JSON objects, field + -- values are compared, not field names. + + procedure Append (Arr : JSON_Value; Item : JSON_Value) + with Pre => Arr.Kind = JSON_Array_Type; + -- Assuming Arr is a JSON array, append Item to it function Clone (Val : JSON_Value) return JSON_Value; - -- Returns a deep clone of Val. - -- Any change in Val or its fields (recursively) will have no impact - -- on the resulting value. + -- Return a deep clone of Val. Any later change in Val or its fields + -- (recursively) will have no impact on the resulting value. function "=" (Left, Right : JSON_Value) return Boolean; - -- Compare to values. + -- Return whether Left and Right are structurally identical. + -- -- The actual contents is compared, not the pointers. So two objects - -- constructed independently, with the same contents, will match. - -- The order that fields were created is irrelevant, for objects. - -- The order in arrays is relevant. + -- constructed independently, with the same contents, will match. For JSON + -- objects, the order for fields is irrelevant, for objects. It is relevant + -- for arrays however. procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : JSON_Value); - pragma Precondition (Kind (Val) = JSON_Object_Type); - -- Adds or modifies the named field for the specified json object, using - -- the Field value. + Field : JSON_Value) + with Pre => Val.Kind = JSON_Object_Type; + -- Assuming Val is a JSON object, add a new field or modify the existing + -- one for the given Field_Name. The field value is Field afterwards. procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_XString; - Field : JSON_Value); - pragma Precondition (Kind (Val) = JSON_Object_Type); - -- Adds or modifies the named field for the specified json object, using - -- the Field value. + Field : JSON_Value) + with Pre => Val.Kind = JSON_Object_Type; + -- Assuming Val is a JSON object, add a new field or modify the existing + -- one for the given Field_Name. The field value is Field afterwards. + + -- All the Set_Field overloads below are convenience shortcut that first + -- create a JSON value from their Field argument and then call the above + -- Set_Field procedures with the result. procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : Boolean); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : Boolean) + with Pre => Val.Kind = JSON_Object_Type; procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : Integer); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : Integer) + with Pre => Val.Kind = JSON_Object_Type; procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : Long_Integer); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : Long_Integer) + with Pre => Val.Kind = JSON_Object_Type; procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : Float); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : Float) + with Pre => Val.Kind = JSON_Object_Type; procedure Set_Field_Long_Float (Val : JSON_Value; Field_Name : UTF8_String; - Field : Long_Float); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : Long_Float) + with Pre => Val.Kind = JSON_Object_Type; procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : UTF8_String); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : UTF8_String) + with Pre => Val.Kind = JSON_Object_Type; procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : UTF8_Unbounded_String); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : UTF8_Unbounded_String) + with Pre => Val.Kind = JSON_Object_Type; procedure Set_Field (Val : JSON_Value; Field_Name : UTF8_String; - Field : JSON_Array); - pragma Precondition (Kind (Val) = JSON_Object_Type); - -- Any change you do to the array afterward will not impact Val + Field : JSON_Array) + with Pre => Val.Kind = JSON_Object_Type; + -- This performs a a shallow copy of Field, so any change you do to the + -- passed array for Field afterwards will not impact Val. procedure Set_Field_If_Not_Empty (Val : JSON_Value; Field_Name : UTF8_String; - Field : UTF8_Unbounded_String); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : UTF8_Unbounded_String) + with Pre => Val.Kind = JSON_Object_Type; -- Set Field only if it is not empty string procedure Set_Field_If_Not_Empty (Val : JSON_Value; Field_Name : UTF8_String; - Field : UTF8_String); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : UTF8_String) + with Pre => Val.Kind = JSON_Object_Type; -- Set Field only if it is not empty string procedure Set_Field_If_Not_Empty (Val : JSON_Value; Field_Name : UTF8_String; - Field : JSON_Array); - pragma Precondition (Kind (Val) = JSON_Object_Type); + Field : JSON_Array) + with Pre => Val.Kind = JSON_Object_Type; -- Set Field only if it is not empty array. - -- Any change you do to the array afterward will not impact Val. + -- This performs a a shallow copy of Field, so any change you do to the + -- passed array for Field afterwards will not impact Val. procedure Unset_Field (Val : JSON_Value; - Field_Name : UTF8_String); - -- Unset the field with the given name, just as if Set_Field had never - -- been called. - - -- Utility functions used to translate a JSON value into an ordinary object + Field_Name : UTF8_String) + with Pre => Val.Kind = JSON_Object_Type; + -- Assuming Val is a JSON object, remove its field whose name matches + -- Field_Name. Do nothing if there is no such a field. + + ------------------------------------------------------ + -- Conversions from JSON values to native Ada types -- + ------------------------------------------------------ function Kind (Val : JSON_Value) return JSON_Value_Type; + -- Return the kind corresponding to the Val JSON value - function Get (Val : JSON_Value) return Boolean; - pragma Precondition (Kind (Val) = JSON_Boolean_Type); + function Get (Val : JSON_Value) return Boolean + with Pre => Val.Kind = JSON_Boolean_Type; - function Get (Val : JSON_Value) return Integer; - pragma Precondition (Kind (Val) = JSON_Int_Type); + function Get (Val : JSON_Value) return Integer + with Pre => Val.Kind = JSON_Int_Type; - function Get (Val : JSON_Value) return Long_Integer; - pragma Precondition (Kind (Val) = JSON_Int_Type); + function Get (Val : JSON_Value) return Long_Integer + with Pre => Val.Kind = JSON_Int_Type; - function Get (Val : JSON_Value) return Long_Long_Integer; - pragma Precondition (Kind (Val) = JSON_Int_Type); + function Get (Val : JSON_Value) return Long_Long_Integer + with Pre => Val.Kind = JSON_Int_Type; - function Get (Val : JSON_Value) return Float; - pragma Precondition (Kind (Val) = JSON_Float_Type); + function Get (Val : JSON_Value) return Float + with Pre => Val.Kind = JSON_Float_Type; - function Get_Long_Float (Val : JSON_Value) return Long_Float; - pragma Precondition (Kind (Val) = JSON_Float_Type); + function Get_Long_Float (Val : JSON_Value) return Long_Float + with Pre => Val.Kind = JSON_Float_Type; - function Get (Val : JSON_Value) return UTF8_String; - pragma Precondition (Kind (Val) = JSON_String_Type); + function Get (Val : JSON_Value) return UTF8_String + with Pre => Val.Kind = JSON_String_Type; - function Get (Val : JSON_Value) return UTF8_Unbounded_String; - pragma Precondition (Kind (Val) = JSON_String_Type); + function Get (Val : JSON_Value) return UTF8_Unbounded_String + with Pre => Val.Kind = JSON_String_Type; - function Get (Val : JSON_Value) return UTF8_XString; - pragma Precondition (Kind (Val) = JSON_String_Type); + function Get (Val : JSON_Value) return UTF8_XString + with Pre => Val.Kind = JSON_String_Type; - function Get (Val : JSON_Value) return JSON_Array; - pragma Precondition (Kind (Val) = JSON_Array_Type); + function Get (Val : JSON_Value) return JSON_Array + with Pre => Val.Kind = JSON_Array_Type; - function Has_Field (Val : JSON_Value; Field : UTF8_String) return Boolean; - pragma Precondition (Kind (Val) = JSON_Object_Type); - -- Tell whether the object val contains a field named Field + function Has_Field (Val : JSON_Value; Field : UTF8_String) return Boolean + with Pre => Val.Kind = JSON_Object_Type; + -- Assuming Val is a JSON object, return whether it contains a field whose + -- name is Field. - function Get (Val : JSON_Value; Field : UTF8_String) return JSON_Value; - pragma Precondition (Kind (Val) = JSON_Object_Type); + function Get (Val : JSON_Value; Field : UTF8_String) return JSON_Value + with Pre => Val.Kind = JSON_Object_Type; - function Get (Val : JSON_Value; Field : UTF8_String) return Boolean; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_Boolean_Type); + function Get (Val : JSON_Value; Field : UTF8_String) return Boolean + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_Boolean_Type; - function Get (Val : JSON_Value; Field : UTF8_String) return Integer; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_Int_Type); + function Get (Val : JSON_Value; Field : UTF8_String) return Integer + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_Int_Type; - function Get (Val : JSON_Value; Field : UTF8_String) return Long_Integer; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_Int_Type); + function Get (Val : JSON_Value; Field : UTF8_String) return Long_Integer + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_Int_Type; - function Get (Val : JSON_Value; Field : UTF8_String) return Float; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_Float_Type); + function Get (Val : JSON_Value; Field : UTF8_String) return Float + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_Float_Type; function Get_Long_Float - (Val : JSON_Value; Field : UTF8_String) return Long_Float; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_Float_Type); - - function Get (Val : JSON_Value; Field : UTF8_String) return UTF8_String; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_String_Type); + (Val : JSON_Value; Field : UTF8_String) return Long_Float + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_Float_Type; + + function Get (Val : JSON_Value; Field : UTF8_String) return UTF8_String + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_String_Type; function Get - (Val : JSON_Value; Field : UTF8_String) return UTF8_Unbounded_String; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_String_Type); - - function Get (Val : JSON_Value; Field : UTF8_String) return JSON_Array; - pragma Precondition - (Kind (Val) = JSON_Object_Type - and then Kind (Get (Val, Field)) = JSON_Array_Type); + (Val : JSON_Value; Field : UTF8_String) return UTF8_Unbounded_String + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_String_Type; + + function Get (Val : JSON_Value; Field : UTF8_String) return JSON_Array + with Pre => Val.Kind = JSON_Object_Type + and then Get (Val, Field).Kind = JSON_Array_Type; --------------- -- Iteration -- @@ -364,9 +473,9 @@ procedure Map_JSON_Object (Val : JSON_Value; - CB : access procedure (Name : UTF8_String; Value : JSON_Value)); - pragma Precondition (Kind (Val) = JSON_Object_Type); - -- Iterate over all fields of the object + CB : access procedure (Name : UTF8_String; Value : JSON_Value)) + with Pre => Val.Kind = JSON_Object_Type; + -- Assuming Val is a JSON object, call CB on all its fields generic type Mapped is private; @@ -376,11 +485,10 @@ (User_Object : in out Mapped; Name : UTF8_String; Value : JSON_Value); - User_Object : in out Mapped); - pragma Precondition (Kind (Val) = JSON_Object_Type); - -- Iter on all fields of the object, like Map_JSON_Object does, - -- but the callback can return a value which is also returned by - -- Gen_Map_JSON_Object itself. + User_Object : in out Mapped) + with Pre => Val.Kind = JSON_Object_Type; + -- Assuming Val is a JSON object, call CB on all its field, passing the + -- given User_Object from call to call. private diff -Nru libgnatcoll-18/src/gnatcoll-locks.adb libgnatcoll-19/src/gnatcoll-locks.adb --- libgnatcoll-18/src/gnatcoll-locks.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-locks.adb 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,44 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2018-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +package body GNATCOLL.Locks is + + ---------------- + -- Initialize -- + ---------------- + + procedure Initialize (This : in out Scoped_Lock) is + begin + This.Lock.Seize; + end Initialize; + + -------------- + -- Finalize -- + -------------- + + procedure Finalize (This : in out Scoped_Lock) is + begin + This.Lock.Release; + end Finalize; + +end GNATCOLL.Locks; diff -Nru libgnatcoll-18/src/gnatcoll-locks.ads libgnatcoll-19/src/gnatcoll-locks.ads --- libgnatcoll-18/src/gnatcoll-locks.ads 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-locks.ads 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,90 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2018-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with GNAT.Semaphores; use GNAT.Semaphores; + +private with Ada.Finalization; + +-- This package provides simple locking primitives on top of GNAT.Semaphores. + +package GNATCOLL.Locks is + + subtype Mutual_Exclusion is Binary_Semaphore + (Initially_Available => True, + Ceiling => Default_Ceiling); + -- This subtype represents a Mutual exclusion primitive, which is a common + -- use case for Semaphores. + + type Scoped_Lock (Lock : access Mutual_Exclusion) + is limited private; + -- This type represents a scoped lock for the Mutual_Exclusion object + -- passed as discriminant. It will hold the Mutex as long as the object is + -- alive, and release it when it is finalized. + -- + -- It provides a useful idiom to protect a subprogram or a part of a + -- subprogram from data races via a critical section. Here is code without + -- a scoped lock:: + -- + -- A : Integer := 0; + -- M : Mutual_Exclusion; + -- + -- procedure Modify_State is + -- begin + -- M.Seize; + -- A := A + 1; + -- if A > 12 then + -- M.Release; + -- return; + -- end if; + -- + -- A := A + 2; + -- M.Release; + -- exception -- Addition can overflow! + -- when others => + -- M.Release; + -- raise; + -- end Modify_State; + -- + -- And here is the code with the scoped lock idiom:: + -- + -- A : Integer := 0; + -- M : Mutual_Exclusion; + -- + -- procedure Modify_State is + -- Lock : Scoped_Lock (M); + -- begin + -- A := A + 1; + -- if A > 12 then + -- return; + -- end if; + -- + -- A := A + 2; + -- end Modify_State; + +private + type Scoped_Lock (Lock : access Mutual_Exclusion) + is new Ada.Finalization.Limited_Controlled with null record; + + overriding procedure Initialize (This : in out Scoped_Lock); + overriding procedure Finalize (This : in out Scoped_Lock); +end GNATCOLL.Locks; diff -Nru libgnatcoll-18/src/gnatcoll-mmap.ads libgnatcoll-19/src/gnatcoll-mmap.ads --- libgnatcoll-18/src/gnatcoll-mmap.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-mmap.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2007-2017, AdaCore -- +-- Copyright (C) 2007-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -119,7 +119,7 @@ (Filename : String; Use_Mmap_If_Available : Boolean := True) return Mapped_File; -- Open a file for reading. The same file can be shared by multiple - -- processes, that will see each others's changes as they occur. + -- processes, that will see each others' changes as they occur. -- Any attempt to write the data might result in a segmentation fault, -- depending on how the file is open. -- Name_Error is raised if the file does not exist. @@ -146,6 +146,7 @@ (Use_Normal, Use_Random, Use_Sequential); + for Use_Advice'Size use Interfaces.C.int'Size; for Use_Advice use (Use_Normal => 1, Use_Random => 2, @@ -227,7 +228,7 @@ function Offset (Region : Mapped_Region) return File_Size with Inline; -- Return the offset, in the physical file on disk, corresponding to the - -- requested mapped region. The first byte in the file has offest 0. + -- requested mapped region. The first byte in the file has offset 0. function Offset (File : Mapped_File) return File_Size with Inline, Obsolescent; @@ -348,7 +349,7 @@ function Is_Mutable (Region : Mapped_Region) return Boolean; -- Return whether it is safe to change bytes in Data (Region). This is true - -- for regions from writeable files, for regions mapped with the "Mutable" + -- for regions from writable files, for regions mapped with the "Mutable" -- flag set, and for regions that are copied in a buffer. Note that it is -- not specified whether empty regions are mutable or not, since there is -- no byte no modify. @@ -359,7 +360,7 @@ -- or equivalent. This is in general irrelevant to your application, unless -- the file can be accessed by multiple concurrent processes or tasks. In -- such a case, and if the file is indeed mmap-ed, then the various parts - -- of the file can be written simulatenously, and thus you cannot ensure + -- of the file can be written simultaneously, and thus you cannot ensure -- the integrity of the file. If the file is not mmapped, the latest -- process to Close it overwrite what other processes have done. diff -Nru libgnatcoll-18/src/gnatcoll-mmap-system__unix.adb libgnatcoll-19/src/gnatcoll-mmap-system__unix.adb --- libgnatcoll-18/src/gnatcoll-mmap-system__unix.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-mmap-system__unix.adb 2019-05-16 17:44:09.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2007-2017, AdaCore -- +-- Copyright (C) 2007-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -22,6 +22,8 @@ ------------------------------------------------------------------------------ with Ada.IO_Exceptions; +with Ada.Unchecked_Conversion; +with Interfaces.C; with System; use System; with GNAT.OS_Lib; use GNAT.OS_Lib; @@ -42,6 +44,9 @@ MAP_SHARED : constant Mmap_Flags := 16#01#; MAP_PRIVATE : constant Mmap_Flags := 16#02#; + function From_Advice is new Ada.Unchecked_Conversion + (Use_Advice, Interfaces.C.int); + function Mmap (Start : Standard.System.Address := Null_Address; Length : File_Size; Prot : Mmap_Prot := PROT_READ; @@ -56,8 +61,7 @@ procedure Madvise (Addr : Standard.System.Address; Length : File_Size; - Advice : Use_Advice); - pragma Import (C, Madvise, "gnatcoll_madvise"); + Advice : Use_Advice) with Inline; -- Allows a process that has knowledge of its memory behavior to -- describe it to the system. This advice applies to the mapped -- region at address Addr, and for the given Length. If Length @@ -71,6 +75,23 @@ -- Wheter memory mapping is actually available on this system. It is an -- error to use Create_Mapping and Dispose_Mapping if this is False. + ------------- + -- Madvise -- + ------------- + + procedure Madvise (Addr : Standard.System.Address; + Length : File_Size; + Advice : Use_Advice) + is + procedure Internal + (Addr : Standard.System.Address; + Length : File_Size; + Advice : Interfaces.C.int); + pragma Import (C, Internal, "gnatcoll_madvise"); + begin + Internal (Addr, Length, From_Advice (Advice)); + end Madvise; + --------------- -- Open_Read -- --------------- diff -Nru libgnatcoll-18/src/gnatcoll-mmap-system__unix.ads libgnatcoll-19/src/gnatcoll-mmap-system__unix.ads --- libgnatcoll-18/src/gnatcoll-mmap-system__unix.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-mmap-system__unix.ads 2019-05-16 17:44:09.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2007-2017, AdaCore -- +-- Copyright (C) 2007-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -25,7 +25,7 @@ with GNAT.OS_Lib; --- OS pecularities abstraction package for Unix systems. +-- OS peculiarities abstraction package for Unix systems. package GNATCOLL.Mmap.System is @@ -88,7 +88,7 @@ -- Create a memory mapping for the given File, for the area starting at -- Offset and containing Length bytes. Store it to Mapping. -- Note that Offset and Length may be modified according to the system - -- needs (for boudaries, for instance). The caller must cope with actually + -- needs (for boundaries, for instance). The caller must cope with actually -- wider mapped areas. procedure Dispose_Mapping diff -Nru libgnatcoll-18/src/gnatcoll-mmap-system__win32.adb libgnatcoll-19/src/gnatcoll-mmap-system__win32.adb --- libgnatcoll-18/src/gnatcoll-mmap-system__win32.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-mmap-system__win32.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2007-2017, AdaCore -- +-- Copyright (C) 2007-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -57,8 +57,8 @@ Codec.From_UTF8 (Filename) & Wide_Character'Val (0); File_Handle, Mapping_Handle : HANDLE; - SizeH : aliased DWORD; - Size : File_Size; + Size : aliased LARGE_INTEGER; + Status : BOOL; begin if Write then dwDesiredAccess := GENERIC_READ + GENERIC_WRITE; @@ -83,34 +83,41 @@ -- Compute its size - Size := File_Size (Win.GetFileSize (File_Handle, SizeH'Access)); + Status := Win.GetFileSizeEx (File_Handle, Size'Access); - if Size = Win.INVALID_FILE_SIZE then - raise Ada.IO_Exceptions.Use_Error; + if Status = Win.FALSE then + -- Raise an error either if we can't compute the size. + raise Ada.IO_Exceptions.Use_Error with "cannot compute file size"; end if; - if SizeH /= 0 and then File_Size'Size > 32 then - Size := Size + (File_Size (SizeH) * 2 ** 32); + if File_Size'Size <= 32 and then Size > 2 ** 32 then + -- Likewise if user tries to map a file for which size is superior + -- than 4GB on 32bits systems. In theory this is supported but this + -- would require change in gnatcoll.mmap API. + raise Ada.IO_Exceptions.Use_Error with "cannot open file >4GB"; end if; -- Then create a mapping object, if needed. On Win32, file memory -- mapping is always available. - if Use_Mmap_If_Available then Mapping_Handle := Win.CreateFileMapping (File_Handle, null, PageFlags, - 0, DWORD (Size), Standard.System.Null_Address); + DWORD (Size / 2 ** 32), + DWORD (Size mod 2 ** 32), + Standard.System.Null_Address); else Mapping_Handle := Win.INVALID_HANDLE_VALUE; end if; + -- Note that conversioin to File_Size is safe at this stage because of + -- previous checks. return (Handle => File_Handle, Mapped => Use_Mmap_If_Available, Mapping_Handle => Mapping_Handle, Write => Write, - Length => Size); + Length => File_Size (Size)); end Open_Common; --------------- @@ -214,6 +221,7 @@ is pragma Unreferenced (Advice); Flags : DWORD; + Offset64 : LARGE_INTEGER; begin if File.Write then Flags := Win.FILE_MAP_WRITE; @@ -223,6 +231,13 @@ Flags := Win.FILE_MAP_READ; end if; + -- Check that limits are valid regarding overflow and/or file size. + if Offset > File_Size'Last - Length or else + Offset + Length > File.Length + then + raise Ada.IO_Exceptions.Use_Error with "Invalid mapping limits"; + end if; + -- Adjust offset and mapping length to account for the required -- alignment of offset on page boundary. @@ -235,19 +250,32 @@ -- it on the upper page boundary, so that the whole queried area is -- covered. + -- By construction Align return an integer >= 0 lower than the + -- original one. As consequence the following 2 statements cannot + -- overflow. Addition of Get_Page_Size to length is done afterwards + -- to avoid possible overflow. Length := Length + Queried_Offset - Offset; - Length := Align (Length + Get_Page_Size - 1); + Length := Align (Length - 1); -- But do not exceed the length of the file - if Offset + Length > File.Length then + -- By construction File.Length - Offset - Length is >=0 (no overflow) + if Get_Page_Size > File.Length - Offset - Length then Length := File.Length - Offset; + else + Length := Length + Get_Page_Size; end if; end; + -- Force conversion of Offset to 64bits format in order to able to + -- split it in two DWORD on both 32bits and 64bits systems. + Offset64 := LARGE_INTEGER (Offset); + Mapping := (Address => Win.MapViewOfFile (File.Mapping_Handle, Flags, - 0, DWORD (Offset), SIZE_T (Length)), + DWORD (Offset64 / 2 ** 32), + DWORD (Offset64 mod 2 ** 32), + SIZE_T (Length)), Length => Length); end Create_Mapping; diff -Nru libgnatcoll-18/src/gnatcoll-mmap-system__win32.ads libgnatcoll-19/src/gnatcoll-mmap-system__win32.ads --- libgnatcoll-18/src/gnatcoll-mmap-system__win32.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-mmap-system__win32.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2007-2017, AdaCore -- +-- Copyright (C) 2007-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -23,7 +23,7 @@ with System; --- OS pecularities abstraction package for Win32 systems. +-- OS peculiarities abstraction package for Win32 systems. package GNATCOLL.Mmap.System is @@ -42,6 +42,7 @@ type DWORD is new Interfaces.C.unsigned_long; type LONG is new Interfaces.C.long; type SIZE_T is new Interfaces.C.size_t; + type LARGE_INTEGER is new Long_Long_Integer; type BOOL is new Interfaces.C.int; for BOOL'Size use Interfaces.C.int'Size; @@ -120,9 +121,9 @@ function CloseHandle (hObject : HANDLE) return BOOL; pragma Import (Stdcall, CloseHandle, "CloseHandle"); - function GetFileSize - (hFile : HANDLE; lpFileSizeHigh : access DWORD) return DWORD; - pragma Import (Stdcall, GetFileSize, "GetFileSize"); + function GetFileSizeEx + (hFile : HANDLE; lpFileSizeHigh : access LARGE_INTEGER) return BOOL; + pragma Import (Stdcall, GetFileSizeEx, "GetFileSizeEx"); function SetFilePointer (hFile : HANDLE; @@ -217,7 +218,7 @@ -- Create a memory mapping for the given File, for the area starting at -- Offset and containing Length bytes. Store it to Mapping. -- Note that Offset and Length may be modified according to the system - -- needs (for boudaries, for instance). The caller must cope with actually + -- needs (for boundaries, for instance). The caller must cope with actually -- wider mapped areas. procedure Dispose_Mapping diff -Nru libgnatcoll-18/src/gnatcoll-opt_parse.adb libgnatcoll-19/src/gnatcoll-opt_parse.adb --- libgnatcoll-18/src/gnatcoll-opt_parse.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-opt_parse.adb 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,1156 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2009-2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with Ada.Command_Line; +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Exceptions; +with Ada.Unchecked_Deallocation; + +with GNAT.OS_Lib; + +with GNATCOLL.VFS; + +package body GNATCOLL.Opt_Parse is + + package Cmd_Line renames Ada.Command_Line; + + function "+" + (Self : String) return XString renames To_XString; + + function "+" + (Self : XString) return String renames To_String; + + function Get_Arguments (Arguments : XString_Array) return XString_Array; + + function Parse_One_Option + (Short, Long : String; + Args : XString_Array; + Pos : Positive; + New_Pos : out Parser_Return) return XString; + + ------------------ + -- Text wrapper -- + ------------------ + + type Text_Wrapper is tagged record + Lines : XString_Vectors.Vector; + Wrap_Col : Natural := 80; + Start_Col : Natural := 0; + end record; + -- Simple abstract type to help with formatting of the outputted help text. + + subtype Col_Type is Integer range -2 .. Integer'Last; + -- Type for a column in the text wrapper. + + Current_Col : constant Col_Type := -1; + -- Constant to represent a magic value that represents the current column + + No_Col : constant Col_Type := -2; + -- Constant used to represent the absence of column + + pragma Warnings (Off, "not dispatching"); + + procedure Append_Text + (Self : in out Text_Wrapper; + Text : String; + Cut : Boolean := True); + -- Append some text to Self. If `Cut` is True, the text will be cut and + -- wrapped on every white space character encountered. + + procedure Set_Next_Start_Column + (Self : in out Text_Wrapper; Col : Col_Type := 0); + -- Trigger the text wrapper so that next time a line implicitly (through + -- wrapping) or explicitly appended, it will begin at column `Col`. + + procedure Set_Column (Self : in out Text_Wrapper; Col : Col_Type); + -- This operation will set the column to write on for the *current line* + -- to Col, and set the next start column to `Col`, so that text on + -- subsequent lines starts at `Col`. + + subtype XString_Ref is XString_Vectors.Reference_Type; + -- Shortcut for a reference to a XString + + function Append_Line + (Self : in out Text_Wrapper) return XString_Ref; + -- Append a new line to Self + + procedure Append_Line + (Self : in out Text_Wrapper; + Text : String := ""; + Col_After : Col_Type := No_Col); + -- Append a new line to Self, after appending `Text`. If + -- `Col_After` is not `No_Col`, then set the next start column to + -- `Col_After`. + + function Current_Line + (Self : in out Text_Wrapper) return XString_Ref + is + (if Self.Lines.Is_Empty + then Self.Append_Line else Self.Lines.Reference (Self.Lines.Last_Index)); + -- Return a reference to the current line. + + function Render (Self : Text_Wrapper) return String; + -- Render the content of Self to a String. + + pragma Warnings (On, "not dispatching"); + + ----------------- + -- Flag_Parser -- + ----------------- + + type Flag_Parser is new Parser_Type with record + Short, Long : XString; + end record; + + type Flag_Parser_Result is new Parser_Result with record + Result : Boolean; + end record; + + overriding function Usage + (Self : Flag_Parser) return String + is ("[" & To_String (Self.Long) & "|" & To_String (Self.Short) & "]"); + + overriding function Help_Name + (Self : Flag_Parser) return String + is + (To_String (Self.Long) & ", " & To_String (Self.Short)); + + overriding function Parse_Args + (Self : in out Flag_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return; + + overriding procedure Release (Self : in out Flag_Parser_Result) is null; + + type Help_Flag_Parser is new Flag_Parser with null record; + -- Specific subtype of Flag_Parser to designate the help flag parser. + + ----------------- + -- Append_Line -- + ----------------- + + procedure Append_Line (Self : in out Text_Wrapper; + Text : String := ""; + Col_After : Col_Type := No_Col) is + begin + if Text /= "" then + Self.Append_Text (Text); + end if; + + if Col_After /= No_Col then + Self.Set_Next_Start_Column (Col_After); + end if; + + declare + Dummy : XString_Ref := Self.Append_Line; + begin + null; + end; + end Append_Line; + + ---------------- + -- Set_Column -- + ---------------- + + procedure Set_Column + (Self : in out Text_Wrapper; Col : Col_Type) + is + begin + Self.Set_Next_Start_Column (Col); + + if Self.Current_Line.Length > Col then + Self.Append_Line; + else + Self.Append_Text + ((1 .. Col - Self.Current_Line.Length => ' '), False); + end if; + end Set_Column; + + ------------ + -- Render -- + ------------ + + function Render (Self : Text_Wrapper) return String is + Res : XString; + begin + for El of Self.Lines loop + Res.Append (El); + Res.Append (ASCII.LF); + end loop; + return +Res; + end Render; + + ----------------- + -- Append_Line -- + ----------------- + + function Append_Line + (Self : in out Text_Wrapper) return XString_Vectors.Reference_Type + is + Ret : XString; + begin + Self.Lines.Append (Ret); + + declare + L : constant XString_Ref := Self.Current_Line; + begin + if Self.Start_Col > 0 then + + L.Append ((1 .. Self.Start_Col => ' ')); + end if; + + return L; + end; + end Append_Line; + + ----------------- + -- Append_Text -- + ----------------- + + procedure Append_Text + (Self : in out Text_Wrapper; + Text : String; + Cut : Boolean := True) + is + begin + if Cut then + declare + Cut_Text : constant XString_Array := XString'(+Text).Split (' '); + begin + for I in Cut_Text'Range loop + if I > 1 then + Append_Text (Self, " ", False); + end if; + + Append_Text (Self, +(Cut_Text (I)), False); + end loop; + end; + else + declare + Cur_Line : constant XString_Ref := Self.Current_Line; + begin + if Cur_Line.Length + Text'Length <= Self.Wrap_Col then + Cur_Line.Append (Text); + return; + end if; + end; + + declare + Cur_Line : constant XString_Ref := Append_Line (Self); + begin + Cur_Line.Append (Text); + end; + + end if; + end Append_Text; + + ---------------------- + -- Set_Next_Start_Column -- + ---------------------- + + procedure Set_Next_Start_Column + (Self : in out Text_Wrapper; Col : Col_Type := 0) is + begin + if Col = Current_Col then + Self.Start_Col := Col_Type (Self.Current_Line.Length); + else + Self.Start_Col := Col; + end if; + end Set_Next_Start_Column; + + ------------------- + -- Get_Arguments -- + ------------------- + + function Get_Arguments (Arguments : XString_Array) return XString_Array is + begin + if Arguments /= No_Arguments then + return Arguments; + end if; + + declare + Args : XString_Array (1 .. Cmd_Line.Argument_Count); + begin + for I in Args'Range loop + Args (I) := +Cmd_Line.Argument (I); + end loop; + return Args; + end; + end Get_Arguments; + + ---------------- + -- Get_Result -- + ---------------- + + function Get_Result + (Self : Parser_Type'Class; + Args : Parsed_Arguments) return Parser_Result_Access + is + -- Due to controlled objects finalization, the following code is not + -- thread safe, so we use a critical section here, so that Get functions + -- for arguments are thread safe. + + Dummy : Scoped_Lock (Self.Parser.Mutex'Access); + begin + declare + Real_Args : Parsed_Arguments; + begin + if Args = No_Parsed_Arguments then + Real_Args := Self.Parser.Default_Result; + else + Real_Args := Args; + end if; + + if Real_Args = No_Parsed_Arguments then + raise Opt_Parse_Error with "No results for command line arguments"; + end if; + + return Real_Args.Ref.Get.Results (Self.Position); + end; + end Get_Result; + + ---------------- + -- Has_Result -- + ---------------- + + function Has_Result + (Self : Parser_Type'Class; + Args : Parsed_Arguments) return Boolean is + begin + return Self.Get_Result (Args) /= null; + end Has_Result; + + ----------- + -- Parse -- + ----------- + + function Parse + (Self : in out Argument_Parser; + Arguments : XString_Array := No_Arguments) return Boolean + is + begin + if Self.Data.Default_Result /= No_Parsed_Arguments then + Self.Data.Default_Result := No_Parsed_Arguments; + end if; + + return Ret : constant Boolean + := Self.Parse (Arguments, Self.Data.Default_Result) + do + if not Ret then + Put_Line (Help (Self)); + end if; + end return; + end Parse; + + ----------- + -- Parse -- + ----------- + + function Parse + (Self : in out Argument_Parser; + Arguments : XString_Array := No_Arguments; + Result : out Parsed_Arguments) return Boolean + is + + Current_Arg : Positive := 1; + Cmd_Line_Args : constant XString_Array := Get_Arguments (Arguments); + + procedure Handle_Failure (Error_Msg : String); + + -------------------- + -- Handle_Failure -- + -------------------- + + procedure Handle_Failure (Error_Msg : String) is + begin + Put_Line + ("Argument parsing failed: " & Error_Msg); + end Handle_Failure; + + begin + Result.Ref.Set + (Parsed_Arguments_Type' + (Raw_Args => new XString_Array'(Cmd_Line_Args), + Results => new Parser_Result_Array + (1 .. Self.Data.All_Parsers.Last_Index))); + + while Current_Arg <= Cmd_Line_Args'Last loop + + for Opt_Parser of Self.Data.Opts_Parsers loop + begin + declare + P_Return : constant Parser_Return := + Opt_Parser.Parse (Cmd_Line_Args, Current_Arg, Result); + begin + if P_Return /= Error_Return then + Current_Arg := Positive (P_Return); + + if Opt_Parser.all in Help_Flag_Parser'Class then + Put_Line (Self.Help); + GNAT.OS_Lib.OS_Exit (0); + end if; + + goto Next_Iter; + end if; + end; + exception + when E : Opt_Parse_Error => + Handle_Failure + ("for option " & (+Opt_Parser.Name) & " - " + & Ada.Exceptions.Exception_Message (E)); + return False; + end; + end loop; + + for Pos_Parser of Self.Data.Positional_Args_Parsers loop + begin + declare + P_Return : constant Parser_Return := + Pos_Parser.Parse (Cmd_Line_Args, Current_Arg, Result); + begin + if P_Return /= Error_Return then + Current_Arg := Positive (P_Return); + goto Next_Iter; + end if; + end; + exception + when E : Opt_Parse_Error => + Handle_Failure + ("for parser " & (+Pos_Parser.Name) & " - " + & Ada.Exceptions.Exception_Message (E)); + return False; + end; + end loop; + + Handle_Failure + ("Unrecognized argument " & (+Cmd_Line_Args (Current_Arg))); + return False; + + <> + end loop; + + for Parser of Self.Data.All_Parsers loop + if not Parser.Opt and then not Parser.Has_Result (Result) then + Handle_Failure ("Missing value for " & (+Parser.Name)); + return False; + end if; + end loop; + + return True; + exception + when E : Opt_Parse_Error => + Handle_Failure (Ada.Exceptions.Exception_Message (E)); + return False; + end Parse; + + ----------- + -- Parse -- + ----------- + + function Parse + (Self : in out Parser_Type'Class; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return + is + begin + if Self.Has_Result (Result) and then not Self.Does_Accumulate then + return Error_Return; + end if; + + return Self.Parse_Args (Args, Pos, Result); + end Parse; + + ------------------------------- + -- Parse_Positional_Arg_List -- + ------------------------------- + + package body Parse_Positional_Arg_List is + type Result_Array_Access is access all Result_Array; + + type Positional_Arg_List_Parser is new Parser_Type with record + null; + end record; + + overriding function Parse_Args + (Self : in out Positional_Arg_List_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return; + + overriding function Usage + (Self : Positional_Arg_List_Parser) return String + is (Name & " [" & Name & " ...]"); + + type Internal_Result is new Parser_Result with record + Results : Result_Array_Access; + end record; + + type Internal_Result_Access is access all Internal_Result; + + overriding procedure Release (Self : in out Internal_Result); + + Self_Val : aliased Positional_Arg_List_Parser := + Positional_Arg_List_Parser' + (Name => +Name, + Help => +Help, + Parser => Parser.Data, + Position => <>, + Opt => Allow_Empty); + + Self : constant Parser_Access := Self_Val'Unchecked_Access; + + --------- + -- Get -- + --------- + + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Result_Array + is + (if Self.Has_Result (Args) + then Internal_Result (Self.Get_Result (Args).all).Results.all + else No_Results); + + ---------------- + -- Parse_Args -- + ---------------- + + overriding function Parse_Args + (Self : in out Positional_Arg_List_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return + is + Last : Parser_Return := Error_Return; + begin + for I in Pos .. Args'Last loop + if Args (I).Starts_With ("--") or Args (I).Starts_With ("-") then + exit; + end if; + + Last := I; + end loop; + + if Last = Error_Return then + return Error_Return; + end if; + + declare + R : Result_Array (1 .. Last - Pos + 1); + begin + for I in R'Range loop + R (I) := Convert (+Args (I + Pos - 1)); + end loop; + + declare + Res : constant Internal_Result_Access := new Internal_Result' + (Start_Pos => Pos, + End_Pos => Last, + Results => new Result_Array'(R)); + begin + Result.Ref.Get.Results (Self.Position) := + Res.all'Unchecked_Access; + end; + + end; + + return Parser_Return (Last + 1); + end Parse_Args; + + overriding procedure Release (Self : in out Internal_Result) is + procedure Free is new Ada.Unchecked_Deallocation + (Result_Array, Result_Array_Access); + begin + Free (Self.Results); + end Release; + + begin + Parser.Data.Positional_Args_Parsers.Append (Self); + Parser.Data.All_Parsers.Append (Self); + Self.Position := Parser.Data.All_Parsers.Last_Index; + end Parse_Positional_Arg_List; + + -------------------------- + -- Parse_Positional_Arg -- + -------------------------- + + package body Parse_Positional_Arg is + + type Positional_Arg_Parser is new Parser_Type with record + null; + end record; + + overriding function Parse_Args + (Self : in out Positional_Arg_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return; + + overriding function Usage + (Self : Positional_Arg_Parser) return String + is (Name); + + type Internal_Result is new Parser_Result with record + Result : Arg_Type; + end record; + + type Internal_Result_Access is access all Internal_Result; + + overriding procedure Release (Self : in out Internal_Result) is null; + + Self_Val : aliased Positional_Arg_Parser := + (Name => +Name, + Help => +Help, + Parser => Parser.Data, + Position => <>, + Opt => False); + + Self : constant Parser_Access := Self_Val'Unchecked_Access; + + --------- + -- Get -- + --------- + + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Arg_Type + is + (Internal_Result (Self.Get_Result (Args).all).Result); + + ---------------- + -- Parse_Args -- + ---------------- + + overriding function Parse_Args + (Self : in out Positional_Arg_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return + is + begin + if Args (Pos).Starts_With ("--") or Args (Pos).Starts_With ("-") then + return Error_Return; + end if; + + declare + Res : constant Arg_Type := Convert (+Args (Pos)); + Int_Res : constant Internal_Result_Access := new Internal_Result' + (Start_Pos => Pos, + End_Pos => Pos, + Result => Res); + begin + Result.Ref.Get.Results (Self.Position) := + Int_Res.all'Unchecked_Access; + end; + + return Parser_Return (Pos + 1); + end Parse_Args; + + begin + Parser.Data.Positional_Args_Parsers.Append (Self); + Parser.Data.All_Parsers.Append (Self); + Self.Position := Parser.Data.All_Parsers.Last_Index; + end Parse_Positional_Arg; + + ---------------- + -- Parse_Args -- + ---------------- + + overriding function Parse_Args + (Self : in out Flag_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return + is + begin + if Args (Pos) = Self.Long or else Args (Pos) = Self.Short then + + declare + Res : constant Parser_Result_Access := new Flag_Parser_Result' + (Start_Pos => Pos, + End_Pos => Pos, + Result => True); + begin + Result.Ref.Get.Results (Self.Position) := Res; + end; + + return Parser_Return (Pos + 1); + else + return Error_Return; + end if; + end Parse_Args; + + ---------------- + -- Parse_Flag -- + ---------------- + + package body Parse_Flag is + + Self_Val : aliased Flag_Parser := Flag_Parser' + (Name => +Long (3 .. Long'Last), + Help => +Help, + Long => +Long, + Short => +Short, + Parser => Parser.Data, + Opt => True, + Position => <>); + + Self : constant Parser_Access := Self_Val'Unchecked_Access; + + --------- + -- Get -- + --------- + + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Boolean + is + R : constant Parser_Result_Access := Self.Get_Result (Args); + begin + if R /= null then + return Flag_Parser_Result (R.all).Result; + else + return False; + end if; + end Get; + + begin + Parser.Data.Opts_Parsers.Append (Self); + Parser.Data.All_Parsers.Append (Self); + Self.Position := Parser.Data.All_Parsers.Last_Index; + end Parse_Flag; + + ------------------ + -- Parse_Option -- + ------------------ + + package body Parse_Option is + + type Option_Parser is new Parser_Type with record + null; + end record; + + overriding function Usage + (Self : Option_Parser) return String + is ("[" & Long & "|" & Short & " " + & To_Upper (Long (3 .. Long'Last)) & "]"); + + overriding function Help_Name + (Dummy : Option_Parser) return String + is + (Long & ", " & Short); + + overriding function Parse_Args + (Self : in out Option_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return; + + type Internal_Result is new Parser_Result with record + Result : Arg_Type; + end record; + + type Internal_Result_Access is access all Internal_Result; + + procedure Release (Self : in out Internal_Result) is null; + + Self_Val : aliased Option_Parser := + Option_Parser' + (Name => +Long (3 .. Long'Last), + Help => +Help, + Parser => Parser.Data, + Opt => True, + Position => <>); + + Self : constant Parser_Access := Self_Val'Unchecked_Access; + + --------- + -- Get -- + --------- + + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Arg_Type + is + R : constant Parser_Result_Access := Self.Get_Result (Args); + begin + if R /= null then + return Internal_Result (R.all).Result; + else + return Default_Val; + end if; + end Get; + + ---------------- + -- Parse_Args -- + ---------------- + + overriding function Parse_Args + (Self : in out Option_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return + is + New_Pos : Parser_Return; + Raw : constant XString := + Parse_One_Option (Short, Long, Args, Pos, New_Pos); + begin + + if New_Pos /= Error_Return then + declare + Res : constant Internal_Result_Access := + new Internal_Result'(Start_Pos => Pos, + End_Pos => Pos, + Result => Convert (+Raw)); + begin + Result.Ref.Get.Results (Self.Position) := + Res.all'Unchecked_Access; + end; + end if; + + return New_Pos; + end Parse_Args; + + begin + Parser.Data.Opts_Parsers.Append (Self); + Parser.Data.All_Parsers.Append (Self); + Self.Position := Parser.Data.All_Parsers.Last_Index; + end Parse_Option; + + ----------------------- + -- Parse_Option_List -- + ----------------------- + + package body Parse_Option_List is + + package Result_Vectors + is new Ada.Containers.Vectors (Positive, Arg_Type); + + type Option_List_Parser is new Parser_Type with record + null; + end record; + + overriding function Usage + (Self : Option_List_Parser) return String + is ("[" & Long & "|" & Short & " " + & To_Upper (Long (3 .. Long'Last)) + & "[" & To_Upper (Long (3 .. Long'Last)) & "...]]"); + + overriding function Help_Name + (Dummy : Option_List_Parser) return String + is + (Long & ", " & Short); + + overriding function Parse_Args + (Self : in out Option_List_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return; + + overriding function Does_Accumulate + (Self : Option_List_Parser) return Boolean is (Accumulate); + + type Internal_Result is new Parser_Result with record + Results : Result_Vectors.Vector; + end record; + + type Internal_Result_Access is access all Internal_Result; + + procedure Release (Self : in out Internal_Result) is null; + + Self_Val : aliased Option_List_Parser := + (Name => +Long (3 .. Long'Last), + Help => +Help, + Parser => Parser.Data, + Opt => True, + Position => <>); + + Self : constant Parser_Access := Self_Val'Unchecked_Access; + + --------- + -- Get -- + --------- + + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Result_Array + is + R : constant Parser_Result_Access := Self.Get_Result (Args); + begin + if R /= null then + declare + Res : Result_Array + (1 .. Internal_Result (R.all).Results.Last_Index); + begin + for I in Res'Range loop + Res (I) := Internal_Result (R.all).Results (I); + end loop; + return Res; + end; + else + return No_Results; + end if; + end Get; + + ---------------- + -- Parse_Args -- + ---------------- + + overriding function Parse_Args + (Self : in out Option_List_Parser; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return + is + Last : Parser_Return := Error_Return; + + Res : Parser_Result_Access + renames Result.Ref.Get.Results (Self.Position); + + Tmp : Internal_Result_Access := null; + + begin + if Accumulate then + declare + New_Pos : Parser_Return; + Raw : constant XString := + Parse_One_Option (Short, Long, Args, Pos, New_Pos); + begin + if New_Pos /= Error_Return then + if Res = null then + Tmp := + new Internal_Result' + (Start_Pos => Pos, + End_Pos => Pos, + Results => Result_Vectors.Empty_Vector); + + Res := Tmp.all'Unchecked_Access; + end if; + + Internal_Result (Res.all).Results.Append (Convert (+Raw)); + end if; + + return New_Pos; + end; + end if; + + if Args (Pos) /= +Long and then Args (Pos) /= +Short then + return Error_Return; + end if; + + for I in Pos + 1 .. Args'Last loop + if Args (I).Starts_With ("--") or Args (I).Starts_With ("-") then + exit; + end if; + + Last := I; + end loop; + + if Last = Error_Return then + return Error_Return; + end if; + + Tmp := new Internal_Result' + (Start_Pos => Pos, + End_Pos => Last, + Results => Result_Vectors.Empty_Vector); + + Res := Tmp.all'Unchecked_Access; + + for I in 1 .. Last - Pos + 1 loop + Internal_Result (Res.all).Results (I) := Convert (+Args (I + Pos)); + end loop; + + return Parser_Return (Last + 1); + end Parse_Args; + + begin + Parser.Data.Opts_Parsers.Append (Self); + Parser.Data.All_Parsers.Append (Self); + Self.Position := Parser.Data.All_Parsers.Last_Index; + end Parse_Option_List; + + ---------------------------- + -- Create_Argument_Parser -- + ---------------------------- + + function Create_Argument_Parser + (Help : String; Command_Name : String := "") return Argument_Parser + is + XCommand_Name : constant XString := + +(if Command_Name = "" + then String + (VFS.Base_Name + (VFS.Create + (VFS.Filesystem_String (Ada.Command_Line.Command_Name)))) + else Command_Name); + begin + return Parser : Argument_Parser do + Parser.Data := + new Argument_Parser_Data'(+Help, XCommand_Name, others => <>); + Parser.Data.Help_Flag := new Help_Flag_Parser' + (Name => +"help", + Help => +"Show this help message", + Position => <>, + Opt => True, + Parser => Parser.Data, + Short => +"-h", + Long => +"--help"); + Parser.Data.Opts_Parsers.Append (Parser.Data.Help_Flag); + Parser.Data.All_Parsers.Append (Parser.Data.Help_Flag); + Parser.Data.Help_Flag.Position := Parser.Data.All_Parsers.Last_Index; + end return; + end Create_Argument_Parser; + + ---------- + -- Help -- + ---------- + + function Help (Self : Argument_Parser) return String is + Ret : Text_Wrapper; + begin + -- Usage + + Ret.Append_Text ("usage: " & (+Self.Data.Command_Name)); + Ret.Set_Next_Start_Column (Current_Col); + + Ret.Append_Text (" "); + + for Parser of Self.Data.All_Parsers loop + Ret.Append_Text (Parser.Usage); + Ret.Append_Text (" "); + end loop; + + Ret.Append_Line (Col_After => 0); + Ret.Append_Line; + + -- Main help + Ret.Append_Text (+Self.Data.Help); + Ret.Append_Line; + Ret.Append_Line; + + Ret.Append_Line ("positional arguments:", Col_After => 3); + + for Parser of Self.Data.Positional_Args_Parsers loop + Ret.Append_Text (Parser.Help_Name); + Ret.Set_Column (25); + + Ret.Append_Line (+Parser.Help, Col_After => 3); + end loop; + + Ret.Append_Line (Col_After => 0); + Ret.Append_Line ("optional arguments:", Col_After => 3); + + for Parser of Self.Data.Opts_Parsers loop + Ret.Append_Text (Parser.Help_Name); + Ret.Set_Column (25); + + Ret.Append_Line (+Parser.Help, Col_After => 3); + end loop; + + return Ret.Render; + end Help; + + ------------- + -- Convert -- + ------------- + + function Convert (Arg : String) return Integer is + begin + return Integer'Value (Arg); + exception + when Constraint_Error => + raise Opt_Parse_Error with "wrong value for Integer: """ & Arg & """"; + end Convert; + + ---------------------- + -- Parse_One_Option -- + ---------------------- + + function Parse_One_Option + (Short, Long : String; + Args : XString_Array; + Pos : Positive; + New_Pos : out Parser_Return) return XString + is + begin + + if + Args (Pos) = Long + or else (Short /= "" and then Args (Pos) = Short) + then + if Pos + 1 > Args'Last then + raise Opt_Parse_Error with "Incomplete option"; + end if; + New_Pos := Pos + 2; + return Args (Pos + 1); + + elsif Args (Pos).Starts_With (Long & "=") then + New_Pos := Pos + 1; + return Args (Pos).Slice (Long'Last + 2, Args (Pos).Length); + + elsif Short /= "" and then Args (Pos).Starts_With (Short) then + New_Pos := Pos + 1; + return Args (Pos).Slice (Short'Last + 1, Args (Pos).Length); + else + New_Pos := Error_Return; + return +""; + end if; + end Parse_One_Option; + + ------------- + -- Release -- + ------------- + + procedure Release (Self : in out Parsed_Arguments_Type) is + procedure Free is new Ada.Unchecked_Deallocation + (Parser_Result'Class, Parser_Result_Access); + procedure Free is new Ada.Unchecked_Deallocation + (Parser_Result_Array, Parser_Result_Array_Access); + procedure Free is new Ada.Unchecked_Deallocation + (XString_Array, XString_Array_Access); + begin + Free (Self.Raw_Args); + for R of Self.Results.all loop + if R /= null then + R.Release; + end if; + Free (R); + end loop; + Free (Self.Results); + end Release; + + -------------- + -- Finalize -- + -------------- + + overriding procedure Finalize (Self : in out Argument_Parser) is + procedure Free is new Ada.Unchecked_Deallocation + (Argument_Parser_Data, Argument_Parser_Data_Access); + + procedure Free is new Ada.Unchecked_Deallocation + (Parser_Type'Class, Parser_Access); + begin + Free (Self.Data.Help_Flag); + Free (Self.Data); + end Finalize; + +end GNATCOLL.Opt_Parse; diff -Nru libgnatcoll-18/src/gnatcoll-opt_parse.ads libgnatcoll-19/src/gnatcoll-opt_parse.ads --- libgnatcoll-18/src/gnatcoll-opt_parse.ads 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-opt_parse.ads 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,446 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2009-2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with Ada.Finalization; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + +with GNATCOLL.Strings; use GNATCOLL.Strings; + +private with Ada.Containers.Vectors; +private with GNATCOLL.Refcount; +private with GNATCOLL.Locks; + +package GNATCOLL.Opt_Parse is + + -- WARNING: The interface of this package is still unstable. No guarantees + -- of API stability. USE AT YOUR OWN RISK. + -- + -- This package is meant to create powerful command line argument parsers + -- in a declarative fashion. The generated argument parsers have a typed + -- interface, in that, you can specify the types of expected arguments and + -- options, and get a statically typed API to access the results. + -- + -- Here is a small example of how to create a command line argument parser + -- and how to use it: + -- + -- with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + -- with Ada.Text_IO; use Ada.Text_IO; + -- with GNATCOLL.Opt_Parse; use GNATCOLL.Opt_Parse; + -- + -- procedure Main is + -- + -- package Arg is + -- Parser : Argument_Parser := Create_Argument_Parser + -- (Help => "Help string for the parser"); + -- + -- package Files is new Parse_Positional_Arg_List + -- (Parser => Parser, + -- Name => "files", + -- Arg_Type => Unbounded_String, + -- Help => "The files to parse"); + -- + -- package Quiet is new Parse_Flag + -- (Parser => Parser, + -- Short => "-q", + -- Long => "--quiet", + -- Help => "Whether the tool should be quiet or not"); + -- + -- package Charset is new Parse_Option + -- (Parser => Parser, + -- Short => "-C", + -- Long => "--charset", + -- Arg_Type => Unbounded_String, + -- Help => + -- "What charset to use for the analysis context. " + -- & "Default is ""latin-1""", + -- Default_Val => To_Unbounded_String ("latin-1")); + -- end Arg; + -- + -- begin + -- + -- if Arg.Parser.Parse then + -- + -- Put_Line ("Charset = " & To_String (Arg.Charset.Get)); + -- for F of Arg.Files.Get loop + -- if not Arg.Quiet.Get then + -- Put_Line ("Got file " & To_String (F)); + -- end if; + -- end loop; + -- end if; + -- + -- end Main; + + ------------------------ + -- General API types -- + ------------------------ + + type Argument_Parser is tagged limited private; + -- Base type for the Opt_Parse API. Represents a general parser to which + -- you will associate specific argument parsers. + + type Parsed_Arguments is private; + -- Type containing the result of an argument parse. Please note you do + -- not need to handle the return value if you don't want to, in which case + -- you will be able to access argument values directly via the generic Get + -- functions. + + No_Arguments : constant XString_Array (1 .. 0) := (others => <>); + -- Constant for the absence of command line arguments + + No_Parsed_Arguments : constant Parsed_Arguments; + -- Constant for a null Parsed_Arguments value + + function Parse + (Self : in out Argument_Parser; + Arguments : XString_Array := No_Arguments) return Boolean; + -- Parse the command line arguments for Self. + + function Parse + (Self : in out Argument_Parser; + Arguments : XString_Array := No_Arguments; + Result : out Parsed_Arguments) return Boolean; + -- Parse command line arguments for Self. Return arguments explicitly. + + function Create_Argument_Parser + (Help : String; Command_Name : String := "") return Argument_Parser; + -- Create an argument parser with the provided help string. + + function Help (Self : Argument_Parser) return String; + -- Return the help for this parser as a String. + + -------------------------- + -- Conversion functions -- + -------------------------- + + -- Convenience conversion functions that are meant to be used in + -- instantiations. + + function Convert + (Arg : String) return XString renames To_XString; + + function Convert + (Arg : String) return Unbounded_String renames To_Unbounded_String; + + function Convert (Arg : String) return Integer; + + Opt_Parse_Error : exception; + -- Exception signaling an error in the parser. This is the error that you + -- will get in the rare cases where you do something invalid with a Parser + -- (such as querying results without calling parse first), and this is + -- also the exception that you should raise in conversion functions when + -- receiving an invalid value. + + -------------------------------- + -- Specific argument parsers -- + -------------------------------- + + generic + Parser : in out Argument_Parser; + -- Argument_Parser owning this argument. + + Name : String; + -- Name of the argument in the parser. Used mainly to formal the help + -- output. + + Help : String; + -- Help string for the argument. + + Allow_Empty : Boolean := False; + -- Whether empty lists are allowed or not. + + type Arg_Type is private; + -- Type of the elements contained in the list. + + with function Convert (Arg : String) return Arg_Type is <>; + -- Conversion function to convert from a raw string argument to the + -- argument type. + + package Parse_Positional_Arg_List is + type Result_Array is array (Positive range <>) of Arg_Type; + + No_Results : constant Result_Array (1 .. 0) := (others => <>); + + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Result_Array; + + end Parse_Positional_Arg_List; + -- Parse a list of positional arguments. This parser can only be the last + -- positional parser, since it will parse every remaining argument on the + -- command line. + + generic + Parser : in out Argument_Parser; + -- Argument_Parser owning this argument. + + Name : String; + -- Name of the argument in the parser. Used mainly to formal the help + -- output. + + Help : String := ""; + -- Help string for the argument. + + type Arg_Type is private; + -- Type of the positional argument. + + with function Convert (Arg : String) return Arg_Type is <>; + -- Conversion function to convert from a raw string argument to the + -- argument type. + + package Parse_Positional_Arg is + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Arg_Type; + end Parse_Positional_Arg; + -- Parse a positional argument. A positional argument is any argument. If + -- the conversion fails, then it will make the whole argument parser fail. + + generic + Parser : in out Argument_Parser; + -- Argument_Parser owning this argument. + + Short : String := ""; + -- Short form for this flag. Should start with one dash and be followed + -- by one or two alphanumeric characters. + + Long : String; + -- Long form for this flag. Should start with two dashes. + + Help : String := ""; + -- Help string for the argument. + package Parse_Flag is + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Boolean; + end Parse_Flag; + -- Parse a Flag option. A flag takes no other argument, and its result is a + -- boolean: False if the flag is not passed, True otherwise. + + generic + Parser : in out Argument_Parser; + -- Argument_Parser owning this argument. + + Short : String := ""; + -- Short form for this flag. Should start with one dash and be followed + -- by one or two alphanumeric characters. + + Long : String; + -- Long form for this flag. Should start with two dashes. + + Help : String := ""; + -- Help string for the argument. + + type Arg_Type is private; + -- Type of the option. + + with function Convert (Arg : String) return Arg_Type is <>; + -- Conversion function to convert from a raw string argument to the + -- argument type. + + Default_Val : Arg_Type; + -- Default value if the option is not passed. + + package Parse_Option is + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Arg_Type; + end Parse_Option; + -- Parse a regular option. A regular option is of the form "--option val", + -- or "--option=val", or "-O val", or "-Oval". If option is not passed, + -- takes the default value. + + generic + Parser : in out Argument_Parser; + -- Argument_Parser owning this argument. + + Short : String := ""; + -- Short form for this flag. Should start with one dash and be followed + -- by one or two alphanumeric characters. + + Long : String; + -- Long form for this flag. Should start with two dashes. + + Help : String := ""; + -- Help string for the argument. + + Accumulate : Boolean := False; + -- If True, then this argument can be passed several times and behaves + -- each time as a regular option, only with results accumulated in the + -- result list. If False, user needs to pass a list of values after the + -- flag name. + + type Arg_Type is private; + -- Type of the option list. + + with function Convert (Arg : String) return Arg_Type is <>; + -- Conversion function to convert from a raw string argument to the + -- argument type. + + package Parse_Option_List is + type Result_Array is array (Positive range <>) of Arg_Type; + + No_Results : constant Result_Array (1 .. 0) := (others => <>); + + function Get + (Args : Parsed_Arguments := No_Parsed_Arguments) return Result_Array; + end Parse_Option_List; + -- Parse an option list. A regular option is of the form + -- "--option val, val2, val3", or "-O val val2 val3". + -- + -- Values cannot start with - or --. + -- + -- If Accumulate is True, mix between option and option list. Parses like + -- regular option, which you can parse several time, and put results in a + -- list. + +private + + use GNATCOLL.Locks; + + type Argument_Parser_Data; + type Argument_Parser_Data_Access is access all Argument_Parser_Data; + + package XString_Vectors is new Ada.Containers.Vectors (Positive, XString); + + type Parser_Type is abstract tagged record + Name : XString; + -- Name of the parser + + Help : XString; + -- Help string for the parser + + Position : Positive; + -- Position of this parser in its enclosing Arguments_Parser + + Opt : Boolean := True; + -- Whether this parser is optional or not + + Parser : Argument_Parser_Data_Access; + end record; + + subtype Parser_Return is Integer range -1 .. Integer'Last; + -- Return value of a Parser. Represents a position, except for the special + -- value Error_Return. + + Error_Return : constant Parser_Return := 0; + -- Special value for Parser_Return when there was an error + + function Parse_Args + (Self : in out Parser_Type; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return + is abstract; + -- Return the result of parsing arguments for this parser. Abstract method + -- that must be overloaded by implementations. + + function Parse + (Self : in out Parser_Type'Class; + Args : XString_Array; + Pos : Positive; + Result : in out Parsed_Arguments) return Parser_Return; + -- Return the result of parsing arguments for this parser. Function wrapper + -- around `Parse_Args` that is called by Arguments_Parser. + + function Usage + (Self : Parser_Type) return String is abstract; + -- Return a usage string for this parser. Abstract method that must be + -- overloaded. + + function Help_Name + (Self : Parser_Type) return String + is + (To_String (Self.Name)); + -- Return the help name for this parser. + + function Does_Accumulate + (Self : Parser_Type) return Boolean is (False); + -- Whether this parser accumulates results or not. If it does, then it is + -- valid to call Parse on it several time, which will add to results. + + type Parser_Access is access all Parser_Type'Class; + + package Parsers_Vectors + is new Ada.Containers.Vectors (Positive, Parser_Access); + + subtype Parser_Vector is Parsers_Vectors.Vector; + + type Argument_Parser_Data is record + Help, Command_Name : XString; + Positional_Args_Parsers, Opts_Parsers : Parser_Vector; + All_Parsers : Parser_Vector; + Default_Result : Parsed_Arguments + := No_Parsed_Arguments; + Help_Flag : Parser_Access := null; + + Mutex : aliased Mutual_Exclusion; + -- Mutex used to make Get_Result thread safe + end record; + + type Parser_Result is abstract tagged record + Start_Pos, End_Pos : Positive; + end record; + + procedure Release (Result : in out Parser_Result) is abstract; + -- Derived types must override this to clean-up internal data when the + -- Parser_Result object is about to be deallocated. + + type Parser_Result_Access is access all Parser_Result'Class; + + function Get_Result + (Self : Parser_Type'Class; + Args : Parsed_Arguments) return Parser_Result_Access; + + function Has_Result + (Self : Parser_Type'Class; + Args : Parsed_Arguments) return Boolean; + + type Parser_Result_Array + is array (Positive range <>) of Parser_Result_Access; + + type Parser_Result_Array_Access is access all Parser_Result_Array; + + type XString_Array_Access is access all XString_Array; + + type Parsed_Arguments_Type is record + Raw_Args : XString_Array_Access; + Results : Parser_Result_Array_Access; + end record; + + procedure Release (Self : in out Parsed_Arguments_Type); + + package Parsed_Arguments_Shared_Ptrs + is new GNATCOLL.Refcount.Shared_Pointers + (Parsed_Arguments_Type, Release => Release, Atomic_Counters => True); + + type Parsed_Arguments is record + Ref : Parsed_Arguments_Shared_Ptrs.Ref + := Parsed_Arguments_Shared_Ptrs.Null_Ref; + end record; + + No_Parsed_Arguments : constant Parsed_Arguments := + (Ref => Parsed_Arguments_Shared_Ptrs.Null_Ref); + + type Argument_Parser is new Ada.Finalization.Limited_Controlled with record + Data : Argument_Parser_Data_Access := null; + end record; + + overriding procedure Finalize (Self : in out Argument_Parser); + +end GNATCOLL.Opt_Parse; diff -Nru libgnatcoll-18/src/gnatcoll-path.ads libgnatcoll-19/src/gnatcoll-path.ads --- libgnatcoll-18/src/gnatcoll-path.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-path.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2009-2017, AdaCore -- +-- Copyright (C) 2009-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -62,7 +62,7 @@ function Is_Absolute_Path (FS : FS_Type; Path : FS_String) return Boolean; - -- Tell wether the path is absolute + -- Tell whether the path is absolute ------------------------ -- Path manipulations -- diff -Nru libgnatcoll-18/src/gnatcoll-pools.adb libgnatcoll-19/src/gnatcoll-pools.adb --- libgnatcoll-18/src/gnatcoll-pools.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-pools.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ --- M O D E L I N G -- +-- G N A T C O L L -- -- -- --- Copyright (C) 2010-2017, AdaCore -- +-- Copyright (C) 2010-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff -Nru libgnatcoll-18/src/gnatcoll-pools.ads libgnatcoll-19/src/gnatcoll-pools.ads --- libgnatcoll-18/src/gnatcoll-pools.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-pools.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ --- M O D E L I N G -- +-- G N A T C O L L -- -- -- --- Copyright (C) 2010-2017, AdaCore -- +-- Copyright (C) 2010-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff -Nru libgnatcoll-18/src/gnatcoll-projects.adb libgnatcoll-19/src/gnatcoll-projects.adb --- libgnatcoll-18/src/gnatcoll-projects.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-projects.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2002-2018, AdaCore -- +-- Copyright (C) 2002-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -25,6 +25,8 @@ with Ada.Calendar; use Ada.Calendar; with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Containers.Hashed_Sets; +with Ada.Containers.Ordered_Sets; +with Ada.Containers.Generic_Array_Sort; with Ada.Directories; with Ada.Exceptions; use Ada.Exceptions; with Ada.Strings; use Ada.Strings; @@ -66,6 +68,8 @@ with GPR.Tree; use GPR.Tree; with GPR.Sinput; with GPR.Snames; use GPR.Snames; +with GPR.Knowledge; +with GPR.Sdefault; package body GNATCOLL.Projects is @@ -123,11 +127,14 @@ -- In some case, Lang might be set to Unknown_Language, if the file was -- set in the project (for instance through the Source_Files attribute), -- but no matching language was found. - -- Next is only relevant when root project is aggregate project. In that - -- case we can have multiple source files with same base name but different - -- full names. Even sources with same full name can belong to different - -- aggregated projects, so there are different Source_File_Data instances - -- for such each such project; + -- Next is only relevant when there may be more than one source with same + -- base name. This can happen when root project is aggregate project, + -- languages other than Ada are involved (i.e. C), or when list of + -- languages is changed on the fly and same sources can be treated as those + -- of different languages. In that case we can have multiple source files + -- with same base name but different full names. Even sources with same + -- full name can belong to different aggregated projects, so there are + -- different Source_File_Data instances for such each such project; function Hash (File : GNATCOLL.VFS.Filesystem_String) return Ada.Containers.Hash_Type; @@ -149,6 +156,10 @@ -- If there is no file with same base name in map, adds the file as the -- first element in corresponding list. Otherwise adds it to the list. + procedure Clean_Up (Map : in out Names_Files.Map); + -- Clean up possibly existing lists of files with similar base names, + -- then Clear the map itself. + function Hash (Node : Project_Node_Id) return Ada.Containers.Hash_Type; pragma Inline (Hash); @@ -224,14 +235,13 @@ Path : Path_Name_Type) return GPR.Project_Id; -- Return the project view for the project Name - type External_Variable_Callback is access function + type External_Variable_Callback is access procedure (Variable : Project_Node_Id; Prj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean; + Project : Project_Type); -- Called for a typed variable declaration that references an external -- variable in GPR. - -- Stops iterating if this subprogram returns False. type Get_Directory_Path_Callback is access function (Project : GPR.Project_Id) return Path_Information; @@ -357,7 +367,10 @@ procedure Reset_View (Self : in out Project_Data'Class); -- Reset and free the internal data of the project view - procedure Compute_Scenario_Variables (Tree : Project_Tree_Data_Access); + procedure Compute_Scenario_Variables + (Tree : Project_Tree_Data_Access; + Recursive : Boolean := True; + Errors : Error_Report := null); -- Compute (and cache) the whole list of scenario variables for the -- project tree. -- This also ensures that each external reference actually exists @@ -389,7 +402,8 @@ Packages_To_Check : GNAT.Strings.String_List_Access := All_Packs; Recompute_View : Boolean := True; Test_With_Missing_With : Boolean := True; - Report_Missing_Dirs : Boolean := True); + Report_Missing_Dirs : Boolean := True; + Implicit_Project : Boolean); -- Internal implementation of load. This doesn't reset the tree at all, -- but will properly setup the GNAT project manager so that error messages -- are redirected and fatal errors do not kill GPS. @@ -452,6 +466,13 @@ -- program run. Second attempt at registering the attribute leads to an -- error in libgpr. + Host_Targets_List : GPR.Knowledge.String_Lists.List := + GPR.Knowledge.String_Lists.Empty_List; + Host_Targets_List_Set : Boolean := False; + procedure Set_Host_Targets_List; + -- Populate the list of host targets that include the host target itself + -- and may as well have corresponding fallback targets. + ----------- -- Lists -- ----------- @@ -674,8 +695,10 @@ ----------------- function Source_Dirs - (Project : Project_Type; - Recursive : Boolean := False) return GNATCOLL.VFS.File_Array + (Project : Project_Type; + Recursive : Boolean := False; + Include_Externally_Built : Boolean := True) + return GNATCOLL.VFS.File_Array is Current_Dir : constant Filesystem_String := Get_Current_Dir; Iter : Inner_Project_Iterator; @@ -686,6 +709,7 @@ Aggregated : Aggregated_Project_List; Aggregated_Dirs : File_Array_Access := null; + begin if Is_Aggregate_Project (Project) and then Recursive then Aggregated := Project.Data.View.Aggregated_Projects; @@ -695,7 +719,8 @@ Source_Dirs (Project_From_Path (Project.Data.Tree, Aggregated.Path), - Recursive => True)); + Recursive => True, + Include_Externally_Built => Include_Externally_Built)); Aggregated := Aggregated.Next; end loop; return Aggregated_Dirs.all; @@ -709,7 +734,10 @@ View := Get_View (P); exit when View = GPR.No_Project; - Count := Count + Length (Project.Tree_View, View.Source_Dirs); + if Include_Externally_Built or else not Externally_Built (P) then + Count := Count + Length (Project.Tree_View, View.Source_Dirs); + end if; + Next (Iter); end loop; @@ -726,19 +754,21 @@ View := Get_View (P); exit when View = GPR.No_Project; - Src := View.Source_Dirs; + if Include_Externally_Built or else not Externally_Built (P) then + Src := View.Source_Dirs; - while Src /= Nil_String loop - Sources (Index) := Create - (Normalize_Pathname - (+Get_String - (String_Elements (P.Data.Tree) (Src).Display_Value), - Current_Dir, - Resolve_Links => False)); - Ensure_Directory (Sources (Index)); - Index := Index + 1; - Src := String_Elements (P.Data.Tree) (Src).Next; - end loop; + while Src /= Nil_String loop + Sources (Index) := Create + (Normalize_Pathname + (+Get_String + (String_Elements (P.Data.Tree) (Src).Display_Value), + Current_Dir, + Resolve_Links => False)); + Ensure_Directory (Sources (Index)); + Index := Index + 1; + Src := String_Elements (P.Data.Tree) (Src).Next; + end loop; + end if; Next (Iter); end loop; @@ -1526,6 +1556,29 @@ Unchecked_Free (Self.Non_Aggregate_Root_Project); end Free; + -------------- + -- Clean_Up -- + -------------- + + procedure Clean_Up (Map : in out Names_Files.Map) is + El : Source_File_Data; + Tmp_El : Source_File_Data_Access; + + procedure Unchecked_Free is new Ada.Unchecked_Deallocation + (Source_File_Data, Source_File_Data_Access); + + begin + for C in Map.Iterate loop + El := Names_Files.Element (C); + while El.Next /= null loop + Tmp_El := El.Next; + El.Next := El.Next.Next; + Unchecked_Free (Tmp_El); + end loop; + end loop; + Map.Clear; + end Clean_Up; + ----------- -- Clear -- ----------- @@ -2056,8 +2109,10 @@ ------------------ function Source_Files - (Project : Project_Type; - Recursive : Boolean := False) return GNATCOLL.VFS.File_Array_Access + (Project : Project_Type; + Recursive : Boolean := False; + Include_Externally_Built : Boolean := True) + return GNATCOLL.VFS.File_Array_Access is Count : Natural := 0; Index : Natural := 1; @@ -2066,7 +2121,11 @@ begin if not Recursive then - if Project.Data = null or else Project.Data.Files = null then + if Project.Data = null + or else Project.Data.Files = null + or else (not Include_Externally_Built + and then Externally_Built (Project)) + then return new File_Array (1 .. 0); else return new File_Array'(Project.Data.Files.all); @@ -2084,7 +2143,10 @@ -- Files may be null in case of a parse error - if P.Data.Files /= null then + if P.Data.Files /= null + and then (Include_Externally_Built + or else not Externally_Built (P)) + then Count := Count + P.Data.Files'Length; end if; @@ -2100,7 +2162,10 @@ P := Current (Iter); exit when P = No_Project; - if P.Data.Files /= null then + if P.Data.Files /= null + and then (Include_Externally_Built + or else not Externally_Built (P)) + then for S in P.Data.Files'Range loop Sources (Index) := P.Data.Files (S); Index := Index + 1; @@ -2110,6 +2175,8 @@ Next (Iter); end loop; + Sort (Sources.all); + return Sources; end; end Source_Files; @@ -2610,8 +2677,11 @@ & Get_Name_String (Name_Id (Lang.Config.Naming_Data.Spec_Suffix))); - when others => - return ""; + when Unit_Separate => + return +(Uname + & Get_Name_String + (Name_Id + (Lang.Config.Naming_Data.Separate_Suffix))); end case; end; end if; @@ -3305,15 +3375,21 @@ ------------------ procedure Add_Language - (Lang : in out String_List; Index : in out Natural; Str : String) is + (Lang : in out String_List; Index : in out Natural; Str : String) + is + Normalized : String := Str; + Idx : constant Integer := Normalized'First; begin + To_Lower (Normalized); + Normalized (Idx) := GNAT.Case_Util.To_Upper (Normalized (Idx)); + for L in Lang'First .. Index - 1 loop - if Lang (L).all = Str then + if Lang (L).all = Normalized then return; end if; end loop; - Lang (Index) := new String'(Str); + Lang (Index) := new String'(Normalized); Index := Index + 1; end Add_Language; @@ -3654,12 +3730,35 @@ File : GNATCOLL.VFS.Filesystem_String; Case_Sensitive : Boolean := True) return Boolean is - Value : String_List_Access := + Value : String_List_Access := Project.Attribute_Value (Attribute => Main_Attribute, Use_Extended => True); - begin + B_File : constant GNATCOLL.VFS.Filesystem_String := Base_Name (File); + Files : VFS.File_Array_Access; + Source : Boolean := False; + begin + Trace (Me, (+File) & " vs " & (+B_File)); + + if GNATCOLL.VFS_Utils.Is_Absolute_Path (File) then + -- Check that given file is a source of Project first. + Files := Project.Source_Files (Recursive => False); + for F of Files.all loop + if F.Full_Name = File then + Source := True; + exit; + end if; + end loop; + Unchecked_Free (Files); + if not Source then + Free (Value); + return False; + end if; + end if; + for V in Value'Range loop - if Equal (Value (V).all, +File, Case_Sensitive => Case_Sensitive) then + if Equal + (Value (V).all, +B_File, Case_Sensitive => Case_Sensitive) + then Free (Value); return True; end if; @@ -4773,51 +4872,71 @@ -- Compute_Scenario_Variables -- -------------------------------- - procedure Compute_Scenario_Variables (Tree : Project_Tree_Data_Access) is + procedure Compute_Scenario_Variables + (Tree : Project_Tree_Data_Access; + Recursive : Boolean := True; + Errors : Error_Report := null) + is Typed_List : Scenario_Variable_Array_Access; Untyped_List : Untyped_Variable_Array_Access; T_Curr : Positive; U_Curr : Positive; + T_Curr2 : Natural; + Var_Quantity : Natural; + package Name_Id_Sets is new Ada.Containers.Ordered_Sets (GPR.Name_Id); + Inconsistent_SC_Externals : Name_Id_Sets.Set := Name_Id_Sets.Empty_Set; + function Count_Vars return Natural; -- Return the number of scenario variables in tree - function Register_Var + function Not_Already + (UVs : Untyped_Variable_Array_Access; + Last : Positive; + Ext_Name : GPR.Name_Id) return Boolean; + -- Checks that an untyped variable with same name + -- has not been registered yet. + + procedure Register_Var (Variable : Project_Node_Id; Proj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean; + Project : Project_Type); -- Wrapper that calls either Register_Scenario_Var or -- Register_Untyped_Var depending on the kind of the variable. - function Register_Scenario_Var + procedure Register_Scenario_Var (Variable : Project_Node_Id; Proj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean; + Project : Project_Type; + Errors : Error_Report := null); -- Add the variable to the list of scenario variables, if not there yet -- (see the documentation for Scenario_Variables for the exact rules -- used to detect aliases). - function Register_Untyped_Var + procedure Register_Untyped_Var (Variable : Project_Node_Id; Proj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean; + Project : Project_Type); -- Likewise, add the variable to the list of untyped variables. function External_Default - (Project : Project_Type; - Var : Project_Node_Id; - Pkg : Project_Node_Id; - T : GPR.Project_Node_Tree_Ref) + (Project : Project_Type; + Var : Project_Node_Id; + Pkg : Project_Node_Id; + T : GPR.Project_Node_Tree_Ref; + Nested_Expr : Project_Node_Id := Empty_Project_Node) return Name_Id; -- Return the default value for the variable. Var must be a variable -- declaration or a variable reference. This routine supports only -- all kinds of expressions, but for composite values it will set on -- the Uses_Variables flag for the root project. + -- Expr is only used for nested external references in the variable + -- declaration to evaluate the proper expression. ---------------- -- Count_Vars -- @@ -4826,32 +4945,53 @@ function Count_Vars return Natural is Count : Natural := 0; - function Cb + procedure Cb (Variable : Project_Node_Id; Prj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean; + Project : Project_Type); -- Increment the total number of variables -------- -- Cb -- -------- - function Cb + procedure Cb (Variable : Project_Node_Id; Prj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean + Project : Project_Type) is - pragma Unreferenced (Variable, Prj, Pkg, Project); + pragma Unreferenced (Prj, Pkg); + Node_Tree : constant GPR.Project_Node_Tree_Ref := + Project.Data.Tree.Tree; + Expr : Project_Node_Id := Expression_Of (Variable, Node_Tree); begin - Count := Count + 1; - return True; + while Expr /= Empty_Project_Node loop + + Expr := First_Term (Expr, Node_Tree); + if Next_Term (Expr, Node_Tree) /= Empty_Project_Node then + -- Non-canonical nesting, we do not care. + return; + end if; + + Expr := Current_Term (Expr, Node_Tree); + + if Kind_Of (Expr, Node_Tree) = N_External_Value then + Count := Count + 1; + -- That is nesting, we need to iterate deeper. + Expr := External_Default_Of (Expr, Node_Tree); + else + -- End of nesting. + return; + end if; + end loop; end Cb; begin For_Each_External_Variable_Declaration - (Tree.Root, Recursive => True, Callback => Cb'Unrestricted_Access); + (Tree.Root, Recursive => Recursive, + Callback => Cb'Unrestricted_Access); return Count; end Count_Vars; @@ -4860,16 +5000,25 @@ ---------------------- function External_Default - (Project : Project_Type; - Var : Project_Node_Id; - Pkg : Project_Node_Id; - T : GPR.Project_Node_Tree_Ref) + (Project : Project_Type; + Var : Project_Node_Id; + Pkg : Project_Node_Id; + T : GPR.Project_Node_Tree_Ref; + Nested_Expr : Project_Node_Id := Empty_Project_Node) return Name_Id is V : Variable_Value; + Name : constant String := + Get_Name_String (GPR.Tree.Name_Of (Var, T)); + -- For diagnostic purposes. + Proj : Project_Type := Tree.Root; - Expr : Project_Node_Id := Expression_Of (Var, T); + Expr : Project_Node_Id := + (if Nested_Expr = Empty_Project_Node then + Expression_Of (Var, T) + else + Nested_Expr); procedure Check_Complexity (Expression : Project_Node_Id); -- Check wether or not the default value is a simple one, @@ -4907,6 +5056,8 @@ Proj := Project_Type (Project_From_Name (Tree, GPR.Tree.Name_Of (In_Prj, T))); + else + Proj := Project; end if; -- Look for Var declaration into the project @@ -4983,7 +5134,14 @@ end loop; if Active (Me_SV) then - Trace (Me, "We will try to compute default of:"); + if Nested_Expr = Empty_Project_Node then + Trace (Me_SV, "We will try to compute default of:"); + else + Trace + (Me_SV, + "We will try to compute default " + & "of a nested sub-expression from:"); + end if; Pretty_Print (Var, T, Backward_Compatibility => False); end if; @@ -5000,18 +5158,45 @@ (Expr, T), Kind => Expression_Kind_Of (Expr, T)); + Trace (Me_SV, "Value is: " & Get_Name_String (V.Value)); return V.Value; + exception + when Ex : others => + Trace + (Me_SV, "Error when computing default for " + & Name & " from project " & Project.Name & ":"); + Trace + (Me_SV, Exception_Information (Ex)); + return GPR.No_Name; end External_Default; + ----------------- + -- Not_Already -- + ----------------- + + function Not_Already + (UVs : Untyped_Variable_Array_Access; + Last : Positive; + Ext_Name : GPR.Name_Id) return Boolean + is + begin + for I in 1 .. Last - 1 loop + if UVs (I).Name = Ext_Name then + return False; + end if; + end loop; + return True; + end Not_Already; + ------------------ -- Register_Var -- ------------------ - function Register_Var + procedure Register_Var (Variable : Project_Node_Id; Proj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean + Project : Project_Type) is T : constant GPR.Project_Node_Tree_Ref := Project.Data.Tree.Tree; @@ -5039,6 +5224,7 @@ Expr := First_Term (Expr, T); Expr := Current_Term (Expr, T); Expr := External_Default_Of (Expr, T); + if Expr /= Empty_Project_Node and then Kind_Of (Expr, T) /= N_Literal_String then @@ -5057,17 +5243,19 @@ Trace (Me_SV, "Project: " & Project.Project_Path.Display_Full_Name); case Kind_Of (Variable, T) is + when N_Variable_Declaration => - return Register_Untyped_Var (Variable, Proj, Pkg, Project); + Register_Untyped_Var (Variable, Proj, Pkg, Project); + when N_Typed_Variable_Declaration => if Is_Simple_Scenario_Variable then - return Register_Scenario_Var (Variable, Proj, Pkg, Project); + Register_Scenario_Var + (Variable, Proj, Pkg, Project, Errors); else - return Register_Untyped_Var (Variable, Proj, Pkg, Project); + Register_Untyped_Var (Variable, Proj, Pkg, Project); end if; when others => Trace (Me, "Unexpected kind of variable"); - return True; end case; end Register_Var; @@ -5075,41 +5263,148 @@ -- Register_Scenario_Var -- --------------------------- - function Register_Scenario_Var + procedure Register_Scenario_Var (Variable : Project_Node_Id; Proj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean + Project : Project_Type; + Errors : Error_Report := null) is - pragma Unreferenced (Proj); + pragma Unreferenced (Proj, Errors); T : constant GPR.Project_Node_Tree_Ref := Project.Data.Tree.Tree; - V : constant Name_Id := External_Reference_Of (Variable, T); + V : constant Name_Id := + External_Reference_Of (Variable, T); N : constant String := Get_String (V); Var : Scenario_Variable; - Is_Valid : Boolean; + + Is_Valid, Duplicate_Found : Boolean; + + function "<" (L, R : String_Access) return Boolean is (L.all < R.all); + procedure Sort_Values is new + Ada.Containers.Generic_Array_Sort + (Positive, String_Access, String_List); + + procedure Look_For_Duplicate_SVs + (Ext_Ref_Name : String; + Found : out Boolean); + -- Compare current Var with all already stored Scenario Variables + -- and if found check that they have same set of possible values. + + procedure Look_For_Duplicate_SVs + (Ext_Ref_Name : String; + Found : out Boolean) + is + Old_Var : Scenario_Variable := No_Variable; + + Dummy : Project_Tree; + -- Possible_Values_Of doesn't reference the Tree parameter + -- that has been left only for compatibility. + begin + for Index in 1 .. T_Curr - 1 loop + if External_Name (Typed_List (Index)) = Ext_Ref_Name then + Trace (Me_SV, "Same external already registered," + & " comparing set of possible values"); + Old_Var := Typed_List (Index); + + declare + Old_Values : String_List_Access := + new String_List'(Possible_Values_Of (Dummy, Old_Var)); + New_Values : String_List_Access := + new String_List'(Possible_Values_Of (Dummy, Var)); + + Values_Identical : Boolean := True; + begin + if Old_Values.all'Length /= New_Values.all'Length then + Trace (Me_SV, "different ammount of values"); + Values_Identical := False; + else + Sort_Values (Old_Values.all); + Sort_Values (New_Values.all); + for I in Old_Values'Range loop + if Old_Values (I).all /= New_Values (I).all then + Trace + (Me_SV, + "Unmatching values: " & Old_Values (I).all + & " and " & New_Values (I).all); + Values_Identical := False; + exit; + end if; + end loop; + end if; + + Free (Old_Values); + Free (New_Values); + + if not Values_Identical then + if + Old_Var.First_Project_Path = Var.First_Project_Path + then + -- Same project + Trace (Me_SV, + Project.Project_Path.Display_Full_Name + & ": Scenario variables " + & Get_Name_String (Old_Var.Var_Name) + & " and " + & Get_Name_String (Var.Var_Name) + & " controlled by same external " + & Ext_Ref_Name + & " have different sets of possible values" + & ASCII.LF); + else + -- Aggregated projects with same name + Trace + (Me_SV, + "Scenario variables " + & Get_Name_String (Old_Var.First_Project_Path) + & ": " + & Get_Name_String (Old_Var.Var_Name) + & " and " + & Project.Project_Path.Display_Full_Name + & ": " + & Get_Name_String (Var.Var_Name) + & " controlled by same external " + & Ext_Ref_Name + & " have different sets of possible values" + & ASCII.LF); + end if; + + Inconsistent_SC_Externals.Include (Old_Var.Ext_Name); + end if; + end; + + Found := True; + return; + end if; + end loop; + + Found := False; + end Look_For_Duplicate_SVs; + begin Trace (Me_SV, "Register_Scenario_Var " & Get_Name_String (GPR.Tree.Name_Of (Variable, T))); - for Index in 1 .. T_Curr - 1 loop - if External_Name (Typed_List (Index)) = N then - -- Nothing to do - return True; - end if; - end loop; - Var := Scenario_Variable' - (Name => V, + (Ext_Name => V, + Var_Name => GPR.Tree.Name_Of (Variable, T), Default => External_Default (Project, Variable, Pkg, T), String_Type => String_Type_Of (Variable, T), Tree_Ref => T, Value => GPR.Ext.Value_Of (Tree.Env.Env.External, V, With_Default => - External_Default (Project, Variable, Pkg, T))); + External_Default (Project, Variable, Pkg, T)), + First_Project_Path => Project.Data.View.Path.Display_Name); + + Look_For_Duplicate_SVs (N, Duplicate_Found); + if Duplicate_Found then + -- Nothing to add for the root one, however there may be some new + -- nested ones. + goto Unwind; + end if; Typed_List (T_Curr) := Var; @@ -5117,12 +5412,12 @@ -- value. Is_Valid := GPR.Ext.Value_Of - (Tree.Env.Env.External, Var.Name) /= No_Name; + (Tree.Env.Env.External, Var.Ext_Name) /= No_Name; if Is_Valid then declare Current : constant Name_Id := - GPR.Ext.Value_Of (Tree.Env.Env.External, Var.Name); + GPR.Ext.Value_Of (Tree.Env.Env.External, Var.Ext_Name); Iter : String_List_Iterator := Value_Of (T, Var); begin Is_Valid := False; @@ -5153,18 +5448,72 @@ end if; T_Curr := T_Curr + 1; - return True; + + <> + -- Unwinding nested external references if any. + Increase_Indent (Me_SV, "Unwind nested external references"); + declare + Expression : Project_Node_Id; + + Expr : Project_Node_Id := + Expression_Of (Variable, T); + Ref : Name_Id; + begin + Expr := + External_Default_Of + (Current_Term + (First_Term + (Expr, T), + T), + T); + Expression := Expr; + while Expr /= Empty_Project_Node loop + Expr := First_Term (Expr, T); + if Next_Term (Expr, T) /= Empty_Project_Node then + Decrease_Indent (Me_SV, + "Unwind terminated: Not canonical nesting"); + return; + end if; + + Expr := Current_Term (Expr, T); + if Kind_Of (Expr, T) = N_External_Value then + Ref := String_Value_Of (External_Reference_Of (Expr, T), T); + Trace (Me_SV, + "Nested external reference: " + & Get_Name_String (Ref)); + + Look_For_Duplicate_SVs + (Get_Name_String (Ref), Duplicate_Found); + if not Duplicate_Found then + + Var.Ext_Name := Ref; + Var.Default := + External_Default + (Project, Variable, Pkg, T, Expression); + + Typed_List (T_Curr) := Var; + T_Curr := T_Curr + 1; + end if; + + Expr := External_Default_Of (Expr, T); + Expression := Expr; + else + Decrease_Indent (Me_SV, "Unwind finished"); + return; + end if; + end loop; + end; end Register_Scenario_Var; -------------------------- -- Register_Untyped_Var -- -------------------------- - function Register_Untyped_Var + procedure Register_Untyped_Var (Variable : Project_Node_Id; Proj : Project_Node_Id; Pkg : Project_Node_Id; - Project : Project_Type) return Boolean + Project : Project_Type) is pragma Unreferenced (Proj); T : constant GPR.Project_Node_Tree_Ref := @@ -5181,7 +5530,7 @@ for Index in 1 .. U_Curr - 1 loop if External_Name (Untyped_List (Index)) = N then -- Nothing to do - return True; + return; end if; end loop; @@ -5196,9 +5545,10 @@ Untyped_List (U_Curr) := Var; U_Curr := U_Curr + 1; - return True; end Register_Untyped_Var; + use Name_Id_Sets; + use Ada.Containers; begin Trace (Me, "Compute the list of scenario variables"); Unchecked_Free (Tree.Env.Scenario_Variables); @@ -5211,15 +5561,44 @@ U_Curr := Untyped_List'First; For_Each_External_Variable_Declaration - (Tree.Root, Recursive => True, + (Tree.Root, Recursive => Recursive, Callback => Register_Var'Unrestricted_Access); - if T_Curr > Typed_List'Last then - Tree.Env.Scenario_Variables := Typed_List; + if Inconsistent_SC_Externals.Length = 0 then + if T_Curr > Typed_List'Last then + Tree.Env.Scenario_Variables := Typed_List; + else + Tree.Env.Scenario_Variables := + new Scenario_Variable_Array'(Typed_List (1 .. T_Curr - 1)); + Unchecked_Free (Typed_List); + end if; else + -- Moving SVs with inconsistent types to UVs + T_Curr2 := T_Curr - 1 - Integer (Inconsistent_SC_Externals.Length); Tree.Env.Scenario_Variables := - new Scenario_Variable_Array'(Typed_List (1 .. T_Curr - 1)); + new Scenario_Variable_Array (1 .. T_Curr2); + T_Curr2 := 1; + for I in 1 .. T_Curr - 1 loop + if + Inconsistent_SC_Externals.Contains (Typed_List (I).Ext_Name) + then + if + Not_Already + (Untyped_List, U_Curr, Typed_List (I).Ext_Name) + then + Untyped_List (U_Curr) := + (Name => Typed_List (I).Ext_Name, + Default => Typed_List (I).Default, + Value => Typed_List (I).Value); + U_Curr := U_Curr + 1; + end if; + else + Tree.Env.Scenario_Variables (T_Curr2) := Typed_List (I); + T_Curr2 := T_Curr2 + 1; + end if; + end loop; Unchecked_Free (Typed_List); + Inconsistent_SC_Externals.Clear; end if; if U_Curr > Untyped_List'Last then @@ -5229,6 +5608,7 @@ new Untyped_Variable_Array'(Untyped_List (1 .. U_Curr - 1)); Unchecked_Free (Untyped_List); end if; + end Compute_Scenario_Variables; ------------------------ @@ -5236,9 +5616,12 @@ ------------------------ function Scenario_Variables - (Self : Project_Tree) return Scenario_Variable_Array is + (Self : Project_Tree; + Root_Only : Boolean := False) + return Scenario_Variable_Array + is begin - return Scenario_Variables (Self.Data); + return Scenario_Variables (Self.Data, Root_Only); end Scenario_Variables; ----------------------- @@ -5246,9 +5629,10 @@ ----------------------- function Untyped_Variables - (Self : Project_Tree) return Untyped_Variable_Array is + (Self : Project_Tree; + Root_Only : Boolean := False) return Untyped_Variable_Array is begin - return Untyped_Variables (Self.Data); + return Untyped_Variables (Self.Data, Root_Only); end Untyped_Variables; ------------------------ @@ -5256,13 +5640,39 @@ ------------------------ function Scenario_Variables - (Tree : Project_Tree_Data_Access) return Scenario_Variable_Array + (Tree : Project_Tree_Data_Access; + Root_Only : Boolean := False) return Scenario_Variable_Array is + SVs : Scenario_Variable_Array_Access; + UVs : Untyped_Variable_Array_Access; begin if Tree = null or else Tree.Is_Aggregated then return (1 .. 0 => <>); end if; + if Root_Only then + -- We need to save the actual values because otherwise + -- Compute_Scenario_Variables will overwrite them. + + SVs := Tree.Env.Scenario_Variables; + UVs := Tree.Env.Untyped_Variables; + Tree.Env.Scenario_Variables := null; + Tree.Env.Untyped_Variables := null; + + Compute_Scenario_Variables (Tree, Recursive => False); + + declare + Result : constant Scenario_Variable_Array := + Tree.Env.Scenario_Variables.all; + begin + Unchecked_Free (Tree.Env.Scenario_Variables); + Unchecked_Free (Tree.Env.Untyped_Variables); + Tree.Env.Scenario_Variables := SVs; + Tree.Env.Untyped_Variables := UVs; + return Result; + end; + end if; + if Tree.Env.Scenario_Variables = null then Compute_Scenario_Variables (Tree); end if; @@ -5270,7 +5680,7 @@ for V of Tree.Env.Scenario_Variables.all loop V.Value := GPR.Ext.Value_Of - (Tree.Env.Env.External, V.Name, With_Default => V.Default); + (Tree.Env.Env.External, V.Ext_Name, With_Default => V.Default); end loop; return Tree.Env.Scenario_Variables.all; @@ -5281,13 +5691,39 @@ ----------------------- function Untyped_Variables - (Tree : Project_Tree_Data_Access) return Untyped_Variable_Array + (Tree : Project_Tree_Data_Access; + Root_Only : Boolean := False) return Untyped_Variable_Array is + SVs : Scenario_Variable_Array_Access; + UVs : Untyped_Variable_Array_Access; begin if Tree = null or else Tree.Is_Aggregated then return (1 .. 0 => <>); end if; + if Root_Only then + -- We need to save the actual values because otherwise + -- Compute_Scenario_Variables will overwrite them. + + SVs := Tree.Env.Scenario_Variables; + UVs := Tree.Env.Untyped_Variables; + Tree.Env.Scenario_Variables := null; + Tree.Env.Untyped_Variables := null; + + Compute_Scenario_Variables (Tree, Recursive => False); + + declare + Result : constant Untyped_Variable_Array := + Tree.Env.Untyped_Variables.all; + begin + Unchecked_Free (Tree.Env.Scenario_Variables); + Unchecked_Free (Tree.Env.Untyped_Variables); + Tree.Env.Scenario_Variables := SVs; + Tree.Env.Untyped_Variables := UVs; + return Result; + end; + end if; + if Tree.Env.Untyped_Variables = null then Compute_Scenario_Variables (Tree); end if; @@ -5306,32 +5742,69 @@ ------------------------ function Scenario_Variables - (Self : Project_Tree; External_Name : String) - return Scenario_Variable + (Self : Project_Tree; + External_Name : String; + Root_Only : Boolean := False) return Scenario_Variable is E : constant String := External_Name; Ext : Name_Id; List : Scenario_Variable_Array_Access; Var : Scenario_Variable; + + SVs : Scenario_Variable_Array_Access; + UVs : Untyped_Variable_Array_Access; + + SV : Scenario_Variable; begin Ext := Get_String (E); + if Root_Only then + -- We need to save the actual values because otherwise + -- Compute_Scenario_Variables will overwrite them. + + SVs := Self.Data.Env.Scenario_Variables; + UVs := Self.Data.Env.Untyped_Variables; + Self.Data.Env.Scenario_Variables := null; + Self.Data.Env.Untyped_Variables := null; + + Compute_Scenario_Variables (Self.Data, Recursive => False); + + for V of Self.Data.Env.Scenario_Variables.all loop + if V.Ext_Name = Ext then + SV := V; + Unchecked_Free (Self.Data.Env.Scenario_Variables); + Unchecked_Free (Self.Data.Env.Untyped_Variables); + Self.Data.Env.Scenario_Variables := SVs; + Self.Data.Env.Untyped_Variables := UVs; + return SV; + end if; + end loop; + + Unchecked_Free (Self.Data.Env.Scenario_Variables); + Unchecked_Free (Self.Data.Env.Untyped_Variables); + Self.Data.Env.Scenario_Variables := SVs; + Self.Data.Env.Untyped_Variables := UVs; + return No_Variable; + end if; + if Self.Data.Env.Scenario_Variables = null then Compute_Scenario_Variables (Self.Data); end if; for V of Self.Data.Env.Scenario_Variables.all loop - if V.Name = Ext then + if V.Ext_Name = Ext then return V; end if; end loop; Var := Scenario_Variable' - (Name => Ext, + (Ext_Name => Ext, + Var_Name => No_Name, Default => No_Name, - String_Type => Empty_Project_Node, -- ??? Won't be able to edit it + String_Type => Empty_Project_Node, -- ??? Won't be able to edit it Tree_Ref => null, - Value => No_Name); + Value => No_Name, + First_Project_Path => GPR.No_Path); List := Self.Data.Env.Scenario_Variables; Self.Data.Env.Scenario_Variables := @@ -5347,14 +5820,50 @@ -------------------------- function Get_Untyped_Variable - (Self : Project_Tree; External_Name : String) return Untyped_Variable + (Self : Project_Tree; + External_Name : String; + Root_Only : Boolean := False) return Untyped_Variable is Ext : Name_Id; List : Untyped_Variable_Array_Access; Var : Untyped_Variable; + + SVs : Scenario_Variable_Array_Access; + UVs : Untyped_Variable_Array_Access; + + UV : Untyped_Variable; begin Ext := Get_String (External_Name); + if Root_Only then + -- We need to save the actual values because otherwise + -- Compute_Scenario_Variables will overwrite them. + + SVs := Self.Data.Env.Scenario_Variables; + UVs := Self.Data.Env.Untyped_Variables; + Self.Data.Env.Scenario_Variables := null; + Self.Data.Env.Untyped_Variables := null; + + Compute_Scenario_Variables (Self.Data, Recursive => False); + + for V of Self.Data.Env.Untyped_Variables.all loop + if V.Name = Ext then + UV := V; + Unchecked_Free (Self.Data.Env.Scenario_Variables); + Unchecked_Free (Self.Data.Env.Untyped_Variables); + Self.Data.Env.Scenario_Variables := SVs; + Self.Data.Env.Untyped_Variables := UVs; + return UV; + end if; + end loop; + + Unchecked_Free (Self.Data.Env.Scenario_Variables); + Unchecked_Free (Self.Data.Env.Untyped_Variables); + Self.Data.Env.Scenario_Variables := SVs; + Self.Data.Env.Untyped_Variables := UVs; + return No_Untyped_Variable; + end if; + if Self.Data.Env.Scenario_Variables = null then Compute_Scenario_Variables (Self.Data); end if; @@ -5385,7 +5894,7 @@ function External_Name (Var : Scenario_Variable) return String is begin - return Get_String (Var.Name); + return Get_String (Var.Ext_Name); end External_Name; ------------------- @@ -5451,7 +5960,7 @@ for V in Vars'Range loop GPR.Ext.Add (Self.Data.Env.Env.External, - Get_String (Vars (V).Name), + Get_String (Vars (V).Ext_Name), Get_String (Vars (V).Value), GPR.Ext.From_Command_Line); end loop; @@ -5593,11 +6102,11 @@ if Kind_Of (Var, Tree) in N_Typed_Variable_Declaration | N_Variable_Declaration and then Is_External_Variable (Var, Tree) - and then not Callback (Var, Prj, Pkg, Current_Project) then - exit; + Callback (Var, Prj, Pkg, Current_Project); + end if; - elsif Kind_Of (Var, Tree) = N_Variable_Declaration + if Kind_Of (Var, Tree) = N_Variable_Declaration or else (Kind_Of (Var, Tree) = N_Typed_Variable_Declaration and then not Is_External_Variable (Var, Tree)) @@ -6791,6 +7300,8 @@ GPR.Current_Verbosity := GPR.High; end if; + Set_Host_Targets_List; + if Self.Data /= null and then Self.Data.Root /= No_Project then Previous_Project := Self.Root_Project.Project_Path; Previous_Status := Self.Data.Status; @@ -6861,7 +7372,8 @@ Project => Project, Packages_To_Check => Packages_To_Check, Recompute_View => False, - Report_Missing_Dirs => Report_Missing_Dirs); + Report_Missing_Dirs => Report_Missing_Dirs, + Implicit_Project => False); GPR.Err.Initialize; -- Clear errors @@ -6902,7 +7414,8 @@ Project => Project, Packages_To_Check => Packages_To_Check, Recompute_View => Recompute_View, - Report_Missing_Dirs => Report_Missing_Dirs); + Report_Missing_Dirs => Report_Missing_Dirs, + Implicit_Project => False); if Previous_Status = Default then Trace (Me, "Remove previous default project on disk, no longer used"); @@ -7116,11 +7629,22 @@ -- Compute the default 'gnatls' command to spawn function Default_Gnatls return String is + No_Prefix : Boolean := False; begin + + for Tgt of Host_Targets_List loop + if Target = Tgt then + No_Prefix := True; + exit; + end if; + end loop; + if Runtime /= Unset or else Target /= Unset then - return (if Target /= Unset then Target & '-' else "") + return + (if Target /= Unset + and then not No_Prefix then Target & '-' else "") & "gnatls" & (if Runtime /= Unset then " --RTS=" & Runtime else ""); else @@ -7455,7 +7979,8 @@ Packages_To_Check : GNAT.Strings.String_List_Access := All_Packs; Recompute_View : Boolean := True; Test_With_Missing_With : Boolean := True; - Report_Missing_Dirs : Boolean := True) + Report_Missing_Dirs : Boolean := True; + Implicit_Project : Boolean) is Block_Me : constant Block_Trace_Handle := Create (Me); @@ -7559,7 +8084,8 @@ Store_Comments => True, Is_Config_File => False, Env => Tree.Data.Env.Env, - Current_Directory => Get_Current_Dir); + Current_Directory => Get_Current_Dir, + Implicit_Project => Implicit_Project); if not Active (Me_Aggregate_Support) and then Project /= Empty_Project_Node @@ -7630,7 +8156,8 @@ Recompute_View => Recompute_View, Packages_To_Check => Packages_To_Check, Test_With_Missing_With => False, - Report_Missing_Dirs => Report_Missing_Dirs); + Report_Missing_Dirs => Report_Missing_Dirs, + Implicit_Project => Implicit_Project); GPR.Com.Fail := null; GPR.Output.Cancel_Special_Output; @@ -7661,7 +8188,8 @@ Recompute_View => Recompute_View, Packages_To_Check => Packages_To_Check, Test_With_Missing_With => False, - Report_Missing_Dirs => Report_Missing_Dirs); + Report_Missing_Dirs => Report_Missing_Dirs, + Implicit_Project => Implicit_Project); GPR.Com.Fail := null; GPR.Output.Cancel_Special_Output; @@ -7730,7 +8258,8 @@ Recompute_View => Recompute_View, Packages_To_Check => Packages_To_Check, Test_With_Missing_With => False, - Report_Missing_Dirs => Report_Missing_Dirs); + Report_Missing_Dirs => Report_Missing_Dirs, + Implicit_Project => Implicit_Project); GPR.Com.Fail := null; GPR.Output.Cancel_Special_Output; @@ -7810,8 +8339,8 @@ procedure Reset_View (Tree : Project_Tree'Class) is begin if not Tree.Data.Is_Aggregated then - Tree.Data.Sources.Clear; - Tree.Data.Objects_Basename.Clear; + Clean_Up (Tree.Data.Sources); + Clean_Up (Tree.Data.Objects_Basename); end if; Tree.Data.Directories.Clear; @@ -7994,6 +8523,14 @@ Create_Attribute (Name_Body_Suffix, ".adb", "ada", Pkg => Naming); Create_Attribute + (Name_Spec_Suffix, ".h", "c", Pkg => Naming); + Create_Attribute + (Name_Body_Suffix, ".c", "c", Pkg => Naming); + Create_Attribute + (Name_Spec_Suffix, ".hh", "c++", Pkg => Naming); + Create_Attribute + (Name_Body_Suffix, ".cpp", "c++", Pkg => Naming); + Create_Attribute (Name_Dot_Replacement, "-", Pkg => Naming); Create_Attribute (Name_Casing, "lowercase", Pkg => Naming); @@ -8428,7 +8965,7 @@ -- all to fully parse all project trees and create instances of all -- projects. - Compute_Scenario_Variables (Self.Data); + Compute_Scenario_Variables (Self.Data, Errors => Errors); Parse_Source_Files (Self); Initialize_Source_Records; @@ -8707,6 +9244,63 @@ end if; end Load_Empty_Project; + --------------------------- + -- Load_Implicit_Project -- + --------------------------- + + procedure Load_Implicit_Project + (Self : in out Project_Tree; + Env : Project_Environment_Access := null; + Recompute_View : Boolean := True) + is + Project_File : Virtual_File; + Gprbuild_Path : Filesystem_String_Access; + Project : Project_Node_Id; + + Implicit_Project_File_Path : constant String := + "share" & + Directory_Separator & + "gpr" & + Directory_Separator & + '_' & + Default_Project_File_Name; + begin + Trace (Me, "Loading implicit project "); + + Project_Tree'Class (Self).Unload; + + Reset (Self, Env); + + Gprbuild_Path := Locate_Exec_On_Path ("gprbuild"); + if Gprbuild_Path = null then + Trace (Me, "Gprbuild not found on path"); + return; + end if; + Project_File := Get_Parent (Create (Dir_Name (Gprbuild_Path.all))); + Project_File := Join (Project_File, +Implicit_Project_File_Path); + Free (Gprbuild_Path); + + if not Project_File.Is_Regular_File then + Trace (Me, "_default.gpr not found in expected location"); + return; + end if; + + Trace (Me, "Implicit project found " & Project_File.Display_Full_Name); + + Internal_Load + (Self, Project_File, null, + Report_Syntax_Errors => True, -- _default.gpr is safe + Project => Project, + Packages_To_Check => No_Packs, + Recompute_View => Recompute_View, + Implicit_Project => True); + + if Project = Empty_Project_Node then + Trace (Me, "Cannot load implicit project"); + return; + end if; + end Load_Implicit_Project; + ------------------------ -- Parse_Source_Files -- ------------------------ @@ -9991,11 +10585,13 @@ -- Clear the cache Unchecked_Free (Project.Data.Tree.Env.Scenario_Variables); - return (Name => Get_String (External_Name), + return (Ext_Name => Get_String (External_Name), + Var_Name => No_Name, Default => No_Name, Value => No_Name, String_Type => Typ, - Tree_Ref => Tree_Node); + Tree_Ref => Tree_Node, + First_Project_Path => GPR.No_Path); end Create_Scenario_Variable; -------------------------- @@ -10043,7 +10639,7 @@ -- Create the new variable, to avoid errors when computing the view of -- the project. - Variable.Name := Get_String (New_Name); + Variable.Ext_Name := Get_String (New_Name); Tree.Change_Environment ((1 => Variable)); end Change_External_Name; @@ -10495,6 +11091,51 @@ Self.TTY_Process_Descriptor_Disabled := Disabled; end Set_Disable_Use_Of_TTY_Process_Descriptor; + --------------------------- + -- Set_Host_Targets_List -- + --------------------------- + + procedure Set_Host_Targets_List is + Gprbuild_Path : Filesystem_String_Access; + KB_Dir : GNATCOLL.VFS.Virtual_File; + + KB : GPR.Knowledge.Knowledge_Base; + + use GPR.Knowledge; + use GPR.Knowledge.String_Lists; + + TS_Id : GPR.Knowledge.Targets_Set_Id; + + begin + Trace (Me, "Set_Host_Targets_List"); + if Host_Targets_List_Set then + -- No point reparsing KB more than once. + return; + end if; + + Host_Targets_List_Set := True; + + Gprbuild_Path := Locate_Exec_On_Path ("gprbuild"); + if Gprbuild_Path = null then + Trace (Me, "Gprbuild not found on path"); + return; + end if; + + KB_Dir := Get_Parent (Create (Dir_Name (Gprbuild_Path.all))); + KB_Dir := Join (Join (KB_Dir, "share"), "gprconfig"); + Free (Gprbuild_Path); + GPR.Knowledge.Parse_Knowledge_Base + (KB, KB_Dir.Display_Full_Name, Parse_Compiler_Info => False); + GPR.Knowledge.Get_Targets_Set (KB, GPR.Sdefault.Hostname, TS_Id); + + Host_Targets_List := GPR.Knowledge.Get_Fallback_List + (Base => KB, + On_Target => TS_Id); + Host_Targets_List.Append + (GPR.Knowledge.Normalized_Target (KB, TS_Id)); + + end Set_Host_Targets_List; + begin -- GPR.Initialize; -- Csets.Initialize; diff -Nru libgnatcoll-18/src/gnatcoll-projects.ads libgnatcoll-19/src/gnatcoll-projects.ads --- libgnatcoll-18/src/gnatcoll-projects.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-projects.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2002-2018, AdaCore -- +-- Copyright (C) 2002-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -139,9 +139,9 @@ -- Allocate a new environment (if Self is null) and initialize internal -- data. -- IDE_Mode turns on some additional functionality such as extra error - -- message filtering that is only relevant for interactive aplications such - -- as GPS. Most of the tools that do a single pass on the project should - -- not turn on this flag. + -- message filtering that is only relevant for interactive applications + -- such as IDE. Most of the tools that do a single pass on the project + -- should not turn on this flag. procedure Free (Self : in out Project_Environment_Access); procedure Free (Self : in out Project_Tree_Access); @@ -224,7 +224,7 @@ -- -- If Report_Missing_Dirs is true, then a warning will be issued when a -- project file's object directory does not exist yet. Note that this flag - -- will be stored in the project environment and will have an effet on + -- will be stored in the project environment and will have an effect on -- further calls to Recompute_View with the same project environment. procedure Set_Trusted_Mode @@ -257,6 +257,16 @@ -- later replace with an actual project. -- A default version of Env will be created if null is passed. + procedure Load_Implicit_Project + (Self : in out Project_Tree; + Env : Project_Environment_Access := null; + Recompute_View : Boolean := True); + -- Load special project _default.gpr that is used by gprbuild when invoked + -- without -P switch. When implicit project file is used current directory + -- is considered to be a source dir and an object dir. + -- This mode is needed when you want to get easy access to Ada sources + -- located in current dir without creating a temporary project file. + procedure Recompute_View (Self : in out Project_Tree; Errors : Error_Report := null); @@ -302,7 +312,7 @@ -- To make it easier to store instances of Project_Type in a data -- structure, that type is not visibly tagged (you do not have to store an -- access to Project_Type'Class and find out when you can free it). - -- However, it might be convient to associate your own custom data with a + -- However, it might be convenient to associate your own custom data with a -- project (for instance extra caches for attributes that your application -- uses often, or other type of data). -- To do so, you should subclass Project_Data, as well as Project_Tree. For @@ -491,7 +501,9 @@ function Source_Dirs (Project : Project_Type; - Recursive : Boolean := False) return GNATCOLL.VFS.File_Array; + Recursive : Boolean := False; + Include_Externally_Built : Boolean := True) + return GNATCOLL.VFS.File_Array; pragma Precondition (Project /= No_Project); -- Return the list of source directories. -- The directories are returned in the order in which they are defined in @@ -502,6 +514,8 @@ -- will also be returned, but in this case the order of the directories in -- the result is undefined and the result cannot be considered as a search -- path for project sources. + -- If Include_Externally_Built is False then source directories belonging + -- to project marked "Externally_Built" will not be returned. -- Note that duplicate directories might be returned when directories are -- shared by multiple projects in the same tree. @@ -567,7 +581,7 @@ Exclude_Externally : Boolean := False) return GNATCOLL.VFS.File_Array; -- Return the object path for this project. The empty string is returned -- if the project doesn't have any object directory (i.e. the user - -- explicitely set it to the empty string). If Including_Libraries is + -- explicitly set it to the empty string). If Including_Libraries is -- True and Project is a library project, it returns both object and ALI -- paths (in that order) or only ALI path if project doesn't have object -- directory. If Exclude_Externall is True and Project is externally built @@ -599,7 +613,7 @@ --------------- type Unit_Parts is (Unit_Body, Unit_Spec, Unit_Separate); - -- A unit is usally composed of two parts: the spec and the body. + -- A unit is usually composed of two parts: the spec and the body. -- - Unit_Spec represents package/subprogram/generic declarations -- - Unit_Body represents package/subprogram/generic bodies and subunits. -- - Unit_Separate is used for additional implementation code in Ada @@ -674,8 +688,11 @@ function Source_Files (Project : Project_Type; - Recursive : Boolean := False) return GNATCOLL.VFS.File_Array_Access; - -- Return the list of source files belonging to the project. + Recursive : Boolean := False; + Include_Externally_Built : Boolean := True) + return GNATCOLL.VFS.File_Array_Access; + -- Return the list of source files belonging to the project. The list is + -- alphabetically sorted by the full paths of the files. -- If Recursive is False, only the direct sources of the project are -- returned. Otherwise, the sources from imported projects are returned as -- well. @@ -689,6 +706,8 @@ -- returned files may not be unique in case when root project is an -- aggregate project. For languages other than Ada multiple sources with -- same base name can also be returned. + -- If Include_Externally_Built is False then source directories belonging + -- to project marked "Externally_Built" will not be returned. type File_And_Project is record File : GNATCOLL.VFS.Virtual_File; @@ -736,7 +755,7 @@ -- absolute path if it currently is a base name. -- -- If Name is an absolute path, it is returned as is. Otherwise, only the - -- base name is used (ie we remove any directory information from Name). + -- base name is used (i.e. we remove any directory information from Name). -- -- If a source file matches Name and Use_Source_Path is true, it is always -- returned, whether it is part of Project or not. This is the most @@ -818,6 +837,9 @@ File : GNATCOLL.VFS.Filesystem_String; Case_Sensitive : Boolean := True) return Boolean; -- Return True if File is one of the main files of Project. + -- If File is an absolute path, additionally checks if it is a source of + -- Project, otherwise just the base name is used to compare against the + -- list of Main units specified in the project. -- Case_Sensitive indicates whether the build machine is case sensitive. -- In general, this machine is the local machine on which the application -- is running, but sometimes you might actually want to process the project @@ -1107,7 +1129,7 @@ -- It will process Root_Project and all its subprojects, recursively, but -- without processing the same project twice. -- - -- The project nodes are returned sorted topologically (ie first the + -- The project nodes are returned sorted topologically (i.e. first the -- projects that don't depend on anything, then their parents, and so on -- until the root project). Extended projects are always returned before -- their extending project. @@ -1233,9 +1255,12 @@ Empty_Untyped_Variable_Array : aliased constant Untyped_Variable_Array; function Scenario_Variables - (Self : Project_Tree) return Scenario_Variable_Array; + (Self : Project_Tree; + Root_Only : Boolean := False) return Scenario_Variable_Array; -- Return the list of scenario variables used in the whole project - -- tree. The result is cached for efficiency + -- tree, unless Root_Only is set to True. In the latter case only + -- variables declared in the root project are returned. + -- The result of whole tree computation is cached for efficiency. -- Two variables are considered the same if they reference the same -- environment variable. The reason is that they might not have the same -- name internally in imported projects, however, they will always have the @@ -1244,27 +1269,39 @@ -- project was loaded. function Untyped_Variables - (Self : Project_Tree) return Untyped_Variable_Array; - -- Return the list of untyped variables used in the whole project - -- tree. The result is cached for efficiency. + (Self : Project_Tree; + Root_Only : Boolean := False) return Untyped_Variable_Array; + -- Return the list of scenario variables used in the whole project + -- tree, unless Root_Only is set to True. In the latter case only + -- variables declared in the root project are returned. function Scenario_Variables - (Self : Project_Tree; External_Name : String) return Scenario_Variable; + (Self : Project_Tree; + External_Name : String; + Root_Only : Boolean := False) return Scenario_Variable; -- Return the scenario variable associated with External_Name. -- If you call Value on the result, you get the current value it had when -- the project was loaded. -- If the project does not contain such a variable (for instance because -- you call this function before loading the project), a new variable is -- created. + -- If Root_Only is set to True and the root project does not have such + -- a variable (even if it is declared in the project tree in some other + -- project), No_Variable is returned. function Get_Untyped_Variable - (Self : Project_Tree; External_Name : String) return Untyped_Variable; + (Self : Project_Tree; + External_Name : String; + Root_Only : Boolean := False) return Untyped_Variable; -- Return the scenario variable associated with External_Name. -- If you call Value on the result, you get the current value it had when -- the project was loaded. -- If the project does not contain such a variable (for instance because -- you call this function before loading the project), a new variable is -- created. + -- If Root_Only is set to True and the root project does not have such + -- a variable (even if it is declared in the project tree in some other + -- project), No_Untyped_Variable is returned. function External_Name (Var : Scenario_Variable) return String; function External_Name (Var : Untyped_Variable) return String; @@ -1456,7 +1493,7 @@ -- explicitly defined the attribute in his project, use Has_Attribute -- instead. -- - -- It is the responsability of the caller to free the memory. + -- It is the responsibility of the caller to free the memory. -- The corresponding attribute would have been set in the project as: -- for Attribute use ("value1", "value2"); -- or @@ -1765,7 +1802,7 @@ Case_Sensitive_Index : Boolean := False) return String; -- Register a new attribute that will be allowed in projects. -- This prevents error messages when loading the project. - -- Attributes can only be added to packages, not at the toplevel of a + -- Attributes can only be added to packages, not at the top level of a -- project. -- Returns a non-empty string if there is an error creating the attribute @@ -1798,6 +1835,11 @@ -- Editing scenario variables -- -------------------------------- + -- After calling most of the following routines local variables pointing + -- to Scenario Variables become obsolete and need to be reassigned again + -- through a call to Scenario_Variables. Otherwise expected updates, + -- such as lists of possible values, will not be observed. + procedure Delete_Scenario_Variable (Tree : Project_Tree'Class; External_Name : String; @@ -1806,7 +1848,7 @@ -- Remove all scenario variables that reference External_Name. -- All the case constructions where this variable occur are replaced by -- the case item corresponding to Keep_Choice. - -- If Delete_Direct_References is True, then all direct references (ie + -- If Delete_Direct_References is True, then all direct references (i.e. -- external() statements in the project file) to External_Name are also -- removed, in addition to the scenario variables that reference it. -- @@ -1840,7 +1882,7 @@ Old_Value : String; New_Value : String); -- Rename one of the choices in the list of possible values for the - -- scenario variables asociated with External_Name. This also changes + -- scenario variables associated with External_Name. This also changes -- the default value for external references. procedure Remove_Value @@ -2098,11 +2140,17 @@ end record; type Scenario_Variable is record - Name : GPR.Name_Id; + Ext_Name : GPR.Name_Id; + Var_Name : GPR.Name_Id; Default : GPR.Name_Id; String_Type : GPR.Project_Node_Id; Tree_Ref : GPR.Project_Node_Tree_Ref; Value : GPR.Name_Id; + + First_Project_Path : GPR.Path_Name_Type; + -- First project in which corresponding controlling external has been + -- discovered. Used for diagnostic message when types of other Scenario + -- Variables controlled by same external do not match. end record; type Untyped_Variable is record @@ -2112,8 +2160,8 @@ end record; No_Variable : aliased constant Scenario_Variable := - (GPR.No_Name, GPR.No_Name, GPR.Empty_Project_Node, - null, GPR.No_Name); + (GPR.No_Name, GPR.No_Name, GPR.No_Name, GPR.Empty_Project_Node, + null, GPR.No_Name, GPR.No_Path); All_Scenarios : aliased constant Scenario_Variable_Array (1 .. 0) := (others => No_Variable); @@ -2246,7 +2294,7 @@ Stack_Switches_Attribute : constant Attribute_Pkg_List := "stack#switches"; - -- For backward compatiblity + -- For backward compatibility Old_Specification_Attribute : constant Attribute_Pkg_String := "naming#specification"; Old_Implementation_Attribute : constant Attribute_Pkg_String := @@ -2284,12 +2332,14 @@ -- Internal version of Project_From_Path function Scenario_Variables - (Tree : Project_Tree_Data_Access) return Scenario_Variable_Array; + (Tree : Project_Tree_Data_Access; + Root_Only : Boolean := False) return Scenario_Variable_Array; pragma Inline (Scenario_Variables); -- Internal version of Scenario_Variables function Untyped_Variables - (Tree : Project_Tree_Data_Access) return Untyped_Variable_Array; + (Tree : Project_Tree_Data_Access; + Root_Only : Boolean := False) return Untyped_Variable_Array; pragma Inline (Untyped_Variables); -- Internal version of Untyped_Variables diff -Nru libgnatcoll-18/src/gnatcoll-projects-normalize.adb libgnatcoll-19/src/gnatcoll-projects-normalize.adb --- libgnatcoll-18/src/gnatcoll-projects-normalize.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-projects-normalize.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2002-2017, AdaCore -- +-- Copyright (C) 2002-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -831,7 +831,7 @@ Last_Values := Last_Values + 1; Values (Last_Values) := External_Variable_Value' (Variable_Type => Scenario_Variables (J).String_Type, - Variable_Name => Scenario_Variables (J).Name, + Variable_Name => Scenario_Variables (J).Ext_Name, Variable_Value => Scenario_Variables (J).Value, Negated => False); end loop; diff -Nru libgnatcoll-18/src/gnatcoll-projects-normalize.ads libgnatcoll-19/src/gnatcoll-projects-normalize.ads --- libgnatcoll-18/src/gnatcoll-projects-normalize.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-projects-normalize.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2002-2017, AdaCore -- +-- Copyright (C) 2002-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -25,11 +25,11 @@ -- Project files can be written freely by the user (through any standard -- editor). However, although we are able to import them whatever form they --- have, these can'be easily manipulated, and a different form needs to be +-- have, these can't be easily manipulated, and a different form needs to be -- used, called normalized project files. -- --- Projects are normalized only the first time they are actually modified (ie --- if they are open in the project browser but never modified, then we don't +-- Projects are normalized only the first time they are actually modified +-- (i.e. if they are open in the project browser but never modified, we don't -- need to modify what the user did, since GPR.Proc.Process can of course work -- with any form of projects). -- @@ -161,7 +161,7 @@ (Tree : GPR.Tree.Project_Node_Tree_Ref; Parent : GPR.Project_Node_Id; Node : GPR.Project_Node_Id); - -- Add Node at the begining of the list for Parent. + -- Add Node at the beginning of the list for Parent. -- Node can also be a N_Declarative_Item (or a list of them). procedure Normalize_Cases diff -Nru libgnatcoll-18/src/gnatcoll-promises.ads libgnatcoll-19/src/gnatcoll-promises.ads --- libgnatcoll-18/src/gnatcoll-promises.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-promises.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2017, AdaCore -- +-- Copyright (C) 2017-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -364,11 +364,11 @@ -- promise. function Is_Created - (Self : Promise'Class) return Boolean with Inline_Always; + (Self : Promise'Class) return Boolean with Inline; -- Whether the promise has been created function Get_State - (Self : Promise'Class) return Actual_Promise_State with Inline_Always; + (Self : Promise'Class) return Actual_Promise_State with Inline; -- Used for pre and post conditions private diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar.ads libgnatcoll-19/src/gnatcoll-ravenscar.ads --- libgnatcoll-18/src/gnatcoll-ravenscar.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This package contains a set of archetypes and patterns for concurrent --- programming using Ravenscar-compliant semantics only. The patterns are thus --- meant to be compiled with pragma Profile(Ravenscar) and run on Ravenscar --- run-time. - -package GNATCOLL.Ravenscar is - - subtype Millisecond is Integer range 0 .. Integer'Last; - - subtype Queue_Size is Integer range 2 .. Integer'Last; - - subtype Queue_Range is Positive; - -end GNATCOLL.Ravenscar; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.adb libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with GNATCOLL.Ravenscar.Utils; - -package body GNATCOLL.Ravenscar.Multiple_Queue_Cyclic_Server is - use GNATCOLL.Ravenscar.Utils; - - procedure Put_Request - (Req : Request; - Kind : Request_Kind) - is - begin - - -- Simply delegates to Protocol.Put - - Protocol.Put (Req, Kind); - - end Put_Request; - - protected body Protocol is - - procedure Put (Req : Request; Kind : Request_Kind) is - Ref : constant Request_Type_Ref := - Queues (Kind) (Insert_Index (Kind))'Access; - begin - - -- put the Req in the appropriate queue - - Queues (Kind) (Insert_Index (Kind)) := Req; - - -- increase insert index - - Increase_Counter (Insert_Index (Kind), QS); - if Pending < Pointer_Queue_Range_Max then - Pending := Pending + 1; - end if; - - -- save pointer to last Req on a queue - - Ptr_Queue (Pointer_Queue_Insert_Index) := (Kind, Ref); - Increase_Counter - (Pointer_Queue_Insert_Index, - Pointer_Queue_Range_Max); - - -- If there has been an overflow, increase also the Extract index. - -- This is because the insert index has surpassed the extract index, - -- overwriting older request. It is thus necessary to increase the - -- extract index to avoid to fetch a newly posted request instead - -- of older ones. - - if Pointer_Queue_Overflow then - Increase_Counter - (Pointer_Queue_Extract_Index, - Pointer_Queue_Range_Max); - end if; - - -- Check if the Insert_Index is going to surpass the extract index - - if Pointer_Queue_Insert_Index = Pointer_Queue_Extract_Index then - Pointer_Queue_Overflow := True; - end if; - - end Put; - - procedure Get_Next_Request (Req : out Request) is - Ref : Pointer_Queue_Item_Ref := null; - begin - - -- If the insert and extract index have the same value, it is - -- possible to avoid overflow if a request is fetched before a new - -- one is posted: this case addresses exactly this. - - if Pointer_Queue_Insert_Index = Pointer_Queue_Extract_Index then - Pointer_Queue_Overflow := False; - end if; - - -- get the oldest Req - - Ref := Ptr_Queue (Pointer_Queue_Extract_Index)'Access; - Increase_Counter - (Pointer_Queue_Extract_Index, - Pointer_Queue_Range_Max); - - Req := Ref.Req.all; - - -- decrease number of pending requests - - Pending := Pending - 1; - - end Get_Next_Request; - pragma Inline (Get_Next_Request); - - procedure Get (Req : out Request; Has_Pending : out Boolean) is - begin - - -- check if there are pending requests - - Has_Pending := Pending > 0; - if Pending > 0 then - Get_Next_Request (Req); - end if; - - end Get; - - end Protocol; - - task body Cyclic_Task is - Req : Request; - Next_Time : Ada.Real_Time.Time := System_Start_Time; - Has_Pending : Boolean := False; - use Ada.Real_Time; - begin - - Next_Time := Next_Time + Milliseconds (Phase); - - loop - - delay until Next_Time; - - Protocol.Get (Req, Has_Pending); - - if Has_Pending then - Dispatch (Req); - else - Cyclic_Operation; - end if; - - Next_Time := Next_Time + Milliseconds (Period); - - end loop; - - end Cyclic_Task; - -end GNATCOLL.Ravenscar.Multiple_Queue_Cyclic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.ads libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_cyclic_server.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,193 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This version of a Ravenscar-compliant cyclic server extends the behaviour --- of GNAT.Ravenscar.Simple_Cyclic_Task by accepting multiple types of --- requests reified in a single variant type; if no requests have been posted --- during the previous period, the server executes its nominal operation --- (Cyclic_Operation). It shares all basic properties of --- GNAT.Ravenscar.Simple_Cyclic_Task. --- --- A typical example of usage is the following: --- --- type Req is (REQ1, REQ2, REQ3); --- type Par (R : Req := REQ1) is --- record --- Req : Req := R; --- case R is --- when REQ1 => --- null; --- when REQ2 => --- P1 : Type1; --- when REQ3 => --- P2 : Type2; --- P3 : Type3; --- end case; --- end record; --- --- procedure Dispatch(P : Par) is --- begin --- case P.Req is --- when REQ1 => --- Do_Something; --- when REQ2 => --- Do_Something(P.P1); --- when REQ3 => --- Do_Something(P.P2, P.P3); --- end case; --- end Dispatch; --- --- procedure Cyclic_Operation; --- --- package My_Cyclic_Server is new GNAT.Ravenscar.Multiple_Queue_Cyclic_Server --- (Task_Priority => 10, --- Period => 1_000, --- Phase => 200, --- System_Start_Time => System_Properties.Start_UP_Time, --- Cyclic_Operation => Cyclic_Operation, --- Protocol_Ceiling => 15, --- QS => 4, --- Request_Kind => Req, --- Param => Par, --- Dispatch => Dispatch); --- --- [...] --- declare --- P : Par(REQ2); --- begin --- -- fill parameters --- P.P2 := Val; --- -- Release the task -- --- My_Sporadic_Task.Put_Request(P); --- --- BEHAVIOUR --- If no Req is posted via Put_Request, My_Cyclic_Server executes --- Cyclic_Operation at its frequency; otherwise it fulfill the posted Req. - -with System; -with Ada.Real_Time; - -generic - - Task_Priority : System.Priority; - -- the priority of the server - - Period : Millisecond; - -- the constant perios of the server - - System_Start_Time : Ada.Real_Time.Time := Ada.Real_Time.Clock; - -- the absolute instant in time for the release of the systems as a whole - - Phase : Millisecond; - -- the phase of the server - - with procedure Cyclic_Operation; - -- the nominal operation which is executed if no requestests have been - -- posted within the previous cycle - - Protocol_Ceiling : System.Any_Priority; - -- the ceiling priority of the protected object used to post and fetch - -- requests - - QS : Queue_Size; - -- the size of accepted requests - - type Request_Kind is (<>); - -- an enumeration type identificng the possible kinds of request - - type Request is private; - -- the reified request type - - with procedure Dispatch (Req : Request); - -- the procedure invoked by the server to dispatch the fetched request - -package GNATCOLL.Ravenscar.Multiple_Queue_Cyclic_Server is - - procedure Put_Request - (Req : Request; - Kind : Request_Kind); - -- Invoked by clients to post reified requests to be fetched and executed - -- by the server - -private - - type Request_Type_Ref is access all Request; - -- pointer type for request - - type Request_Queue is array (1 .. QS) of aliased Request; - -- physical queue for posted requests - - type All_Queue is array (Request_Kind'Range) of Request_Queue; - -- the entire set of queues (one for each possible request) - - type All_Queue_Index is array (Request_Kind'Range) of Queue_Range; - -- type to collect all indexes to access requests - - Pointer_Queue_Range_Max : constant Integer := QS; - -- maximum index value - - type Pointer_Queue_Item is record - Kind : Request_Kind; - Req : Request_Type_Ref; - end record; - -- reified request descriptor saved in a queue - - type Pointer_Queue_Item_Ref is access all Pointer_Queue_Item; - -- pointer type to reified request descriptors - - type Pointer_Queue is - array (Integer range 1 .. Pointer_Queue_Range_Max) - of aliased Pointer_Queue_Item; - -- logical queue of posted requests - - protected Protocol is - pragma Priority (Protocol_Ceiling); - - procedure Put (Req : Request; Kind : Request_Kind); - - procedure Get (Req : out Request; Has_Pending : out Boolean); - - private - Queues : All_Queue; - Insert_Index : All_Queue_Index := (others => 1); - Pending : Integer := 0; - Ptr_Queue : Pointer_Queue := - (others => (Request_Kind'First, null)); - Pointer_Queue_Insert_Index : Integer := 1; - Pointer_Queue_Extract_Index : Integer := 1; - Pointer_Queue_Overflow : Boolean := False; - end Protocol; - -- the protected object used to post/fetch requests - - task Cyclic_Task is - pragma Priority (Task_Priority); - end Cyclic_Task; - -- the cyclic server - -end GNATCOLL.Ravenscar.Multiple_Queue_Cyclic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.adb libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,159 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with GNATCOLL.Ravenscar.Utils; - -package body GNATCOLL.Ravenscar.Multiple_Queue_Sporadic_Server is - use GNATCOLL.Ravenscar.Utils; - - procedure Put_Request - (Req : Request; - Kind : Request_Kind) - is - begin - - -- Simply delegates to Protocol.Put - - Protocol.Put (Req, Kind); - - end Put_Request; - - protected body Protocol is - - procedure Update_Barrier is - begin - Barrier := Pending > 0; - end Update_Barrier; - pragma Inline (Update_Barrier); - - procedure Put - (Req : Request; - Kind : Request_Kind) - is - Ref : constant Request_Type_Ref := - Queues (Kind) (Insert_Index (Kind))'Access; - begin - - -- put the Req in the appropriate queue - - Queues (Kind) (Insert_Index (Kind)) := Req; - - -- increase insert index - - Increase_Counter (Insert_Index (Kind), QS); - if Pending < Pointer_Queue_Range_Max then - Pending := Pending + 1; - end if; - - -- save pointer to last Req on a queue - - Ptr_Queue (Pointer_Queue_Insert_Index) := (Kind, Ref); - Increase_Counter - (Pointer_Queue_Insert_Index, - Pointer_Queue_Range_Max); - - -- if there has been an overflow, increase also the Extract index. - -- This is because the insert index has surpassed the extract index, - -- overwriting older request. It is thus necessary to increase the - -- extract index to avoid to fetch a newly posted request instead - -- of older ones. - - if Pointer_Queue_Overflow then - Increase_Counter - (Pointer_Queue_Extract_Index, - Pointer_Queue_Range_Max); - end if; - - -- Check if the Insert_Index is going to surpass the extract index - if Pointer_Queue_Insert_Index = Pointer_Queue_Extract_Index then - Pointer_Queue_Overflow := True; - end if; - - -- update the barrier - - Update_Barrier; - - end Put; - - procedure Get_Next_Request (Req : out Request) is - Ref : Pointer_Queue_Item_Ref := null; - begin - - if Pointer_Queue_Insert_Index = Pointer_Queue_Extract_Index then - Pointer_Queue_Overflow := False; - end if; - - -- get the oldest Req - Ref := Ptr_Queue (Pointer_Queue_Extract_Index)'Access; - Increase_Counter - (Pointer_Queue_Extract_Index, - Pointer_Queue_Range_Max); - - Req := Ref.Req.all; - - Pending := Pending - 1; - - end Get_Next_Request; - pragma Inline (Get_Next_Request); - - entry Get - (Req : out Request; - Release_Time : out Ada.Real_Time.Time) when Barrier - is - begin - Release_Time := Ada.Real_Time.Clock; - Get_Next_Request (Req); - Update_Barrier; - end Get; - - end Protocol; - - task body Sporadic_Task is - Req : Request; - Release_Time : Ada.Real_Time.Time; - Next_Time : Ada.Real_Time.Time := System_Start_Time; - use Ada.Real_Time; - begin - - loop - - -- report.Print(natural'Image(Pointer_Queue_Range_Max)); - delay until Next_Time; - - Protocol.Get (Req, Release_Time); - - Dispatch (Req); - - Next_Time := Release_Time + Milliseconds (Minimum_Interelease_Time); - - end loop; - - end Sporadic_Task; - -end GNATCOLL.Ravenscar.Multiple_Queue_Sporadic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.ads libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-multiple_queue_sporadic_server.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,183 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- This version of a Ravenscar-compliant sporadic server extends the behaviour --- of GNAT.Ravenscar.Sporadic_Server by accepting multiple types of requests --- reified in a single variant type. It shares all basic properties of --- GNAT.Ravenscar.Sporadic_Server. --- --- A typical example of usage is the following: --- --- type Req is (REQ1, REQ2, REQ3); --- type Par (R : Req := REQ1) is --- record --- Req : Req := R; --- case R is --- when REQ1 => --- null; --- when REQ2 => --- P1 : Type1; --- when REQ3 => --- P2 : Type2; --- P3 : Type3; --- end case; --- end record; --- --- procedure Dispatch(P : Par) is --- begin --- case P.Req is --- when REQ1 => --- Do_Something; --- when REQ2 => --- Do_Something(P.P1); --- when REQ3 => --- Do_Something(P.P2, P.P3); --- end case; --- end Dispatch; --- --- package My_Sporadic_Server is --- new GNAT.Ravenscar.Multiple_Queue_Sporadic_Server --- (Task_Priority => 10, --- Minimum_Interelease_Time => 1_000, --- Protocol_Ceiling => 15, --- System_Start_Time => System_Properties.Start_UP_Time, --- QS => 4, --- Request_Kind => Req, --- Param => Par, --- Dispatch => Dispatch); --- --- [...] --- declare --- P : Par(REQ2); --- begin --- -- fill parameters --- P.P2 := Val; --- -- Release the task -- --- My_Sporadic_Server.Put_Request(P); - -with System; -with Ada.Real_Time; - -generic - - Task_Priority : System.Priority; - -- the priority of the server - - Minimum_Interelease_Time : Millisecond; - -- the minimum time between two consecutive releases - - System_Start_Time : Ada.Real_Time.Time := Ada.Real_Time.Clock; - -- the absolute instant in time for the release of the systems as a whole - - Protocol_Ceiling : System.Any_Priority; - -- the ceiling priority of the protected object used to post and fetch - -- requests - - QS : Queue_Size; - -- the size of accepted requests - - type Request_Kind is (<>); - -- an enumeration type identificng the possible kinds of request - - type Request is private; - -- the reified request type - - with procedure Dispatch (Req : Request); - -- the procedure invoked by the server to dispatch the fetched request - -package GNATCOLL.Ravenscar.Multiple_Queue_Sporadic_Server is - - procedure Put_Request - (Req : Request; - Kind : Request_Kind); - -- Invoked by clients to post reified requests to be fetched and executed - -- by the server - -private - - type Request_Type_Ref is access all Request; - -- pointer type for request - - type Request_Queue is array (1 .. QS) of aliased Request; - -- physical queue for posted requests - - type All_Queue is array (Request_Kind'Range) of Request_Queue; - -- the entire set of queues (one for each possible request) - - type All_Queue_Index is array (Request_Kind'Range) of Queue_Range; - -- type to collect all indexes to access requests - - Pointer_Queue_Range_Max : constant Integer := QS; - -- maximum index value - - type Pointer_Queue_Item is record - Kind : Request_Kind; - Req : Request_Type_Ref; - end record; - -- reified request descriptor saved in a queue - - type Pointer_Queue_Item_Ref is access all Pointer_Queue_Item; - -- pointer type to reified request descriptors - - type Pointer_Queue is - array (Integer range 1 .. Pointer_Queue_Range_Max) - of aliased Pointer_Queue_Item; - -- logical queue of posted requests - - protected Protocol is - -- the protected object used to post/fetch requests - - pragma Priority (Protocol_Ceiling); - - procedure Put - (Req : Request; - Kind : Request_Kind); - - entry Get - (Req : out Request; - Release_Time : out Ada.Real_Time.Time); - - private - Barrier : Boolean := False; - Queues : All_Queue; - Insert_Index : All_Queue_Index := (others => 1); - Pending : Integer := 0; - Ptr_Queue : Pointer_Queue := - (others => (Request_Kind'First, null)); - Pointer_Queue_Insert_Index : Integer := 1; - Pointer_Queue_Extract_Index : Integer := 1; - Pointer_Queue_Overflow : Boolean := False; - end Protocol; - - task Sporadic_Task is - pragma Priority (Task_Priority); - end Sporadic_Task; - -- the cyclic server - -end GNATCOLL.Ravenscar.Multiple_Queue_Sporadic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-simple_cyclic_task.adb libgnatcoll-19/src/gnatcoll-ravenscar-simple_cyclic_task.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-simple_cyclic_task.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-simple_cyclic_task.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package body GNATCOLL.Ravenscar.Simple_Cyclic_Task is - - task body Simple_Cyclic_Task is - use Ada.Real_Time; - Next_Time : Time := System_Start_Time + Milliseconds (Phase); - begin - loop - delay until Next_Time; - Cyclic_Operation; - Next_Time := Next_Time + Milliseconds (Period); - end loop; - end Simple_Cyclic_Task; - -end GNATCOLL.Ravenscar.Simple_Cyclic_Task; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-simple_cyclic_task.ads libgnatcoll-19/src/gnatcoll-ravenscar-simple_cyclic_task.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-simple_cyclic_task.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-simple_cyclic_task.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,81 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- A simple archetype of a Ravenscar-compliant cyclic task. The task is meant --- to be released at a constant time interval and to execute at --- a contant priority level (a part when subject to the immediate priority --- ceiling protocol). --- --- The task timing behaviour can be analyzed with the most common timing --- analysis techniques. --- --- A typical example of usage is the following: --- --- procedure Cyclic_Operation; --- package My_Cyclic_Task is new GNATCOLL.Ravenscar.Simple_Cyclic_Task --- (Task_Priority => 10, --- Phase => 1_000, --- Period => 1_000, --- System_Start_Time => System_Properties.Start_UP_Time, --- Cyclic_Operation => Cyclic_Operation); --- --- The instantiation generates a cyclic task which executes at priority 10, --- is released for the first time at System_UP_Time + Phase, executes --- Cyclic_Operation, and suspends itself until Period milliseconds have passed --- from the previous release. - -with System; -with Ada.Real_Time; - -generic - - Task_Priority : System.Priority; - -- the task priority - - Phase : Millisecond; - -- the task phse - - Period : Millisecond; - -- the task period - - System_Start_Time : Ada.Real_Time.Time := Ada.Real_Time.Clock; - -- system-wide release instant - - with procedure Cyclic_Operation; - -- the nominal operation - -package GNATCOLL.Ravenscar.Simple_Cyclic_Task is - -private - - task Simple_Cyclic_Task is - pragma Priority (Task_Priority); - end Simple_Cyclic_Task; - -end GNATCOLL.Ravenscar.Simple_Cyclic_Task; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-simple_sporadic_task.adb libgnatcoll-19/src/gnatcoll-ravenscar-simple_sporadic_task.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-simple_sporadic_task.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-simple_sporadic_task.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,77 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package body GNATCOLL.Ravenscar.Simple_Sporadic_Task is - - procedure Release is - begin - Protocol.Release; - end Release; - - protected body Protocol is - - procedure Update_Barrier is - begin - Barrier := Pending > 0; - end Update_Barrier; - pragma Inline (Update_Barrier); - - procedure Release is - begin - Pending := Pending + 1; - Update_Barrier; - end Release; - - entry Wait (Release_Time : out Ada.Real_Time.Time) when Barrier is - begin - - -- keep track of the release instant to guarantee a faithful - -- interelease time - - Release_Time := Ada.Real_Time.Clock; - Pending := Pending - 1; - Update_Barrier; - end Wait; - - end Protocol; - - task body Simple_Sporadic_Task is - use Ada.Real_Time; - Next_Time : Time := System_Start_Time; - Release_Time : Time; - begin - loop - delay until Next_Time; - Protocol.Wait (Release_Time); - Sporadic_Operation; - Next_Time := Release_Time + Milliseconds (Minimum_Interelease_Time); - end loop; - end Simple_Sporadic_Task; - -end GNATCOLL.Ravenscar.Simple_Sporadic_Task; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-simple_sporadic_task.ads libgnatcoll-19/src/gnatcoll-ravenscar-simple_sporadic_task.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-simple_sporadic_task.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-simple_sporadic_task.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,109 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- A simple archetype of a Ravenscar-compliant sporadic task. The task is --- meant to enforce a minimum interelease interval and to execute at a contant --- priority level (a part when subject to the immediate priority ceiling --- protocol). The suspension/release mechanism is managed by a protected --- object. In the worst case, the task behaviour is identical to the behaviour --- of a cyclic task (GNAT.Ravenscar.Simple_Cyclic_Task) with Period = --- Minimum_Interelease_Time. --- --- The task timing behaviour can be analyzed with the most common timing --- analysis techniques. --- --- A typical example of usage is the following: --- --- procedure Sporadic_Operation; --- package My_Sporadic_Task is new GNATCOLL.Ravenscar.Simple_Sporadic_Task --- (Task_Priority => 10, --- Minimum_Interelease_Time => 1_000, --- Protocol_Ceiling => 15, --- System_Start_Time => System_Properties.Start_UP_Time, --- Sporadic_Operation => Sporadic_Operation); --- --- [...] --- -- Release the task -- --- My_Sporadic_Task.Release; --- [...] --- --- The instantiation generates a sporadic task which executes at priority 10, --- is ready to executed starting from System_UP_Time + Phase, executes --- Sporadic_Operation, and enforce a minimum interelease time of 1000 --- milliseconds. Protocol_Ceiling is the ceiling priority of the protected --- object managing the suspension/release mechanism of the task: the protected --- object is accessed by both the clients (via Release) and the sporadic task --- itself. Protocol_Ceiling must be equal to the priority of the client with --- the highest priority, including the task itself (Task_Priority). - -with Ada.Real_Time; -with System; - -generic - - Task_Priority : System.Priority; - -- The priority of the task - - Minimum_Interelease_Time : Millisecond; - -- The minimum time between two consecutive releases - - System_Start_Time : Ada.Real_Time.Time := Ada.Real_Time.Clock; - -- the system-wide relase time - - Protocol_Ceiling : System.Any_Priority; - -- the ceiling priority of the protected object used to post and fetch - -- requests - - with procedure Sporadic_Operation; - -- the nominal operation - -package GNATCOLL.Ravenscar.Simple_Sporadic_Task is - - procedure Release; - -- used by client to trigger the task - -private - - protected Protocol is - pragma Priority (Protocol_Ceiling); - - procedure Release; - - entry Wait (Release_Time : out Ada.Real_Time.Time); - - private - Barrier : Boolean := False; - Pending : Integer := 0; - end Protocol; - - task Simple_Sporadic_Task is - pragma Priority (Task_Priority); - end Simple_Sporadic_Task; - -end GNATCOLL.Ravenscar.Simple_Sporadic_Task; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server.adb libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,124 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -with GNATCOLL.Ravenscar.Utils; - -package body GNATCOLL.Ravenscar.Sporadic_Server is - use GNATCOLL.Ravenscar.Utils; - - procedure Put_Request (Par : Param) is - begin - -- just a delegation - Protocol.Put_Request (Par); - end Put_Request; - - protected body Protocol is - - procedure Update_Barrier is - begin - Barrier := Pending > 0; - end Update_Barrier; - pragma Inline (Update_Barrier); - - procedure Put_Request (Par : Param) is - begin - - Buffer (Insert_Index) := Par; - Increase_Counter (Insert_Index, QS); - - -- Check if with the posting of this message, the Insert_Index is - -- greater of the extract index: if so, increase also the extract - -- index to avoid fetching a newer request when older ones are - -- pending - - if Buffer_Overflow then - Increase_Counter (Extract_Index, QS); - end if; - - -- increase the number of pending request but do not overcome the - -- maximum - - if Pending < QS then - Pending := Pending + 1; - end if; - - -- If Insert_Index = Extract_Index, then at the next posting an - -- overflow may occour - - if Insert_Index = Extract_Index then - Buffer_Overflow := True; - end if; - - Update_Barrier; - - end Put_Request; - - entry Get_Request - (Release_Time : out Ada.Real_Time.Time; - Par : out Param) when Barrier - is - begin - - -- get the real release time - - Release_Time := Ada.Real_Time.Clock; - - -- cancel the overflow if fetching request - - if Extract_Index = Insert_Index then - Buffer_Overflow := False; - end if; - - Par := Buffer (Extract_Index); - - Increase_Counter (Extract_Index, QS); - - Pending := Pending - 1; - - Update_Barrier; - - end Get_Request; - - end Protocol; - - task body Sporadic_Task is - use Ada.Real_Time; - Next_Time : Time := System_Start_Time; - Release_Time : Time; - Par : Param; - begin - loop - delay until Next_Time; - Protocol.Get_Request (Release_Time, Par); - Sporadic_Operation (Par); - Next_Time := Release_Time + Milliseconds (Minimum_Interelease_Time); - end loop; - end Sporadic_Task; - -end GNATCOLL.Ravenscar.Sporadic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server.ads libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,123 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- A simple archetype of a Ravenscar-compliant sporadic server: it extends the --- sporadic task archetype (GNAT.RAVENSCAR.Simple_Sporadic_Task) by permitting --- to carry parameters for the release of the task. The sporadic operation is --- of course called in a deferred way, so parameters are always IN by --- construction. --- --- A typical example of usage is the following: --- --- type Par is ... --- procedure Sporadic_Operation(P : Par); --- package My_Sporadic_Server is new GNATCOLL.Ravenscar.Sporadic_Server --- (Task_Priority => 10, --- Minimum_Interelease_Time => 1_000, --- Protocol_Ceiling => 15, --- System_Start_Time => System_Properties.Start_UP_Time, --- QS => 4, --- Param => Par, --- Sporadic_Operation => Sporadic_Operation); --- --- [...] --- declare --- P : Par; --- begin --- -- Release the task -- --- My_Sporadic_Server.Put_Request(P); --- --- --- Explanations for GNAT.Ravenscar.Sporadic_Task still hold; QS is the --- maximium numbered of buffered requests, which are executed following a FIFO --- policy. - -with System; -with Ada.Real_Time; - -generic - - Task_Priority : System.Priority; - -- The priority of the task - - Minimum_Interelease_Time : Millisecond; - -- The minimum time between two consecutive releases - - System_Start_Time : Ada.Real_Time.Time := Ada.Real_Time.Clock; - -- the system-wide relase time - - Protocol_Ceiling : System.Any_Priority; - -- the ceiling priority of the protected object used to post and fetch - -- requests - - QS : Queue_Size; - -- the maximum number of buffered requests - - type Param is private; - -- the descriptor of the request to be fulfilled by the server - - with procedure Sporadic_Operation (Par : Param); - -- the procedure to be executed by the server - -package GNATCOLL.Ravenscar.Sporadic_Server is - - procedure Put_Request (Par : Param); - -- Invoked by the client to post as request and trigger the server - -private - - type Queue is array (1 .. QS) of Param; - -- the queue containing reified requests - - protected Protocol is - -- the protected object containing the request queue - - pragma Priority (Protocol_Ceiling); - - procedure Put_Request (Par : Param); - - entry Get_Request - (Release_Time : out Ada.Real_Time.Time; - Par : out Param); - - private - Barrier : Boolean := False; - Pending : Integer := 0; - Insert_Index : Integer := 1; - Extract_Index : Integer := 1; - Buffer : Queue; - Buffer_Overflow : Boolean := False; - end Protocol; - - task Sporadic_Task is - pragma Priority (Task_Priority); - end Sporadic_Task; - -- the sporadic server - -end GNATCOLL.Ravenscar.Sporadic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server_with_callback.adb libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server_with_callback.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server_with_callback.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server_with_callback.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,58 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package body GNATCOLL.Ravenscar.Sporadic_Server_With_Callback is - - procedure Put_Request - (In_Par : In_Param; - CB : Callback) - is - begin - - -- a simple delegation - - My_Sporadic_Task.Put_Request ((In_Par, CB)); - - end Put_Request; - - procedure Dispatch (Req : Queue_Item) is - Out_Par : Out_Param; - begin - - -- first execute the nominal operation - - Sporadic_Operation (Req.In_Par, Out_Par); - - -- then the callback - - Req.CB.all (Out_Par); - - end Dispatch; - -end GNATCOLL.Ravenscar.Sporadic_Server_With_Callback; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server_with_callback.ads libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server_with_callback.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-sporadic_server_with_callback.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-sporadic_server_with_callback.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- Ravenscar tasks always communicate via messages or shared resources. It is --- thus not possible to have a deferred operation (an operation executed by a --- dedicated task) which carries OUT parameters. This archetype shows a --- solution to this expressive limit by extending --- GNAT.Ravenscar.Sporadic_Server. Clients release the server passing IN --- parameters and a pointer to a procedure: the latter is automatically --- called passing the computed value of OUT parameters of the deferred --- operation executed by the sporadic server. --- --- A tipical example of usage is the following: --- --- type IN_Param is ... --- type OUT_Param is ... --- procedure Sporadic_Operation(In_P : IN_Param; OUT_P : out OUT_Param); --- procedure CallBack (P : OUT_Param); --- package My_Sporadic_Server is --- new GNATCOLL.Ravenscar.Sporadic_Server_With_Callback --- Task_Priority => 10, --- Minimum_Interelease_Time => 1_000, --- Protocol_Ceiling => 15, --- System_Start_Time => System_Properties.Start_UP_Time, --- QS => 4, --- IN_Param_Type => IN_Param, --- OUT_Param_Type => IOUT_Param, --- Sporadic_Operation => Sporadic_Operation); --- --- [...] --- declare --- P : IN_Param; --- begin --- -- Release the task -- --- My_Sporadic_Server.Put_Request(P, Callback'access); --- --- BEHAVIOUR: --- My_Sporadic_Server executes Sporadic_Operation and Callback passing as --- parameters the values computed by Sporadic_Operation. --- --- Additional explanations for GNAT.Ravenscar.Sporadic_Server still hold. - -with System; -with Ada.Real_Time; -with GNATCOLL.Ravenscar.Sporadic_Server; - -generic - - Task_Priority : System.Priority; - -- the task priority - - Minimum_Interelease_Time : Millisecond; - -- the minimum time between two consecutive releases - - System_Start_Time : Ada.Real_Time.Time := Ada.Real_Time.Clock; - -- the system-wide release instant - - Protocol_Ceiling : System.Any_Priority; - -- the ceiling priority of the protected object used to post and fetch - -- requests - - QS : Queue_Size; - -- the maximum amount of saved requests - - type In_Param is private; - -- the descriptor of IN parameters - - type Out_Param is private; - -- the descriptor of OUT parameters - - with procedure Sporadic_Operation - (In_Par : In_Param; - Out_par : out Out_Param); - -- the nominal operation - -package GNATCOLL.Ravenscar.Sporadic_Server_With_Callback is - - type Callback is access procedure (Out_Par : Out_Param); - -- the type of the callback - - procedure Put_Request - (In_Par : In_Param; - CB : Callback); - -- invoked by clients to put requests (and corresponding callback) - -private - - type Queue_Item is record - In_Par : In_Param; - CB : Callback; - end record; - -- a reifed request descriptor containing IN parameters and callback - - procedure Dispatch (Req : Queue_Item); - -- the dispatch procedure first executes the posted request and then - -- the callback - - package My_Sporadic_Task is new GNATCOLL.Ravenscar.Sporadic_Server - (Task_Priority, - Minimum_Interelease_Time, - System_Start_Time, - Protocol_Ceiling, - QS, - Queue_Item, - Dispatch); - -- a sporadic server to execute reqeusts - -end GNATCOLL.Ravenscar.Sporadic_Server_With_Callback; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-timed_out_sporadic_server.adb libgnatcoll-19/src/gnatcoll-ravenscar-timed_out_sporadic_server.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-timed_out_sporadic_server.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-timed_out_sporadic_server.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package body GNATCOLL.Ravenscar.Timed_Out_Sporadic_Server is - - procedure Put_Request (Par : Param) renames - Timed_Out_Sporadic_Server.Put_Request; - - procedure Handler is - begin - Ada.Synchronous_Task_Control.Set_True (Timer_Server_Suspender); - end Handler; - - task body Timer_Server is - use Ada.Real_Time; - begin - - loop - - -- set to False the suspension object - - Ada.Synchronous_Task_Control.Set_False (Timer_Server_Suspender); - - -- wait on the suspension object to be set to true by the timing - -- event - - Ada.Synchronous_Task_Control.Suspend_Until_True - (Timer_Server_Suspender); - - -- when triggered, execute the handler - - Time_Out_Handler; - - -- and set the next release instant for the timer to Clock + - -- Maximum_Interelease_Time - - My_Timer.Set - (Clock + Milliseconds (Maximum_Interelease_Time), - Handler_Access); - - end loop; - - end Timer_Server; - - procedure Timed_Out_Sporadic_Operation (Par : Param) is - use Ada.Real_Time; - Next_Time_Out_Instant : constant Ada.Real_Time.Time := - Clock + Milliseconds (Maximum_Interelease_Time); - begin - - -- Set the timer to the next instant - - My_Timer.Set (Next_Time_Out_Instant, Handler_Access); - - -- execute the operation - - Sporadic_Operation (Par); - - end Timed_Out_Sporadic_Operation; - -end GNATCOLL.Ravenscar.Timed_Out_Sporadic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-timed_out_sporadic_server.ads libgnatcoll-19/src/gnatcoll-ravenscar-timed_out_sporadic_server.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-timed_out_sporadic_server.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-timed_out_sporadic_server.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- Ravenscar constraints prohibit the use of language-level timeout facilities --- (via the select statement). This archetype manage to mimic the semantics of --- a timeout within Ravenscar constraints: if the server is not released --- (via Put_Request) within Maximum_Interelase_Time, it is automatically --- released by the run-time and invokes an appropriate, user-specified handler --- --- A typical example of usage is the following: --- --- type Par is ... --- procedure Sporadic_Operation(P : Par); --- procedure Handler; --- package My_Sporadic_Server is new Ravenscar.Timed_Out_Sporadic_Server --- (Task_Priority => 10, --- Minimum_Interelease_Time => 1_000, --- Maximum_Interelease_Time => 2_000, -- wait at most 2 seconds --- Protocol_Ceiling => 15, --- System_Start_Time => System_Properties.Start_UP_Time, --- QS => 4, --- Param => Par, --- Sporadic_Operation => Sporadic_Operation, --- Time_Out_Handler => Handler); --- --- [...] --- declare --- P : Par; --- begin --- -- Release the task -- --- My_Sporadic_Server.Put_Request(P); --- --- BEHAVIOUR --- If the time elapsed between two consecutive releases of the server is --- greater then Maximimum_Interelease_Time, then Handler is invoked. --- --- Explanations for GNAT.Ravenscar.Sporadic_Server still hold. --- --- NOTE FOR THE ANALYSIS: the pattern is implemented as follows: --- (1) A Timer is set to expires at each Maximum_Interelease_Time --- (a) I can be deleted and re-set if the server is released --- (b) If it expires, it release an additional task (see point 2) --- (2) An additional sporadic task with minimum_interarrival_time = --- maximum_interarrival_time is suspended waiting to be released by the --- timer at point (1): this task executes the handler. It suspends on a --- Suspension_Object. - -with Ada.Real_Time; -with System; -with Ada.Synchronous_Task_Control; -with GNATCOLL.Ravenscar.Sporadic_Server; -with GNATCOLL.Ravenscar.Timers.One_Shot_Timer; - -generic - - Task_Priority : System.Priority; - -- The priority of the task - - Minimum_Interelease_Time : Millisecond; - -- The minimum time between two consecutive releases - - Maximum_Interelease_Time : Millisecond; - -- the maximum interrelease time which trigger the automatic release - -- of the server - - System_Start_Time : Ada.Real_Time.Time := Ada.Real_Time.Clock; - -- the system-wide relase time - - Protocol_Ceiling : System.Any_Priority; - -- the ceiling priority of the protected object used to post and fetch - -- requests - - QS : Queue_Size; - -- the maximum number of saved requests - - type Param is private; - -- the request descriptor - - with procedure Sporadic_Operation (Par : Param); - -- the procedure invoked when the server is released by the client - - with procedure Time_Out_Handler; - -- the handler executed by the server when non released the maximum - -- interrelease time - -package GNATCOLL.Ravenscar.Timed_Out_Sporadic_Server is - - procedure Put_Request (Par : Param); - -- invoked by the clients - -private - - procedure Timed_Out_Sporadic_Operation (Par : Param); - - package Timed_Out_Sporadic_Server is new Sporadic_Server - (Task_Priority, - Minimum_Interelease_Time, - System_Start_Time, - Protocol_Ceiling, - QS, - Param, - Timed_Out_Sporadic_Operation); - -- The sporadic server - - Timer_Server_Suspender : Ada.Synchronous_Task_Control.Suspension_Object; - -- A suspension object for the timer server (see below) - - task Timer_Server is - pragma Priority (Task_Priority); - end Timer_Server; - -- The task which is triggered by the timer. We have an additional task - -- to avoid having the timer itself to execute (it runs at interrupt - -- priority). - - package My_Timer is new GNATCOLL.Ravenscar.Timers.One_Shot_Timer; - -- the timer triggering the task if no request is posted within - -- the maximum interrelease time - - procedure Handler; - - Handler_Access : constant GNATCOLL.Ravenscar.Timers.Timer_Action := - Handler'Access; - -end GNATCOLL.Ravenscar.Timed_Out_Sporadic_Server; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-timers.ads libgnatcoll-19/src/gnatcoll-ravenscar-timers.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-timers.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-timers.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,36 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- Contains types for Ravenscar timers - -package GNATCOLL.Ravenscar.Timers is - - type Timer_Action is access procedure; - -end GNATCOLL.Ravenscar.Timers; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-timers-one_shot_timer.adb libgnatcoll-19/src/gnatcoll-ravenscar-timers-one_shot_timer.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-timers-one_shot_timer.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-timers-one_shot_timer.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,85 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package body GNATCOLL.Ravenscar.Timers.One_Shot_Timer is - - --------- - -- Set -- - --------- - - procedure Set - (Instant : Ada.Real_Time.Time; - Action : Timer_Action) is - begin - -- Set the timer - - Events.Set_Action (Instant, Action); - end Set; - - ------------ - -- Cancel -- - ------------ - - procedure Cancel (Success : out Boolean) is - begin - -- cancel the timer - - Ada.Real_Time.Timing_Events.Cancel_Handler (The_Event, Success); - end Cancel; - - protected body Events is - - ------------- - -- Handler -- - ------------- - - procedure Handler - (Event : in out Ada.Real_Time.Timing_Events.Timing_Event) - is - pragma Unreferenced (Event); - begin - The_Action.all; - end Handler; - - ---------------- - -- Set_Action -- - ---------------- - - procedure Set_Action - (Instant : Ada.Real_Time.Time; - Action : Timer_Action) is - begin - The_Action := Action; - Ada.Real_Time.Timing_Events.Set_Handler - (The_Event, Instant, Events_Handler); - end Set_Action; - - end Events; - -end GNATCOLL.Ravenscar.Timers.One_Shot_Timer; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-timers-one_shot_timer.ads libgnatcoll-19/src/gnatcoll-ravenscar-timers-one_shot_timer.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-timers-one_shot_timer.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-timers-one_shot_timer.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,74 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- A Ravenscar-compliant one-shot timer - -with System; -with Ada.Real_Time; -with Ada.Real_Time.Timing_Events; - -generic -package GNATCOLL.Ravenscar.Timers.One_Shot_Timer is - - procedure Set - (Instant : Ada.Real_Time.Time; - Action : Timer_Action); - -- Set the timer to an absolute instant in time to execute a specific - -- action. - - procedure Cancel (Success : out Boolean); - -- cancel the timer - -private - - The_Event : Ada.Real_Time.Timing_Events.Timing_Event; - -- the timing event - - protected Events is - -- the handler used to invoke the user-provided action (see procedure - -- Set). - pragma Priority (System.Any_Priority'Last); - - procedure Handler - (Event : in out Ada.Real_Time.Timing_Events.Timing_Event); - - procedure Set_Action - (Instant : Ada.Real_Time.Time; - Action : Timer_Action); - - private - - The_Action : GNATCOLL.Ravenscar.Timers.Timer_Action; - - end Events; - - Events_Handler : constant Ada.Real_Time.Timing_Events.Timing_Event_Handler - := Events.Handler'Access; - -end GNATCOLL.Ravenscar.Timers.One_Shot_Timer; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-utils.adb libgnatcoll-19/src/gnatcoll-ravenscar-utils.adb --- libgnatcoll-18/src/gnatcoll-ravenscar-utils.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-utils.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - -package body GNATCOLL.Ravenscar.Utils is - - procedure Increase_Counter - (Counter : in out Integer; - Max : Integer; - Min : Integer := 1) - is - begin - if Counter = Max then - Counter := Min; - else - Counter := Counter + 1; - end if; - end Increase_Counter; - -end GNATCOLL.Ravenscar.Utils; diff -Nru libgnatcoll-18/src/gnatcoll-ravenscar-utils.ads libgnatcoll-19/src/gnatcoll-ravenscar-utils.ads --- libgnatcoll-18/src/gnatcoll-ravenscar-utils.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-ravenscar-utils.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- G N A T C O L L -- --- -- --- Copyright (C) 2008-2017, AdaCore -- --- -- --- GNAT is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 2, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT 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 distributed with GNAT; see file COPYING. If not, write -- --- to the Free Software Foundation, 51 Franklin Street, Fifth Floor, -- --- Boston, MA 02110-1301, USA. -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- -- --- GNAT was originally developed by the GNAT team at New York University. -- --- Extensive contributions were provided by Ada Core Technologies Inc. -- --- -- ------------------------------------------------------------------------------- - --- A collection of untilities used in GNATCOLL.Ravenscar -package GNATCOLL.Ravenscar.Utils is - - procedure Increase_Counter - (Counter : in out Integer; - Max : Integer; - Min : Integer := 1); - -- A procedure to increase a counter up to a maximum limit - -end GNATCOLL.Ravenscar.Utils; diff -Nru libgnatcoll-18/src/gnatcoll-refcount.adb libgnatcoll-19/src/gnatcoll-refcount.adb --- libgnatcoll-18/src/gnatcoll-refcount.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-refcount.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2010-2017, AdaCore -- +-- Copyright (C) 2010-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -40,15 +40,20 @@ with Ada.Unchecked_Conversion; with Ada.Unchecked_Deallocation; with GNATCOLL.Atomic; use GNATCOLL.Atomic; -with System.Memory; use System, System.Memory; +with System; use System; package body GNATCOLL.Refcount is - procedure Inc_Ref (R : access Counters; Atomic : Boolean) - with Inline => True; - procedure Inc_Ref (R : access Weak_Data; Atomic : Boolean) - with Inline => True; - -- Increase/Decrease the refcount, and return the new value + function Inc_Ref + (R : access Counters; Atomic : Boolean) return Atomic_Counter with Inline; + -- Increase the refcount and return the new value + + function Inc_Ref (R : access Counters; Atomic : Boolean) return Boolean; + -- Increase the refcount only if it was non-zero, returns True if the + -- increment has occurred. + + procedure Inc_Ref (R : access Weak_Data; Atomic : Boolean) with Inline; + -- Increase the refcount procedure Unchecked_Free is new Ada.Unchecked_Deallocation (Weak_Data, Weak_Data_Access); @@ -56,22 +61,55 @@ (Refcounted'Class, Refcounted_Access); procedure Finalize (Data : in out Weak_Data_Access; Atomic : Boolean); - -- Decrease refcount, and free memory if needed + -- Decrease refcount and free memory if needed - function Sync_Bool_Compare_And_Swap - is new GNATCOLL.Atomic.Sync_Bool_Compare_And_Swap - (Weak_Data, Weak_Data_Access); + function Sync_Bool_Compare_And_Swap is new Atomic.Sync_Bool_Compare_And_Swap + (Weak_Data, Weak_Data_Access); ------------- -- Inc_Ref -- ------------- - procedure Inc_Ref (R : access Counters; Atomic : Boolean) is + function Inc_Ref (R : access Counters; Atomic : Boolean) return Boolean is + Tmp : Atomic_Counter; + Tm2 : Atomic_Counter; begin if Atomic then - Increment (R.Refcount); + Tmp := R.Refcount; + if Tmp = 0 then + return False; + end if; + + loop + Tm2 := Sync_Val_Compare_And_Swap_Counter + (R.Refcount'Access, Tmp, Atomic_Counter'Succ (Tmp)); + if Tm2 = Tmp then + return True; + elsif Tm2 = 0 then + return False; + else + Tmp := Tm2; + end if; + end loop; + + else + if R.Refcount = 0 then + return False; + end if; + + R.Refcount := Atomic_Counter'Succ (R.Refcount); + return True; + end if; + end Inc_Ref; + + function Inc_Ref + (R : access Counters; Atomic : Boolean) return Atomic_Counter is + begin + if Atomic then + return Sync_Add_And_Fetch (R.Refcount'Access, 1); else Unsafe_Increment (R.Refcount); + return R.Refcount; end if; end Inc_Ref; @@ -99,8 +137,6 @@ Unchecked_Free (Data); end if; end if; - - Data := null; end Finalize; --------------------- @@ -168,7 +204,7 @@ ---------- function Weak (Self : Ref'Class) return Weak_Ref is - R : access Counters; + R : Counters_Access; V : Weak_Data_Access; begin if Self.Data = null then @@ -179,8 +215,9 @@ if R.Weak_Data = null then V := new Weak_Data' - (Refcount => 2, -- hold by Self and the result - Element => Convert (Self.Data)); + (Refcount => 2, -- hold by Self and the result + Lock => 0, + Element => Convert (Self.Data)); if not Sync_Bool_Compare_And_Swap (R.Weak_Data'Access, Oldval => null, Newval => V) then @@ -203,13 +240,34 @@ --------- procedure Set (Self : in out Ref'Class; Weak : Weak_Ref'Class) is + Data : Pools.Element_Access; + WD : Weak_Data_Access := Weak.Data; + NL : Atomic_Counter; begin Finalize (Self); - if not Weak.Was_Freed then - Self.Data := Convert (Weak.Data.Element); - Inc_Ref (Pools.Header_Of (Self.Data), Atomic_Counters); + if WD = null then + return; end if; + + Data := Convert (WD.Element); + + if Data = null then + return; + end if; + + if Integer (Sync_Add_And_Fetch (WD.Lock'Access, 2)) rem 2 /= 0 then + return; + end if; + + if Inc_Ref (Pools.Header_Of (Data), Atomic_Counters) then + Self.Data := Data; + end if; + + NL := Sync_Sub_And_Fetch (WD.Lock'Access, 2); + + pragma Assert + (Integer (NL) rem 2 = 0, "Unexpected Lock value " & NL'Img); end Set; --------------- @@ -219,7 +277,7 @@ function Was_Freed (Self : Weak_Ref'Class) return Boolean is begin return Self.Data = null - or else Self.Data.Element = System.Null_Address; + or else Self.Data.Element = System.Null_Address; end Was_Freed; --------- @@ -236,9 +294,13 @@ ------------ overriding procedure Adjust (Self : in out Ref) is + RC : Atomic_Counter; begin if Self.Data /= null then - Inc_Ref (Pools.Header_Of (Self.Data), Atomic_Counters); + RC := Inc_Ref (Pools.Header_Of (Self.Data), Atomic_Counters); + + pragma Assert + (RC > 1, "Unexpected reference counter after adjust" & RC'Img); end if; end Adjust; @@ -258,11 +320,14 @@ -------------- overriding procedure Finalize (Self : in out Weak_Ref) is - Data : Weak_Data_Access := Self.Data; begin - if Data /= null then + if Self.Data /= null then + Finalize (Self.Data, Atomic_Counters); + + -- Make Finalize idempotent, since it could be called several + -- times for the same instance (RM 7.6.1(24)). + Self.Data := null; - Finalize (Data, Atomic_Counters); end if; end Finalize; @@ -271,28 +336,40 @@ -------------- overriding procedure Finalize (Self : in out Ref) is - R : access Counters; + R : Counters_Access; Data : Pools.Element_Access := Self.Data; - Tmp : Boolean; begin if Data /= null then Self.Data := null; R := Pools.Header_Of (Data); - if Atomic_Counters then - Tmp := Decrement (R.Refcount); - else - Tmp := Unsafe_Decrement (R.Refcount); - end if; - if Tmp then + if (if Atomic_Counters + then Decrement (R.Refcount) + else Unsafe_Decrement (R.Refcount)) + then if R.Weak_Data /= null then - R.Weak_Data.Element := System.Null_Address; + R.Weak_Data.Element := Null_Address; + + -- Spinlock to wait until all Set Ref from Weak_Ref + -- operations completed. + + while R.Weak_Data.Lock /= 0 + or else not Sync_Bool_Compare_And_Swap_Counter + (R.Weak_Data.Lock'Access, 0, 1) + loop + -- Would be better to use GCC _mm_pause instruction + -- instead of zero delay but it is not supported in GCC + -- for all platforms. + + delay 0.0; + end loop; + Finalize (R.Weak_Data, Atomic_Counters); end if; Release (Data.all); - Unchecked_Free (Data); -- using storage_pool + Unchecked_Free (Data); -- using storage_pool end if; end if; end Finalize; diff -Nru libgnatcoll-18/src/gnatcoll-refcount.ads libgnatcoll-19/src/gnatcoll-refcount.ads --- libgnatcoll-18/src/gnatcoll-refcount.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-refcount.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2010-2017, AdaCore -- +-- Copyright (C) 2010-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -69,23 +69,25 @@ type Weak_Data is record Element : System.Address := System.Null_Address; - Refcount : aliased GNATCOLL.Atomic.Atomic_Counter; - pragma Volatile (Refcount); + Refcount : aliased Atomic.Atomic_Counter; + Lock : aliased Atomic.Atomic_Counter; + -- To resolve the race condition between the last Ref disappearing and + -- the new Ref creation from Weak_Ref. end record; type Weak_Data_Access is access all Weak_Data; type Counters is record - Refcount : aliased GNATCOLL.Atomic.Atomic_Counter := 1; - pragma Volatile (Refcount); - - Weak_Data : aliased Weak_Data_Access := null; - -- A pointer to the weak pointers'data. This data is created the + Refcount : aliased Atomic.Atomic_Counter := 1; + Weak_Data : aliased Weak_Data_Access; + -- A pointer to the weak pointer's data. This data is created the -- first time we create a weak pointer. We hold a reference to that -- data, so that it can never be freed while at least one reference -- exists. end record; - package Headers is new Header_Pools (Counters); + type Counters_Access is access all Counters; + + package Headers is new Header_Pools (Counters, Counters_Access); Application_Uses_Tasks : constant Boolean := System.Soft_Links.Lock_Task /= System.Soft_Links.Task_Lock_NT'Access; @@ -228,7 +230,7 @@ -- pointer itself, not the encapsulated value. function Unchecked_Get (Self : Ref'Class) return Element_Access - with Inline_Always; + with Inline; -- A version that returns directly the element access. This is meant -- for easy conversion of existing code, but its use is discouraged -- in new code, where Get should be used instead. @@ -239,7 +241,7 @@ function Get (Self : Ref'Class) return Reference_Type is ((Element => Unchecked_Get (Self))) - with Inline_Always; + with Inline; -- A safer version of Unchecked_Get. -- There is no performance penalty, since the compiler knows that a -- Reference_Type is in fact always of the same size and can be @@ -264,7 +266,7 @@ -- and the simple fact that Self is a parameter ensures it retains at -- least one reference during the execution of Process. -- - -- If you want to always be on the safe side and prevevent users from + -- If you want to always be on the safe side and prevent users from -- using Get, you could add the following configuration pragma to your -- compilation: -- pragma Restrictions @@ -391,7 +393,7 @@ private type Refcounted is abstract tagged record - Refcount : aliased GNATCOLL.Atomic.Atomic_Counter := 0; + Refcount : aliased Atomic.Atomic_Counter := 0; end record; -- This requires, as a result, that all refcounted types also be tagged -- types (thus adding the size of a tag and the size of an integer to each diff -Nru libgnatcoll-18/src/gnatcoll-scripts.ads libgnatcoll-19/src/gnatcoll-scripts.ads --- libgnatcoll-18/src/gnatcoll-scripts.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-scripts.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2003-2017, AdaCore -- +-- Copyright (C) 2003-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -24,8 +24,8 @@ -- This module provides various types and subprograms to integrate various -- external scripting languages. -- This API was designed so that multiple scripting languages can be used with --- your application, and so that the core of the applicatoin and all the --- various modules remain as independant as possible from the specific +-- your application, and so that the core of the application and all the +-- various modules remain as independent as possible from the specific -- language. pragma Ada_2012; @@ -58,7 +58,7 @@ type Callback_Data is abstract tagged private; type Callback_Data_Access is access all Callback_Data'Class; - -- Data used to communicate with the scripting language engine, to marshall + -- Data used to communicate with the scripting language engine, to marshal -- the parameters and return values. type Class_Instance is private; @@ -131,7 +131,7 @@ function Get_Name (Subprogram : access Subprogram_Record) return String is abstract; -- Return the name of the subprogram, as a string that can be displayed for - -- the user. This is used when analysing the contents of a hook for + -- the user. This is used when analyzing the contents of a hook for -- instance ------------------ @@ -154,7 +154,7 @@ Qualified_Name : String) return Module_Type; -- Lookup an existing module or create it if needed. -- The qualified name uses '.' as the separator, and all intermediate - -- levels are created as needed. The name of the toplevel module must be + -- levels are created as needed. The name of the top-level module must be -- included, so even if you passed "MyApp" as the Module name to -- Register_Python_Scripting, the qualified name here should look like -- MyApp.Module1.Module2 @@ -213,8 +213,6 @@ -- the first time the class is created (typically just before the matching -- calls to Register_Command), and can be left to its default value -- afterward. - -- Description of the new class must be put in the file shell_commands.xml, - -- which is read dynamically when generating the documentation. function Get_Name (Class : Class_Type) return String; -- Return the name of the class (module.name) @@ -912,7 +910,7 @@ return Callback_Data_Access; -- Return the data for a given script. -- The returned value should not be freed by the caller, it is the - -- responsability of the callback_data_list to do so. + -- responsibility of the callback_data_list to do so. procedure Set (Repo : access Scripts_Repository_Record'Class; @@ -1215,7 +1213,7 @@ Hide_Output : Boolean := False; Show_Command : Boolean := True; Errors : access Boolean) return String; - -- Same as above, working direcly on a String. This String is interpreted + -- Same as above, working directly on a String. This String is interpreted -- as a command line using the mechanism described in -- GNATCOLL.Command_Lines. -- These are only provided for backward compatibility and you should use @@ -1349,7 +1347,7 @@ Equal_Method : constant String; -- Should return a boolean, testing for equality. - -- Note that in python, at least, definining this will not automatically + -- Note that at least in python, defining this will not automatically -- define the inequality, so it might be better to use Comparison_Method -- instead. @@ -1431,10 +1429,6 @@ -- -- Destructor_Method is called just before the instance is destroyed -- - -- Description of the new command must be put in the file - -- shell_commands.xml, which is read dynamically when generating the - -- documentation. - -- -- If the command has some graphical output (dialog,...), it must run in -- a separate main loop (Gtk.Main.Gtk_Main or modal dialogs). -- @@ -1561,7 +1555,7 @@ -- Return the list of user data stored for this instance. Depending on the -- scripting language, this list might be stored in various places (as a -- python attribute, directly in Ada for the shell,...) This list is shared - -- amonst the scripting languages. + -- amongst the scripting languages. package CI_Pointers is new Smart_Pointers (Class_Instance_Record); type Class_Instance is record diff -Nru libgnatcoll-18/src/gnatcoll-scripts-impl.ads libgnatcoll-19/src/gnatcoll-scripts-impl.ads --- libgnatcoll-18/src/gnatcoll-scripts-impl.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-scripts-impl.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2003-2017, AdaCore -- +-- Copyright (C) 2003-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -39,7 +39,7 @@ (Script : access Scripting_Language_Record'Class; Console : Virtual_Console := null; Txt : String); - -- Display txt either on the specified console or on the scripts' default + -- Display Txt either on the specified console or on the scripts' default -- console if Console is set to null. -- If Hide is set to True, the text is not displayed on the console after -- all, although it will be displayed in the log instead. diff -Nru libgnatcoll-18/src/gnatcoll-scripts-projects.adb libgnatcoll-19/src/gnatcoll-scripts-projects.adb --- libgnatcoll-18/src/gnatcoll-scripts-projects.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-scripts-projects.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2003-2018, AdaCore -- +-- Copyright (C) 2003-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -591,37 +591,18 @@ function Scenario_Variables_Cmd_Line (Prefix : String) return String is Scenario_Vars : constant Scenario_Variable_Array := Project_Tree.Scenario_Variables; - - function Concat - (Current : String; Index : Natural; Set_Var : String) return String; - -- Concat the command line line for the Index-nth variable and the - -- following ones to Current, and return the result. - - ------------ - -- Concat -- - ------------ - - function Concat - (Current : String; Index : Natural; Set_Var : String) return String is - begin - if Index > Scenario_Vars'Last then - return Current; - end if; - - return Concat - (Current - & Set_Var & External_Name (Scenario_Vars (Index)) - & "=" & Value (Scenario_Vars (Index)) - & " ", - Index + 1, - Set_Var); - end Concat; - + Untyped_Vars : constant Untyped_Variable_Array := + Project_Tree.Untyped_Variables; + Res : Unbounded_String; begin - -- A recursive function is probably not the most efficient way, but this - -- prevents limits on the command line lengths. This also avoids the use - -- of unbounded strings. - return Concat ("", Scenario_Vars'First, Prefix); + for Var of Scenario_Vars loop + Append (Res, Prefix & External_Name (Var) & "=" & Value (Var) & " "); + end loop; + + for Var of Untyped_Vars loop + Append (Res, Prefix & External_Name (Var) & "=" & Value (Var) & " "); + end loop; + return To_String (Res); end Scenario_Variables_Cmd_Line; -------------- diff -Nru libgnatcoll-18/src/gnatcoll-scripts-projects.ads libgnatcoll-19/src/gnatcoll-scripts-projects.ads --- libgnatcoll-18/src/gnatcoll-scripts-projects.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-scripts-projects.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2003-2017, AdaCore -- +-- Copyright (C) 2003-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -34,7 +34,7 @@ -- Get current project tree function Project_Tree return GNATCOLL.Projects.Project_Tree_Access; - -- Get project tree from assigned project tree retriver pointer + -- Get project tree from assigned project tree retriever pointer procedure Register_Commands (Repo : not null access Scripts_Repository_Record'Class; diff -Nru libgnatcoll-18/src/gnatcoll-scripts-utils.ads libgnatcoll-19/src/gnatcoll-scripts-utils.ads --- libgnatcoll-18/src/gnatcoll-scripts-utils.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-scripts-utils.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2003-2017, AdaCore -- +-- Copyright (C) 2003-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -25,6 +25,8 @@ package GNATCOLL.Scripts.Utils is + use type GNAT.Strings.String_List_Access; + function Argument_List_To_Quoted_String (Args : GNAT.Strings.String_List; Quote : Character := '"'; @@ -44,7 +46,8 @@ -- As above but for a single argument function Argument_String_To_List_With_Triple_Quotes - (Arg_String : String) return GNAT.Strings.String_List_Access; + (Arg_String : String) return GNAT.Strings.String_List_Access + with Post => Argument_String_To_List_With_Triple_Quotes'Result /= null; -- This is similar to GNAT.OS_Lib.Argument_String_To_List, except that -- if part of the string is surrounded by triple quotes, any special -- character is ignored till the closing triple quotes. This is the same diff -Nru libgnatcoll-18/src/gnatcoll-storage_pools-alignment.adb libgnatcoll-19/src/gnatcoll-storage_pools-alignment.adb --- libgnatcoll-18/src/gnatcoll-storage_pools-alignment.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-storage_pools-alignment.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2005-2017, AdaCore -- +-- Copyright (C) 2005-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -36,7 +36,7 @@ -- Allocate -- -------------- - procedure Allocate + overriding procedure Allocate (Pool : in out Unbounded_No_Reclaim_Align_Pool; Address : out System.Address; Storage_Size : Storage_Count; @@ -77,7 +77,7 @@ -- Deallocate -- ---------------- - procedure Deallocate + overriding procedure Deallocate (Pool : in out Unbounded_No_Reclaim_Align_Pool; Address : System.Address; Storage_Size : Storage_Count; @@ -114,7 +114,7 @@ -- Storage_Size -- ------------------ - function Storage_Size + overriding function Storage_Size (Pool : Unbounded_No_Reclaim_Align_Pool) return Storage_Count is pragma Unreferenced (Pool); diff -Nru libgnatcoll-18/src/gnatcoll-storage_pools-alignment.ads libgnatcoll-19/src/gnatcoll-storage_pools-alignment.ads --- libgnatcoll-18/src/gnatcoll-storage_pools-alignment.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-storage_pools-alignment.ads 2019-05-16 17:44:09.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2005-2017, AdaCore -- +-- Copyright (C) 2005-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -48,17 +48,17 @@ (Alignment : System.Storage_Elements.Storage_Count) is new System.Storage_Pools.Root_Storage_Pool with null record; - function Storage_Size + overriding function Storage_Size (Pool : Unbounded_No_Reclaim_Align_Pool) return System.Storage_Elements.Storage_Count; - procedure Allocate + overriding procedure Allocate (Pool : in out Unbounded_No_Reclaim_Align_Pool; Address : out System.Address; Storage_Size : System.Storage_Elements.Storage_Count; Alignment : System.Storage_Elements.Storage_Count); - procedure Deallocate + overriding procedure Deallocate (Pool : in out Unbounded_No_Reclaim_Align_Pool; Address : System.Address; Storage_Size : System.Storage_Elements.Storage_Count; diff -Nru libgnatcoll-18/src/gnatcoll-storage_pools-headers.adb libgnatcoll-19/src/gnatcoll-storage_pools-headers.adb --- libgnatcoll-18/src/gnatcoll-storage_pools-headers.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-storage_pools-headers.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2015-2017, AdaCore -- +-- Copyright (C) 2015-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -22,6 +22,7 @@ ------------------------------------------------------------------------------ with System.Memory; use System, System.Memory; +with Ada.Unchecked_Conversion; package body GNATCOLL.Storage_Pools.Headers is @@ -36,7 +37,6 @@ type Header is record Extra : Extra_Header; end record; - type Extra_Header_Access is access all Extra_Header; Extra_Bytes : constant Storage_Offset := (Header'Max_Size_In_Storage_Elements @@ -55,7 +55,7 @@ -- alignment of the Element_Type is suitable. function Convert is new Ada.Unchecked_Conversion - (System.Address, Extra_Header_Access); + (System.Address, Header_Access); function Address_Header_Of (Addr : System.Address) return System.Address @@ -112,10 +112,16 @@ package body Typed is function Header_Of - (Element : Element_Access) return access Extra_Header + (Element : Element_Access) return Header_Access is - F : constant Integer := Element.all'Finalization_Size; - -- If the element_type is a controlled type, this constant will + F : Integer; + begin + if Element = null then + return null; + end if; + + F := Element.all'Finalization_Size; + -- If the element_type is a controlled type, this will -- be the number of extra bytes requested by the compiler in -- calls to Allocate and Deallocate (see the memory layout -- description in the specs). @@ -124,17 +130,15 @@ -- the compiler when calling Deallocate, but not when calling -- Header_Of so we need to take them into account when looking -- for the our own header. - - H : constant access Extra_Header := - (if Element = null - then null - else Convert - (Address_Header_Of - (Element.all'Address - - Storage_Offset (F) - - Element_Type'Descriptor_Size))); - begin - return H; + -- + -- Place the Descriptor_Size within the type conversion to + -- prevent a potential ambiguity in address manipulation when + -- System.Aux_Dec is present. + + return Convert + (Address_Header_Of + (Element.all'Address + - Storage_Offset (F - Element_Type'Descriptor_Size))); end Header_Of; end Typed; diff -Nru libgnatcoll-18/src/gnatcoll-storage_pools-headers.ads libgnatcoll-19/src/gnatcoll-storage_pools-headers.ads --- libgnatcoll-18/src/gnatcoll-storage_pools-headers.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-storage_pools-headers.ads 2019-05-16 17:44:09.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2015-2017, AdaCore -- +-- Copyright (C) 2015-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -45,7 +45,6 @@ -- String_Pools.Free (Str); -- reclaim memory pragma Ada_2012; -with Ada.Unchecked_Conversion; with Ada.Unchecked_Deallocation; with System.Storage_Pools; use System.Storage_Pools; with System.Storage_Elements; use System.Storage_Elements; @@ -106,6 +105,7 @@ -- The header to allocate for each element. The pool will make sure -- to pad its size so that the element's data is properly aligned. + type Header_Access is access all Extra_Header; package Header_Pools is type Header_Pool is new Root_Storage_Pool with null record; @@ -141,7 +141,7 @@ -- than as a separate dope vector. function Header_Of - (Element : Element_Access) return access Extra_Header + (Element : Element_Access) return Header_Access with Inline; -- Points to the beginning of the header for Element. -- Returns null if Element is null diff -Nru libgnatcoll-18/src/gnatcoll-string_builders.adb libgnatcoll-19/src/gnatcoll-string_builders.adb --- libgnatcoll-18/src/gnatcoll-string_builders.adb 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-string_builders.adb 2019-05-16 17:44:08.000000000 +0000 @@ -0,0 +1,243 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with Ada.Unchecked_Deallocation; + +package body GNATCOLL.String_Builders is + + Minimal_Heap_Size : constant Natural := 64; + + procedure Free is new Ada.Unchecked_Deallocation + (String, String_Access); + + procedure Allocate (Self : in out String_Builder; Chars : Natural); + + -------------- + -- Allocate -- + -------------- + + procedure Allocate (Self : in out String_Builder; Chars : Natural) + is + Str_Max : Natural := (if Self.Heap_Str = null then Minimal_Heap_Size + else Self.Heap_Str'Length); + begin + + -- Ensure we have room for total length + 1 (for ASCII.NUL) + while Self.Str_Last + Chars + 1 > Str_Max loop + Str_Max := Str_Max * 2; + end loop; + + -- Perform reallocations + if Self.Heap_Str = null or else Str_Max > Self.Heap_Str'Length then + declare + New_Str : constant String_Access := new String (1 .. Str_Max); + begin + if Self.Heap_Str /= null then + -- Copy previous content if necessary + New_Str (1 .. Self.Str_Last + 1) := + Self.Heap_Str (1 .. Self.Str_Last + 1); + Free (Self.Heap_Str); + elsif Self.Str_Last > 0 then + New_Str (1 .. Self.Str_Last + 1) := + Self.Stack_Str (1 .. Self.Str_Last + 1); + end if; + Self.Heap_Str := New_Str; + end; + end if; + end Allocate; + + ------------ + -- Append -- + ------------ + + procedure Append (Self : in out String_Builder; Str : String) is + New_Last : constant Natural := Self.Str_Last + Str'Length; + begin + if Str'Length = 0 then + return; + end if; + + if New_Last > String_Builder_Short_Size then + Allocate (Self, Str'Length); + Self.Heap_Str (Self.Str_Last + 1 .. New_Last) := Str; + Self.Heap_Str (New_Last + 1) := ASCII.NUL; + else + Self.Stack_Str (Self.Str_Last + 1 .. New_Last) := Str; + Self.Stack_Str (New_Last + 1) := ASCII.NUL; + end if; + Self.Str_Last := New_Last; + + end Append; + + procedure Append (Self : in out Static_String_Builder; Str : String) is + New_Last : constant Natural := Self.Str_Last + Str'Length; + begin + if Str'Length = 0 then + return; + end if; + + if New_Last > Self.Size_With_NUL - 1 then + raise Constraint_Error; + end if; + + Self.Str (Self.Str_Last + 1 .. New_Last) := Str; + Self.Str_Last := New_Last; + Self.Str (Self.Str_Last + 1) := ASCII.NUL; + end Append; + + procedure Append (Self : in out String_Builder; Char : Character) is + begin + if Self.Str_Last + 1 > String_Builder_Short_Size then + Allocate (Self, 1); + Self.Str_Last := Self.Str_Last + 1; + Self.Heap_Str (Self.Str_Last) := Char; + Self.Heap_Str (Self.Str_Last + 1) := ASCII.NUL; + else + Self.Str_Last := Self.Str_Last + 1; + Self.Stack_Str (Self.Str_Last) := Char; + Self.Stack_Str (Self.Str_Last + 1) := ASCII.NUL; + end if; + end Append; + + procedure Append (Self : in out Static_String_Builder; Char : Character) is + New_Last : constant Natural := Self.Str_Last + 1; + begin + if New_Last > Self.Size_With_NUL - 1 then + raise Constraint_Error; + end if; + Self.Str_Last := New_Last; + Self.Str (Self.Str_Last) := Char; + Self.Str (Self.Str_Last + 1) := ASCII.NUL; + end Append; + + --------------- + -- As_String -- + --------------- + + function As_String (Self : String_Builder) return String is + begin + if Self.Str_Last > String_Builder_Short_Size then + return Self.Heap_Str.all (1 .. Self.Str_Last); + else + return Self.Stack_Str (1 .. Self.Str_Last); + end if; + end As_String; + + function As_String (Self : Static_String_Builder) return String is + begin + return Self.Str (1 .. Self.Str_Last); + end As_String; + + ---------------- + -- As_CString -- + ---------------- + + function As_CString (Self : String_Builder) return CString is + begin + if Self.Str_Last = 0 then + return Empty_CString; + elsif Self.Str_Last > String_Builder_Short_Size then + return CString (Self.Heap_Str (1)'Address); + else + return CString (Self.Stack_Str (1)'Address); + end if; + end As_CString; + + function As_CString (Self : Static_String_Builder) return CString is + begin + if Self.Str_Last = 0 then + return Empty_CString; + else + return CString (Self.Str (1)'Address); + end if; + end As_CString; + + ---------------- + -- Deallocate -- + ---------------- + procedure Deallocate (Self : in out String_Builder) is + begin + if Self.Heap_Str /= null then + Free (Self.Heap_Str); + Self.Str_Last := 0; + end if; + end Deallocate; + + ------------- + -- Element -- + ------------- + + function Element (Self : String_Builder; N : Positive) return Character is + begin + if N > Self.Str_Last then + raise Constraint_Error; + elsif Self.Str_Last > String_Builder_Short_Size then + return Self.Heap_Str.all (N); + else + return Self.Stack_Str (N); + end if; + end Element; + + function Element + (Self : Static_String_Builder; N : Positive) + return Character + is + begin + if N > Self.Str_Last then + raise Constraint_Error; + else + return Self.Str (N); + end if; + end Element; + + ------------ + -- Length -- + ------------ + + function Length (Self : String_Builder) return Natural is + begin + return Self.Str_Last; + end Length; + + function Length (Self : Static_String_Builder) return Natural is + begin + return Self.Str_Last; + end Length; + + --------- + -- Set -- + --------- + + procedure Set (Self : in out String_Builder; Str : String) is + begin + Self.Str_Last := 0; + Append (Self, Str); + end Set; + + procedure Set (Self : in out Static_String_Builder; Str : String) is + begin + Self.Str_Last := 0; + Append (Self, Str); + end Set; + +end GNATCOLL.String_Builders; diff -Nru libgnatcoll-18/src/gnatcoll-string_builders.ads libgnatcoll-19/src/gnatcoll-string_builders.ads --- libgnatcoll-18/src/gnatcoll-string_builders.ads 1970-01-01 00:00:00.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-string_builders.ads 2019-05-16 17:44:09.000000000 +0000 @@ -0,0 +1,132 @@ +------------------------------------------------------------------------------ +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2019, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with System; + +package GNATCOLL.String_Builders is + + type String_Builder is limited private; + -- String_Builder is an efficient unbounded structure to create String + -- object by aggregation. The structure also maintains a null character at + -- the end of the String allowing export to C without reallocation. + -- Instances of String_Builder should be finalized by calling Deallocate + -- procedure. + + type CString is private; + -- CString can be used as parameter to C functions expecting a + -- "const char *" + + procedure Append (Self : in out String_Builder; Str : String); + -- Append Str to Self + + procedure Append (Self : in out String_Builder; Char : Character); + -- Append Char to Self + + procedure Set (Self : in out String_Builder; Str : String); + -- Reset content of Self to Str + + function Element (Self : String_Builder; N : Positive) return Character + with Inline; + -- Return the Nth character of Self + + function Length (Self : String_Builder) return Natural + with Inline; + -- Return the length of Self (the size does not take into account + -- the trailing ASCII.NUL character maintained by the structure). + + function As_String (Self : String_Builder) return String + with Inline; + -- Return an Ada String (without the trailing ASCII.NUL) + + function As_CString (Self : String_Builder) return CString + with Inline; + -- Return a char* pointing to the beginning of Self content + + procedure Deallocate (Self : in out String_Builder) + with Inline; + -- Free heap memory associated with Self + + type Static_String_Builder (Size_With_NUL : Natural) is limited private; + -- Behave the same way as String_Builder except that the maximum + -- size if known in advance. The structure does not allocate memory + -- on the heap. Size passed as discriminant should be the maximum size + -- of the string plus one character for the trailing NUL char. + + procedure Append (Self : in out Static_String_Builder; Str : String) + with Inline; + -- Append Str to Self + + procedure Append (Self : in out Static_String_Builder; Char : Character) + with Inline; + -- Append Char to Self + + procedure Set (Self : in out Static_String_Builder; Str : String) + with Inline; + -- Reset content of Self to Str + + function Element + (Self : Static_String_Builder; N : Positive) + return Character + with Inline; + -- Return the Nth character of Self + + function Length (Self : Static_String_Builder) return Natural + with Inline; + -- Return the length of Self (the size does not take into account + -- the trailing ASCII.NUL character maintained by the structure). + + function As_String (Self : Static_String_Builder) return String + with Inline; + -- Return an Ada String (without the trailing ASCII.NUL) + + function As_CString (Self : Static_String_Builder) return CString + with Inline; + -- Return a char* pointing to the beginning of Self content +private + + type String_Access is access String; + type CString is new System.Address; + + Empty_String : constant String := "" & ASCII.NUL; + Empty_CString : constant CString := CString (Empty_String (1)'Address); + + type Static_String_Builder (Size_With_NUL : Natural) is limited record + Str : String (1 .. Size_With_NUL); + Str_Last : Natural := 0; + end record; + + String_Builder_Short_Size : constant Natural := 43; + + type String_Builder is limited record + Heap_Str : String_Access := null; + Str_Last : Natural := 0; + Stack_Str : String (1 .. String_Builder_Short_Size + 1); + end record; + -- String_Builder record size is set to use 64 bytes on most systems + -- (size of L1 cache line on most systems). For 43-bytes long or smaller + -- strings no allocation on the heap will be done (in that case Stack_Str + -- is used to store the string). For bigger strings Heap_Str is used. + -- Str_Last is the index either in Stack_Str or Heap_Str of the last + -- character in the string. + +end GNATCOLL.String_Builders; diff -Nru libgnatcoll-18/src/gnatcoll-strings_impl.adb libgnatcoll-19/src/gnatcoll-strings_impl.adb --- libgnatcoll-18/src/gnatcoll-strings_impl.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-strings_impl.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2017, AdaCore -- +-- Copyright (C) 2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -2469,12 +2469,16 @@ ---------------- procedure Capitalize (Self : in out XString) is - S : Char_Array; - L : Natural; + S : Char_Array; + L : Natural; begin Make_Writable (Self); Get_String (Self, S, L); S (1) := To_Upper (S (1)); + for Idx in 2 .. L loop + S (Idx) := To_Lower (S (Idx)); + end loop; + end Capitalize; ----------- diff -Nru libgnatcoll-18/src/gnatcoll-strings_impl.ads libgnatcoll-19/src/gnatcoll-strings_impl.ads --- libgnatcoll-18/src/gnatcoll-strings_impl.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-strings_impl.ads 2019-05-16 17:44:09.000000000 +0000 @@ -637,7 +637,7 @@ function Hash (Self : XString) return Ada.Containers.Hash_Type; -- Return a hash value suitable for the standard containers map. - -- This is not a cryptographica hash. + -- This is not a cryptographic hash. function Hash_Case_Insensitive (Self : XString) return Ada.Containers.Hash_Type; diff -Nru libgnatcoll-18/src/gnatcoll_support.c libgnatcoll-19/src/gnatcoll_support.c --- libgnatcoll-18/src/gnatcoll_support.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll_support.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,22 +1,29 @@ /*---------------------------------------------------------------------------- --- G N A T C O L L -- +-- G N A T C O L L -- -- -- --- Copyright (C) 2008-2017, AdaCore -- +-- Copyright (C) 2008-2018, AdaCore -- -- -- --- This is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. This software is distributed in the hope that it will be useful, -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- -- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY 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 distributed with this software; see file -- --- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- --- of the license. -- -----------------------------------------------------------------------------*/ +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ #include #include +#include #include #ifdef _WIN32 @@ -189,10 +196,8 @@ * Support for atomic operations ************************************************************************/ -#ifdef ATOMIC_INTRINSICS -int gnatcoll_sync_bool_compare_and_swap_access +bool gnatcoll_sync_bool_compare_and_swap_access (void** ptr, void* oldval, void* newval) { return __sync_bool_compare_and_swap(ptr, oldval, newval); } -#endif diff -Nru libgnatcoll-18/src/gnatcoll-templates.ads libgnatcoll-19/src/gnatcoll-templates.ads --- libgnatcoll-18/src/gnatcoll-templates.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-templates.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2008-2017, AdaCore -- +-- Copyright (C) 2008-2018, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -49,11 +49,11 @@ Quoted : Boolean) return String; -- A callback for Substitute below. It is called once for each '%...' -- parameter found in the string. Name doesn't include the delimiter. - -- Quoted indicate whether the parameter was quoted, ie the '%...' was - -- found as part of a quoted subtrings (for instance + -- Quoted indicate whether the parameter was quoted, i.e. the '%...' was + -- found as part of a quoted substring (for instance -- a "quoted %version substring" b -- The reason is that the substituted version could be different in such - -- a case, and the subtituted value might need to protect quote symbols + -- a case, and the substituted value might need to protect quote symbols -- in its replacement string. -- Should raise Invalid_Substitution if Name cannot be substituted diff -Nru libgnatcoll-18/src/gnatcoll-traces.adb libgnatcoll-19/src/gnatcoll-traces.adb --- libgnatcoll-18/src/gnatcoll-traces.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-traces.adb 2019-05-16 17:44:08.000000000 +0000 @@ -489,7 +489,7 @@ Term : GNATCOLL.Terminal.Terminal_Info; Supports_Buffer : Boolean := True; - Buf_Size : size_t := 2**10; + Buf_Size : size_t := 1; -- Line buffering by default begin if Name = "" then @@ -523,8 +523,10 @@ begin Buf_Size := size_t'Value (A (A'First + 12 .. A'Last)); exception - when others => - Buf_Size := 2**10; + when Constraint_Error => + -- Ignore not numeric buffer_size value and Buf_Size + -- remains default. + null; end; elsif Starts_With (A.all, "colors=") then @@ -626,12 +628,15 @@ (Var : String; Quoted : Boolean) return String is pragma Unreferenced (Quoted); - use Ada.Environment_Variables; + -- No way to "use Ada.Environment_Variables;" because of + -- visibility conflict with Traces.Exists and GNAT can't + -- discover it, see R924-001. begin - if Exists (Var) then - return Value (Var); + if Ada.Environment_Variables.Exists (Var) then + return Ada.Environment_Variables.Value (Var); + else + raise Invalid_Substitution; end if; - raise Invalid_Substitution; end Substitute_Cb; N : constant String := Normalize_Pathname @@ -865,6 +870,24 @@ return Handle; end Create_Internal; + ------------ + -- Exists -- + ------------ + + function Exists (Unit_Name : String) return Boolean is + Is_Star : constant Boolean := Starts_With (Unit_Name, "*.") + or else Ends_With (Unit_Name, ".*"); + Handle : Trace_Handle; + Upper_Case : constant String := To_Upper (Unit_Name); + begin + Handle := Find_Handle + ((if Is_Star then Global.Wildcard_Handles_List + else Global.Handles_List), + Upper_Case); + + return Handle /= null; + end Exists; + -------------------- -- Cache_Settings -- -------------------- @@ -943,6 +966,13 @@ then -- If active, store it in the list of active decorators if Active then + for A in 1 .. Global.Active_Last loop + if Global.Active_Decorators (A) = Dec then + -- Already in the list + return; + end if; + end loop; + -- ??? Should check if we have too many decorators Global.Active_Last := Global.Active_Last + 1; Global.Active_Decorators (Global.Active_Last) := Dec; @@ -1736,10 +1766,10 @@ & "([^\s=:>+-]+)" & S -- 1 = name & "(?:=" & S & "(yes|no))?" & S -- 2 = active? & "(:[^\s>]+)?" & S -- 3 = options - & "(?:>" & S & "(\S+))?" & S -- 4 = stream + & "(?:>>?" & S & "(\S+))?" & S -- 4 = stream & "|" - & "(>\S+)?" & S -- 5 = default stream + & "(>>?\S+)?" & S -- 5 = default stream & "|" & "(\+)" & S -- 6 = "+" diff -Nru libgnatcoll-18/src/gnatcoll-traces.ads libgnatcoll-19/src/gnatcoll-traces.ads --- libgnatcoll-18/src/gnatcoll-traces.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-traces.ads 2019-05-16 17:44:09.000000000 +0000 @@ -113,11 +113,14 @@ -- supported for standard output or standard error, and syslog does -- not support colors). -- --- * "buffer_size": the size of the buffer. The logs are --- synchronized with the disk when this buffer is full. --- Setting this to 0 means that synchronization appears after --- every output line, which is slow but might help when --- debugging a crashing application. +-- * "buffer_size": the size of the buffer. The logs are synchronized +-- with the disk when this buffer is full. +-- Setting this to 0 means that synchronization appears after every +-- write operation into log file. Value 1 means synchronization after +-- every output line, which is the same as buffer_size=0 in the +-- current implementation. Bigger buffer_size value improves the trace +-- performance but can result in loss of information on application +-- crash. The default buffer_size value is 1. -- -- * "colors": whether to allow colors on this stream. -- This combines with the DEBUG.COLORS settings. @@ -222,7 +225,7 @@ -- "DEBUG.SPLIT_LINES" (default: true) -- Whether long messages should be split at each ASCII.LF character. When -- we do this, the trace handle name and decorators are replicated at the --- beginning of each followup line. This results in a slow down. +-- beginning of each follow-up line. This results in a slow down. -- Example -- ======= @@ -390,6 +393,11 @@ -- by the compiler, so that you can have logs till the last minute. -- See also the "DEBUG.FINALIZE_TRACES" configuration. + function Exists (Unit_Name : String) return Boolean; + -- Return True if the handle has been created in some other part of the + -- code. If Unit_Name starts and/or finishes by '*' then this function + -- will check if a corresponding wildcard handle exists. + function Unit_Name (Handle : not null access Trace_Handle_Record'Class) return String; -- Return the unit name (upper-cased) for this handle. This can be used for diff -Nru libgnatcoll-18/src/gnatcoll-utils.adb libgnatcoll-19/src/gnatcoll-utils.adb --- libgnatcoll-18/src/gnatcoll-utils.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-utils.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2008-2017, AdaCore -- +-- Copyright (C) 2008-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -24,17 +24,18 @@ with Ada.Calendar.Formatting; with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; +with Ada.Environment_Variables; with Ada.Strings.Fixed; use Ada.Strings; with Ada.Strings.Maps; use Ada.Strings.Maps; with GNAT.Calendar.Time_IO; with GNAT.Case_Util; with GNAT.OS_Lib; with GNAT.Strings; use GNAT.Strings; +with GNATCOLL.String_Builders; +with System; package body GNATCOLL.Utils is - OpenVMS_Host : Boolean := False; - function Count_For_Split (Str : String; On : Character; @@ -358,7 +359,7 @@ return False; end if; - -- Do the loop in reverse, since it likely that Suffix starts with '.' + -- Do the loop in reverse, since it's likely that Suffix starts with '.' -- In the GPS case, it is also often the case that suffix starts with -- '.ad' for Ada extensions for J in reverse Suffix'Range loop @@ -391,103 +392,126 @@ function Is_Directory_Separator (C : Character) return Boolean is begin -- In addition to the default directory_separator allow the '/' to - -- act as separator since this is allowed in MS-DOS, Windows 95/NT, - -- and OS2 ports. On VMS, the situation is more complicated because - -- there are two characters to check for. - - return C = GNAT.OS_Lib.Directory_Separator - or else C = '/' - or else (OpenVMS_Host and then (C = ']' or else C = ':')); + -- act as separator since this a valid path separator on Windows + -- systems. + return C = GNAT.OS_Lib.Directory_Separator or else C = '/'; end Is_Directory_Separator; - ---------------------- - -- Set_OpenVMS_Host -- - ---------------------- - - procedure Set_OpenVMS_Host (Setting : Boolean := True) is - begin - OpenVMS_Host := Setting; - end Set_OpenVMS_Host; - ------------------------- -- Executable_Location -- ------------------------- function Executable_Location return String is - Exec_Name : constant String := Ada.Command_Line.Command_Name; - - function Get_Install_Dir (S : String) return String; - -- S is the executable name preceeded by the absolute or relative - -- path, e.g. "c:\usr\bin\gcc.exe" or "..\bin\gcc". Returns the absolute - -- or relative directory where "bin" lies (in the example "C:\usr" - -- or ".."). If the executable is not a "bin" directory, return "". - - --------------------- - -- Get_Install_Dir -- - --------------------- - - function Get_Install_Dir (S : String) return String is - Exec : String := GNAT.OS_Lib.Normalize_Pathname - (S, Resolve_Links => True); - Path_Last : Integer := 0; - - begin - for J in reverse Exec'Range loop - if Is_Directory_Separator (Exec (J)) then - Path_Last := J - 1; - exit; - end if; - end loop; - - if Path_Last >= Exec'First + 2 then - GNAT.Case_Util.To_Lower (Exec (Path_Last - 2 .. Path_Last)); - end if; - - -- If we are not in a bin/ directory - - if Path_Last < Exec'First + 2 - or else Exec (Path_Last - 2 .. Path_Last) /= "bin" - or else (Path_Last - 3 >= Exec'First - and then not Is_Directory_Separator (Exec (Path_Last - 3))) - then - return Exec (Exec'First .. Path_Last) - & GNAT.OS_Lib.Directory_Separator; - - else - -- Skip bin/, but keep the last directory separator - return Exec (Exec'First .. Path_Last - 3); - end if; - end Get_Install_Dir; - - -- Beginning of Executable_Location - + Exec_Path : constant String := Executable_Path; + Path_Last : Integer := -1; begin - -- First determine if a path prefix was placed in front of the - -- executable name. - - for J in reverse Exec_Name'Range loop - if Is_Directory_Separator (Exec_Name (J)) then - return Get_Install_Dir (Exec_Name); + -- Find the directory containing the executable + for J in reverse Exec_Path'Range loop + if Is_Directory_Separator (Exec_Path (J)) then + Path_Last := J - 1; + exit; end if; end loop; - -- If you are here, the user has typed the executable name with no - -- directory prefix. - -- There is a potential issue here (see K112-046) where GNAT.OS_Lib - -- will in fact return any non-executable file found in the PATH, - -- whereas shells only consider executable files. As a result, the - -- user might end up with a wrong directory, not matching the one - -- found by the shell. + -- Handle special case for which we did not find any directory + -- (can occur for some platforms if the path to the executable + -- can not be found). + if Path_Last = -1 then + return ""; + end if; - declare - Ex : String_Access := GNAT.OS_Lib.Locate_Exec_On_Path (Exec_Name); - Dir : constant String := Get_Install_Dir (Ex.all); - begin - Free (Ex); - return Dir; - end; + -- Check if we can strip bin directory. As some systems are + -- case insensitive perform a case insensitive comparison. + if Path_Last >= Exec_Path'First + 3 then + declare + Dir_Element : String := Exec_Path (Path_Last - 2 .. Path_Last); + begin + GNAT.Case_Util.To_Lower (Dir_Element); + if Dir_Element = "bin" and then + Is_Directory_Separator (Exec_Path (Path_Last - 3)) + then + return Exec_Path (Exec_Path'First .. Path_Last - 3); + else + return Exec_Path (Exec_Path'First .. Path_Last + 1); + end if; + end; + else + return Exec_Path (Exec_Path'First .. Path_Last + 1); + end if; end Executable_Location; + --------------------- + -- Executable_Path -- + --------------------- + + function Executable_Path return String is + function Internal + (Str : System.Address; Length : Integer) return Integer; + pragma Import (C, Internal, "c_executable_path"); + + -- Allocate a buffer of size 32K (maximum path on windows platform when + -- prefixing the path with \?. This should also cover Linux and MacOS. + Result : String (1 .. 32768); + + -- Length of returned path by system low level functions + Allocated : Integer; + begin + Allocated := Internal (Result'Address, Result'Length); + + if Allocated = 0 or else Allocated >= Result'Length then + -- If we cannot get the executable name through system API, fallback + -- on argv[0] which is less accurate. + declare + Command_Name : constant String := Ada.Command_Line.Command_Name; + begin + + -- Check if the argument contains some directory information. + for Idx in Command_Name'Range loop + if Is_Directory_Separator (Command_Name (Idx)) then + -- We have some path information. Note that in case the + -- path is relative and the application changed the current + -- directory then the returned path will be incorrect. + return GNAT.OS_Lib.Normalize_Pathname + (Command_Name, Resolve_Links => True); + end if; + end loop; + + -- If you are here, the user has typed the executable name with no + -- directory prefix. + -- There is a potential issue here (see K112-046) where + -- GNAT.OS_Lib will in fact return any non-executable file found + -- in the PATH, whereas shells only consider executable files. + -- As a result, the user might end up with a wrong path, not + -- matching the one found by the shell. + -- PATH variable might also have been modified by application or + -- not passed with the same value to the executable itself. + declare + Executable_Path : String_Access := + GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name); + begin + if Executable_Path /= null then + declare + Result : constant String := Executable_Path.all; + begin + Free (Executable_Path); + return GNAT.OS_Lib.Normalize_Pathname + (Result, Resolve_Links => True); + end; + else + -- In case PATH was modified on launching the app or by the + -- app itself we might end in a case in which we cannot get + -- the original executable path. In that case return the + -- command name. + return Command_Name; + end if; + end; + end; + else + return GNAT.OS_Lib.Normalize_Pathname + (Result (Result'First .. Allocated), Resolve_Links => True); + end if; + end Executable_Path; + ----------------- -- Skip_Blanks -- ----------------- @@ -716,7 +740,7 @@ end if; end if; - -- Special case: UTC time zone speficied as 'Z' + -- Special case: UTC time zone specified as 'Z' if Str'Length > 1 and then Str (Last) = 'Z' then Last := Last - 1; @@ -838,8 +862,9 @@ -------------- function Line_End (Str : String; P : Natural) return Natural is + Index : constant Natural := Natural'Max (Str'First, P); begin - for J in P .. Str'Last loop + for J in Index .. Str'Last loop if Str (J) = ASCII.LF or else Str (J) = ASCII.CR then return J - 1; end if; @@ -853,8 +878,9 @@ --------------- function Next_Line (Str : String; P : Natural) return Natural is + Index : constant Natural := Natural'Max (Str'First, P); begin - for J in P .. Str'Last - 1 loop + for J in Index .. Str'Last - 1 loop if Str (J) = ASCII.LF then return J + 1; end if; @@ -1026,4 +1052,103 @@ end loop; end Skip_To_Column; + --------------- + -- Join_Path -- + --------------- + + function Join_Path + (Path : String; Path1, Path2, Path3, Path4 : String := "") + return String + is + use String_Builders; + Sep : constant Character := GNAT.OS_Lib.Directory_Separator; + Result : Static_String_Builder + (Path'Length + Path1'Length + Path2'Length + + Path3'Length + Path4'Length + 4 + 1); + -- Maximum length for the returned path is the sum of paths + -- passed as argument, 4 directory separators and 1 character + -- to let room for a null character. + + procedure Append_Path_Element (Path_Elmt : String); + + -------------------------- + -- Append_Path_Element -- + -------------------------- + + procedure Append_Path_Element (Path_Elmt : String) is + begin + if Path_Elmt /= "" then + if GNAT.OS_Lib.Is_Absolute_Path (Path_Elmt) then + -- If the element to add is an absolute path then reset the + -- result. + Set (Result, Path_Elmt); + else + -- If not at the beginning of the resulting path ensure that a + -- directory separator is inserted. + if Length (Result) > 0 and then + not Is_Directory_Separator + (Element (Result, Length (Result))) + then + Append (Result, Sep); + end if; + + Append (Result, Path_Elmt); + end if; + end if; + end Append_Path_Element; + + begin + Append_Path_Element (Path); + Append_Path_Element (Path1); + Append_Path_Element (Path2); + Append_Path_Element (Path3); + Append_Path_Element (Path4); + return As_String (Result); + end Join_Path; + + --------------------- + -- Add_Search_Path -- + --------------------- + + procedure Add_Search_Path (Variable : String; Path : String) + is + use String_Builders; + package Env renames Ada.Environment_Variables; + Original_Value : constant String := Env.Value (Variable, ""); + Result : Static_String_Builder + (Original_Value'Length + Path'Length + 1 + 1); + Start : Integer := Original_Value'First; + begin + -- Do nothing if path is empty + if Path = "" then + return; + end if; + + -- Add the new path + Set (Result, Path); + + -- Scan original value and remove any duplicate of the new path + for Idx in Original_Value'Range loop + if Original_Value (Idx) = GNAT.OS_Lib.Path_Separator then + if Original_Value (Start .. Idx - 1) /= Path then + Append (Result, GNAT.OS_Lib.Path_Separator); + Append (Result, Original_Value (Start .. Idx - 1)); + Start := Idx + 1; + end if; + if Idx = Original_Value'Last then + Append (Result, GNAT.OS_Lib.Path_Separator); + end if; + elsif Idx = Original_Value'Last and then + Start <= Original_Value'Last + then + if Original_Value (Start .. Idx) /= Path then + Append (Result, GNAT.OS_Lib.Path_Separator); + Append (Result, Original_Value (Start .. Idx)); + end if; + end if; + end loop; + + Env.Set (Variable, As_String (Result)); + end Add_Search_Path; + end GNATCOLL.Utils; diff -Nru libgnatcoll-18/src/gnatcoll-utils.ads libgnatcoll-19/src/gnatcoll-utils.ads --- libgnatcoll-18/src/gnatcoll-utils.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-utils.ads 2019-05-16 17:44:09.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2008-2018, AdaCore -- +-- Copyright (C) 2008-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -27,6 +27,7 @@ pragma Ada_2012; with Ada.Calendar.Time_Zones; use Ada.Calendar; +with Ada.Characters.Handling; with Ada.Strings.Unbounded; with GNAT.Calendar; with GNAT.Expect; @@ -34,13 +35,18 @@ package GNATCOLL.Utils is - type Cst_String_Access is access constant String; + ------------- + -- Strings -- + ------------- + + -- Some simple-minded string manipulation routines. + -- See also GNATCOLL.Strings providing alternative more efficient + -- implementation - No_Time : Ada.Calendar.Time renames GNAT.Calendar.No_Time; + type Cst_String_Access is access constant String; procedure Free (List : in out GNAT.Strings.String_List); -- Free the memory used by List. - -- ??? This should be moved to GNAT.Strings itself in fact function Equal (S1, S2 : String; Case_Sensitive : Boolean) return Boolean; function Case_Insensitive_Equal (S1, S2 : String) return Boolean; @@ -52,7 +58,7 @@ Min_Width : Integer; Force_Sign : Boolean := False; Padding : Character := '0') return String; - -- Return Value as a string, using at least Width digits (padded with + -- Returns Value as a string, using at least Width digits (padded with -- leading characters Padding if necessary); negative values will always -- have a leading minus sign; positive values will have a leading plus sign -- if Force_Sign is True. @@ -64,27 +70,27 @@ Pattern : String; Replacement : String) with Pre => Pattern /= ""; - -- Return S, with all occurrences of Pattern replaced with Replacement + -- Returns S, with all occurrences of Pattern replaced with Replacement function Replace (S : String; Pattern : String; Replacement : String) return String with Pre => Pattern /= ""; - -- Return S, with all occurrences of Pattern replaced with Replacement + -- Returns S, with all occurrences of Pattern replaced with Replacement procedure Split (Str : String; On : String; For_Each : access function (Item : String) return Boolean); - -- Split the string on the given delimiter "On" and call function For_Each - -- for all found substrings not including delimiter. If function For_Each - -- returns False the string processing stops. + -- Splits the string on the given delimiter "On" and calls the function + -- For_Each for every found substring not including the delimiter. + -- If For_Each returns False the string processing stops. function Split (Str : String; On : Character; Omit_Empty_Lines : Boolean := True) return GNAT.Strings.String_List_Access; - -- Split the string on the given character. + -- Splits the string on the given character. -- The result depends on the value of Omit_Empty_Lines. For instance, the -- string "a" & ASCII.LF & ASCII.LF & "b" will be split as: -- ["a", "b"] if Omit_Empty_Lines is true @@ -92,8 +98,6 @@ -- -- Result must be freed by caller. -- See also Split below - -- - -- For a more efficient version, see GNATCOLL.Strings type Unbounded_String_Array is array (Natural range <>) of Ada.Strings.Unbounded.Unbounded_String; @@ -106,11 +110,10 @@ Omit_Empty_Lines : Boolean := True) return Unbounded_String_Array; -- Same as Split above, returning an Unbounded_String_Array that does not -- need to be freed. - -- For a more efficient version, see GNATCOLL.Strings function Capitalize (Name : String) return String; - -- Capitalize a string, ie put in upper case the first character and all - -- characters following '_' + -- Capitalizes a string, i.e. puts in upper case the first character and + -- any character preceded by '_' function Is_Whitespace (Char : Character) return Boolean; -- Returns True if Char is a space, new line, or tab; otherwise returns @@ -118,11 +121,9 @@ function Starts_With (Str : String; Prefix : String) return Boolean; -- Returns True if Str starts with Prefix - -- See also GNATCOLL.Strings. function Ends_With (Str : String; Suffix : String) return Boolean; -- Returns True if Str ends with Suffix - -- See also GNATCOLL.Strings. procedure Skip_Blanks (Str : String; Index : in out Natural); procedure Skip_Blanks_Backward (Str : String; Index : in out Natural); @@ -133,36 +134,32 @@ -- before Str'First if no non-whitespace was found. function Find_Char (Str : String; Char : Character) return Natural; - -- Return the first occurrence of Char after Str'First (use substrings for - -- later occurrences). - -- See also GNATCOLL.Strings.Find + -- Returns the first occurrence of Char after Str'First (use substrings for + -- later occurrences). Returns Str'Last + 1 if there is no match function Join (Str : String; List : GNAT.Strings.String_List) return String; - -- Return a string that is the concatenation of the list elements, + -- Returns a string that is the concatenation of the list elements, -- separated by Str: (List(1) & Str & List(2) & Str & ...) -- null elements in list are skipped - -- See also GNATCOLL.Strings.Join function EOL (Str : String) return Natural; pragma Inline (EOL); - -- Return the first end-of-line after Str'First (use substrings for later - -- lines). The result is either Str'Last+1 or pointing to the first - -- ASCII.LF found. + -- Returns the first ASCII.LF character after Str'First (use substrings for + -- subsequent lines). The result is either Str'Last+1 or points to the + -- first ASCII.LF found. function Line_Start (Str : String; P : Natural) return Natural; - -- Return the start of the line pointed by P - -- See also GNATCOLL.Strings.Head + -- Returns the start of the line pointed by P function Line_End (Str : String; P : Natural) return Natural; - -- Return the end of the line pointed by P - -- See also GNATCOLL.Strings.Tail + -- Returns the end of the line pointed by P procedure Skip_Lines (Str : String; Lines : Integer; Index : in out Natural; Lines_Skipped : out Natural); - -- Skip Lines forward or backward. Index is set to the beginning of a line. + -- Skips lines forward or backward. Sets Index to the beginning of a line. -- Lines_Skipped is the number of lines that have actually been skipped. -- Use with Skip_To_Column to go to a specific position in a buffer. @@ -171,10 +168,10 @@ Columns : Integer := 0; Index : in out Integer; Tab_Width : Integer := 8); - -- Assuming Index points to the begining of a line (as is the case after - -- Skip_Lines for instance), jump to the specific column on that line. - -- This procedure handles tabulations (ie Columns are columns visible to - -- the user, after tab expansion). + -- Assuming Index points to the beginning of a line (as is the case after + -- Skip_Lines for instance), jumps to the specific column on that line. + -- This procedure handles tabulations (i.e. Columns are columns visible to + -- the user following the tab expansion). function Forward_UTF8_Char (Str : String; @@ -182,16 +179,16 @@ -- Moves Index one character forward, taking into account UTF8 encoding. function Next_Line (Str : String; P : Natural) return Natural; - -- Return the start of the next line or Buffer'Last if the end of the - -- buffer is reached. + -- Returns the start of the next line or Str'Last if the end of Str + -- is reached without finding next line. function Previous_Line (Str : String; P : Natural) return Natural; - -- Return the start of the previous line or Buffer'First if P already - -- points to the first line of Buffer. + -- Returns the start of the previous line or Str'First if P already + -- points to the first line of Str. function Is_Blank_Line (Str : String; Index : Natural := 0) return Boolean; - -- Return True if the line pointed by Index only contains blank characters + -- Returns True if the line pointed by Index only contains blank characters -- (' ', HT, LF, CR). By default, if Index is 0, then the line considered -- is the first line of the buffer. @@ -199,19 +196,44 @@ (Str : String; Index : in out Natural; Substring : String); - -- Skip every character until an occurence of Substring is found. - -- Index is set to the first character of the occurence. + -- Skips every character until an occurrence of Substring is found. + -- Index is set to the first character of the occurrence. function Strip_Character (Text : String; C : Character) return String; - -- Return a version of Text after stripping all C's from the string + -- Returns a version of Text after stripping all C's from the string function Strip_CR (Text : String) return String; pragma Inline (Strip_CR); - -- Return a version of Text after stripping all the CR from the string. + -- Returns a version of Text after stripping all ASCII.CR from the string. -- This function is used on Windows or when the Strip_CR preference is - -- enabled (for systems that share dos files). + -- enabled (for systems that share DOS files). -- CR/LF sequences are replaced by LF chars. + function Predicate + (Text : String; + Predicate : access function (Item : Character) return Boolean) + return Boolean + is (for all C of Text => Predicate (C)); + -- Whether all characters in Text match Predicate. + -- This can be used with the various utilities in Ada.Characters.Handling, + -- for instance to check whether a string is made up of only lower case + -- characters. + + function Is_Alphanumeric (Text : String) return Boolean + is (Predicate (Text, Ada.Characters.Handling.Is_Alphanumeric'Access)); + function Is_Lower (Text : String) return Boolean + is (Predicate (Text, Ada.Characters.Handling.Is_Lower'Access)); + function Is_Upper (Text : String) return Boolean + is (Predicate (Text, Ada.Characters.Handling.Is_Upper'Access)); + + function Is_Identifier (C : Character) return Boolean + is (C = '_' or else Ada.Characters.Handling.Is_Alphanumeric (C)); + function Is_Identifier (Text : String) return Boolean + is (Predicate (Text, Is_Identifier'Access)); + -- Whether C is a valid character for an identifier (in most programming + -- languages). It doesn't check whether the identifier starts with an + -- underscore for instance, just whether the characters would be valid. + ------------ -- Expect -- ------------ @@ -226,23 +248,42 @@ ------------------ function Executable_Location return String; - -- Return the name of the parent directory where the executable is stored - -- (so if you are running "prefix"/bin/gps, you would get "prefix"). - -- A special case is done for "bin" directories, which are skipped. - -- The returned directory always ends up with a directory separator. + -- Returns the name of the parent directory where the executable is stored + -- (so if you are running "prefix/my_exe", you would get "prefix/"). + -- A special case is done for "bin" directories, which are consumed + -- (so if you are running "prefix/bin/my_exe", you would get "prefix/"). + -- The returned directory always ends with a directory separator. + + function Executable_Path return String; + -- Returns absolute path to the current executable. + -- + -- On Linux, Windows and MacOS the procedure is safe and will return always + -- the right executable. For other platforms the function might return + -- an incorrect value if environment is modified (executable parameters, + -- current directory and/or PATH variable). function Is_Directory_Separator (C : Character) return Boolean; + pragma Inline (Is_Directory_Separator); -- Returns True if C is a directory separator - procedure Set_OpenVMS_Host (Setting : Boolean := True); - -- Set whether the host is an OpenVMS host + function Join_Path + (Path : String; Path1, Path2, Path3, Path4 : String := "") return String; + -- Join one or more path into a single one. Note that if one argument is an + -- absolute path then previous arguments will be ignored. + + procedure Add_Search_Path (Variable : String; Path : String); + -- Prepend a path to an environment variable containing a list of paths. + -- If Path is already in the search list, subsequent occurences will be + -- removed and thus limit final path value size. ----------- -- Dates -- ----------- + No_Time : Ada.Calendar.Time renames GNAT.Calendar.No_Time; + function Time_Value (Str : String) return Ada.Calendar.Time; - -- Check the validity of Str as a string representing a date + -- Checks the validity of Str as a string representing a date -- using the same formats as in GNAT.Calendar.Time_IO.Value. In addition, -- it also supports timezones (as output for instance by PostgreSQL) -- 1970-01-01 12:00:00+01 @@ -253,10 +294,17 @@ -- The input date is assumed to be in UTC unless a timezone is specified -- as hours with a final "[+-]\d\d", or as hours and minutes with -- "[+-]\d\d\d\d" or "[+-]\d\d:\d\d" + -- + -- The output date is always returned for the UTC time zone. + -- So if you are in GMT+12 and you parse "2017-01-01T11:00:00", the + -- result date will be: year=2016, month=12, day=31, time=23:00:00. + -- If you want to spit the resulting time to extract the components, + -- you should use: + -- Ada.Calendar.Formatting.Split (.., Time_Zone => 0); function Truncate (Date : Time; Time_Zone : Time_Zones.Time_Offset := 0) return Time; - -- Remove time part from the date in specified timezone. + -- Removes time part from the date in specified timezone. -- For example, if we want to truncate "2015 May 10 05:00 GMT+6" time at -- UTC timezone we are going to get "2015 May 9, 00:00 UTC" because -- "2015 May 10 05:00 GMT+6" equal to "2015 May 9 23:00 UTC". diff -Nru libgnatcoll-18/src/gnatcoll-vfs.adb libgnatcoll-19/src/gnatcoll-vfs.adb --- libgnatcoll-18/src/gnatcoll-vfs.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-vfs.adb 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2003-2017, AdaCore -- +-- Copyright (C) 2003-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -109,7 +109,7 @@ -- "=" -- --------- - function "=" (File1, File2 : Virtual_File) return Boolean is + overriding function "=" (File1, File2 : Virtual_File) return Boolean is begin -- Test for the same pointer to actual value (or both null) if File1.Value = File2.Value then @@ -140,6 +140,23 @@ end "="; --------- + -- "=" -- + --------- + + function "=" (Left : Writable_File; Right : Writable_File) return Boolean is + use type GNAT.OS_Lib.File_Descriptor; + + begin + -- Compare all components except Error for backward compatibility. + + return Left.File = Right.File + and then Left.Tmp_File = Right.Tmp_File + and then Left.FD = Right.FD + and then Left.Append = Right.Append + and then Left.Success = Right.Success; + end "="; + + --------- -- "<" -- --------- @@ -224,7 +241,17 @@ return +Full_Filename; end if; - return GNATCOLL.Path.Normalize (FS, +Full_Filename); + if GNATCOLL.Path.Is_Absolute_Path (FS, +Full_Filename) then + return GNATCOLL.Path.Normalize (FS, +Full_Filename); + else + declare + Full_Path : constant Virtual_File := + Get_Current_Dir (Host => Host) / Full_Filename; + begin + return GNATCOLL.Path.Normalize (FS, + +Full_Path.Full_Name); + end; + end if; end Internal_Get_Path; begin @@ -323,6 +350,16 @@ From_Unix (Dir.Value.Get_FS, +Base_Name))); end Create_From_Dir; + ------------------ + -- Error_String -- + ------------------ + + function Error_String + (Self : Writable_File) return Ada.Strings.Unbounded.Unbounded_String is + begin + return Self.Error; + end Error_String; + -------------------- -- Locate_On_Path -- -------------------- @@ -1192,17 +1229,21 @@ W.Tmp_File := Create (File.Full_Name.all & "~", Host => File.Get_Host); - W.Tmp_File.Value.Open_Write (Append => False, FD => W.FD); + W.Tmp_File.Value.Open_Write + (Append => False, FD => W.FD, Error => W.Error); else W.Tmp_File := No_File; -- append-mode, and the file already exists. - File.Value.Open_Write (Append => True, FD => W.FD); + File.Value.Open_Write + (Append => True, FD => W.FD, Error => W.Error); end if; if W.FD = GNAT.OS_Lib.Invalid_FD then - return Invalid_File; + return X : Writable_File := Invalid_File do + X.Error := W.Error; + end return; else return W; end if; @@ -1812,7 +1853,7 @@ -- Finalize -- -------------- - procedure Finalize (File : in out Virtual_File) is + overriding procedure Finalize (File : in out Virtual_File) is Value : GNATCOLL.IO.File_Access := File.Value; begin File.Value := null; -- Make Finalize idempotent @@ -1825,7 +1866,7 @@ -- Adjust -- ------------ - procedure Adjust (File : in out Virtual_File) is + overriding procedure Adjust (File : in out Virtual_File) is begin if File.Value /= null then Ref (File.Value); diff -Nru libgnatcoll-18/src/gnatcoll-vfs.ads libgnatcoll-19/src/gnatcoll-vfs.ads --- libgnatcoll-18/src/gnatcoll-vfs.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/gnatcoll-vfs.ads 2019-05-16 17:44:08.000000000 +0000 @@ -1,7 +1,7 @@ ------------------------------------------------------------------------------ -- G N A T C O L L -- -- -- --- Copyright (C) 2003-2018, AdaCore -- +-- Copyright (C) 2003-2019, AdaCore -- -- -- -- This library is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- @@ -48,8 +48,9 @@ with Ada.Calendar; with Ada.Containers; -with Ada.Unchecked_Deallocation; with Ada.Finalization; +with Ada.Strings.Unbounded; +with Ada.Unchecked_Deallocation; with Interfaces.C.Strings; use Interfaces.C.Strings; @@ -147,7 +148,8 @@ -- The latter can be found, for source files, through the functions in -- projects-registry.ads. -- If Normalize is set, then the VFS is created using the normalized - -- Full_Filename. + -- Full_Filename. In that case note that the path passed is transformed + -- into an absolute path. function Create_From_Dir (Dir : Virtual_File; @@ -230,6 +232,8 @@ -- are not resolved there by default, unless you specify Resolve_Links to -- True. -- The returned value can be used to recreate a Virtual_File instance. + -- If file names are case insensitive, the normalized name will always + -- be all lower cases. function Full_Name (File : Virtual_File; @@ -241,6 +245,7 @@ -- Return a Hash_Type computed from the full name of the given VFS. -- Could be used to instantiate an Ada 2005 container that uses a VFS as -- key and requires a hash function. + -- See File_Sets below. function File_Extension (File : Virtual_File; @@ -307,7 +312,7 @@ (File : Virtual_File; Host : String := Local_Host) return GNAT.Strings.String_Access; -- Convert the File to a String Access that can be used as argument for - -- spawning a process on "Host". The returned value needs to be freeed by + -- spawning a process on "Host". The returned value needs to be freed by -- the caller. ------------------------ @@ -328,7 +333,7 @@ function Size (File : Virtual_File) return Long_Integer; -- The size of the file - function "=" (File1, File2 : Virtual_File) return Boolean; + overriding function "=" (File1, File2 : Virtual_File) return Boolean; -- Overloading of the standard operator function "<" (File1, File2 : Virtual_File) return Boolean; @@ -510,7 +515,8 @@ -- those entries, according to filter. The list of files returned -- includes directories in systems providing a hierarchical directory -- structure, including . (the current directory) and .. (the parent - -- directory) in systems providing these entries. + -- directory) in systems providing these entries. Note that entries + -- are not sorted. -- The result must be freed by the caller. function Read_Dir_Recursive @@ -519,7 +525,8 @@ Filter : Read_Dir_Filter := All_Files) return File_Array_Access; -- Reads all entries from the directory, recursively, and returns all -- files with the given extension (if specified) that match the filter. - -- The entries "." and ".." are never returned. + -- The entries "." and ".." are never returned. Note that entries + -- are not sorted. -- The result must be freed by the caller. procedure Remove_Dir @@ -561,12 +568,15 @@ Invalid_File : constant Writable_File; -- Used when a file couldn't be open + function "=" (Left : Writable_File; Right : Writable_File) return Boolean; + -- Return True when points to the same file. + function Write_File (File : Virtual_File; Append : Boolean := False) return Writable_File; - -- Open File for writing. The returned handler can be used for writting. + -- Open File for writing. The returned handler can be used for writing. -- You must close it, otherwise the file will not actually be written in - -- some cases. If Append is True then writting will be done at the end of + -- some cases. If Append is True then writing will be done at the end of -- the file if the file exists otherwise the file is created. -- Return Invalid_File is the file couldn't be open for writing -- @@ -575,6 +585,10 @@ -- that the original file (if there was one) is not destroyed if for some -- reason the write fails. + function Error_String + (Self : Writable_File) return Ada.Strings.Unbounded.Unbounded_String; + -- Return error message for last operation on file. + procedure Write (File : in out Writable_File; Str : String); @@ -613,8 +627,8 @@ end record; pragma Finalize_Storage_Only (Virtual_File); - procedure Finalize (File : in out Virtual_File); - procedure Adjust (File : in out Virtual_File); + overriding procedure Finalize (File : in out Virtual_File); + overriding procedure Adjust (File : in out Virtual_File); type Writable_File is record File : Virtual_File; @@ -622,6 +636,7 @@ FD : GNAT.OS_Lib.File_Descriptor := GNAT.OS_Lib.Invalid_FD; Append : Boolean; Success : Boolean; + Error : Ada.Strings.Unbounded.Unbounded_String; end record; Invalid_File : constant Writable_File := @@ -629,7 +644,8 @@ Tmp_File => (Ada.Finalization.Controlled with Value => null), FD => GNAT.OS_Lib.Invalid_FD, Append => False, - Success => False); + Success => False, + Error => <>); type Virtual_Dir is record File : Virtual_File; diff -Nru libgnatcoll-18/src/link_max.c libgnatcoll-19/src/link_max.c --- libgnatcoll-18/src/link_max.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/link_max.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,22 +1,25 @@ -/********************************************************************* - * G P S * - * * - * Copyright (C) 2007 * - * AdaCore * - * * - * GPS 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., 59 Temple * - * Place - Suite 330, Boston, MA 02111-1307, USA. * - *********************************************************************/ +/*---------------------------------------------------------------------------- +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2007-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ /* Dummy version of __gnat_link_max (needed by mlib-utl.adb) */ diff -Nru libgnatcoll-18/src/objlist_file.c libgnatcoll-19/src/objlist_file.c --- libgnatcoll-18/src/objlist_file.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/objlist_file.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,22 +1,25 @@ -/********************************************************************* - * G P S * - * * - * Copyright (C) 2007 * - * AdaCore * - * * - * GPS 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., 59 Temple * - * Place - Suite 330, Boston, MA 02111-1307, USA. * - *********************************************************************/ +/*---------------------------------------------------------------------------- +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2007-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ /* Dummy versions of __gnat_objlist_file_supported, __gnat_object_file_option and diff -Nru libgnatcoll-18/src/run_path_option.c libgnatcoll-19/src/run_path_option.c --- libgnatcoll-18/src/run_path_option.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/run_path_option.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,23 +1,25 @@ -/********************************************************************* - * G P S * - * * - * Copyright (C) 2002-2004 * - * ACT-Europe * - * * - * GPS 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., 59 Temple * - * Place - Suite 330, Boston, MA 02111-1307, USA. * - *********************************************************************/ - +/*---------------------------------------------------------------------------- +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2002-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ /* Dummy version of run_path_option, needed by mlib.adb */ diff -Nru libgnatcoll-18/src/separate_run_path_option.c libgnatcoll-19/src/separate_run_path_option.c --- libgnatcoll-18/src/separate_run_path_option.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/separate_run_path_option.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,22 +1,25 @@ -/********************************************************************* - * G P S * - * * - * Copyright (C) 2009-2017, AdaCore * - * * - * GPS 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., 59 Temple * - * Place - Suite 330, Boston, MA 02111-1307, USA. * - *********************************************************************/ - +/*---------------------------------------------------------------------------- +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2009-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ /* Dummy version of __gnat_separate_run_path_options, needed by mlib.adb */ diff -Nru libgnatcoll-18/src/set_std_prefix.c libgnatcoll-19/src/set_std_prefix.c --- libgnatcoll-18/src/set_std_prefix.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/set_std_prefix.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,22 +1,25 @@ -/********************************************************************* - * G P S * - * * - * Copyright (C) 2002-2004 * - * ACT-Europe * - * * - * GPS 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., 59 Temple * - * Place - Suite 330, Boston, MA 02111-1307, USA. * - *********************************************************************/ +/*---------------------------------------------------------------------------- +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2002-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ /* Dummy version of set_std_prefix (needed by osint.adb) */ diff -Nru libgnatcoll-18/src/terminals.c libgnatcoll-19/src/terminals.c --- libgnatcoll-18/src/terminals.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/terminals.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,19 +1,25 @@ /*---------------------------------------------------------------------------- --- G N A T C O L L -- +-- G N A T C O L L -- -- -- --- Copyright (C) 2014-2017, AdaCore -- +-- Copyright (C) 2014-2018, AdaCore -- -- -- --- This is free software; you can redistribute it and/or modify it under -- --- terms of the GNU General Public License as published by the Free Soft- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. This software is distributed in the hope that it will be useful, -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- -- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY 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 distributed with this software; see file -- --- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy -- --- of the license. -- -----------------------------------------------------------------------------*/ +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ #ifdef _WIN32 #include diff -Nru libgnatcoll-18/src/update_path.c libgnatcoll-19/src/update_path.c --- libgnatcoll-18/src/update_path.c 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/src/update_path.c 2019-05-16 17:44:09.000000000 +0000 @@ -1,22 +1,25 @@ -/********************************************************************* - * G P S * - * * - * Copyright (C) 2002-2004 * - * ACT-Europe * - * * - * GPS 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., 59 Temple * - * Place - Suite 330, Boston, MA 02111-1307, USA. * - *********************************************************************/ +/*---------------------------------------------------------------------------- +-- G N A T C O L L -- +-- -- +-- Copyright (C) 2002-2018, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- -- +-- -- +-- -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-----------------------------------------------------------------------------*/ /* Dummy version of update_path (needed by osint.adb) */ diff -Nru libgnatcoll-18/testsuite/drivers/basic.py libgnatcoll-19/testsuite/drivers/basic.py --- libgnatcoll-18/testsuite/drivers/basic.py 2018-03-24 08:28:47.000000000 +0000 +++ libgnatcoll-19/testsuite/drivers/basic.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,62 +0,0 @@ -from e3.fs import cp -from e3.testsuite.driver import TestDriver -from e3.testsuite.process import check_call -from e3.testsuite.result import TestStatus -from drivers import gprbuild -import os - - -class BasicTestDriver(TestDriver): - """Default GNATcoll testsuite driver. - - In order to declare a test: - - 1- Create a directory with a test.yaml inside - 2- Add test sources in that directory - 3- Add a main called test.adb that use support/test_assert.ads package. - 4- Do not put test.gpr there, it breaks the test, if you need a project - file for testing, name it something else. - 5- If you need additional files for you test, list them in test.yaml: - data: - - "your_file1" - - "your_file2" - """ - - def add_test(self, dag): - """Declare test workflow. - - The workflow is the following:: - - build --> check status - - :param dag: tree of test fragment to amend - :type dag: e3.collection.dag.DAG - """ - self.add_fragment(dag, 'build') - self.add_fragment(dag, 'check_run', after=['build']) - - if 'test_exe' not in self.test_env: - self.test_env['test_exe'] = 'obj/test' - - def build(self, previous_values): - """Build fragment.""" - return gprbuild(self, gcov=self.env.gcov) - - def check_run(self, previous_values): - """Check status fragment.""" - if not previous_values['build']: - return - - for data in self.test_env.get('data', []): - cp(os.path.join(self.test_env['test_dir'], data), - self.test_env['working_dir'], recursive=True) - - process = check_call( - self, - [os.path.join(self.test_env['working_dir'], - self.test_env['test_exe'])]) - if '<=== TEST PASSED ===>' not in process.out: - self.result.set_status(TestStatus.FAIL) - else: - self.result.set_status(TestStatus.PASS) - self.push_result() diff -Nru libgnatcoll-18/testsuite/drivers/data_validation.py libgnatcoll-19/testsuite/drivers/data_validation.py --- libgnatcoll-18/testsuite/drivers/data_validation.py 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/drivers/data_validation.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -from e3.fs import rm -from e3.testsuite.driver import TestDriver -from e3.testsuite.process import check_call -from e3.testsuite.result import TestStatus, TestResult -from drivers import gprbuild -import os - - -class DataValidationDriver(TestDriver): - """Data validation driver. - - For each test program call the program with data file defined in - data_files key of the test. If the program returns 0 assume that - the test passed. - """ - - def add_test(self, dag): - self.add_fragment(dag, 'build') - - tear_down_deps = [] - for data_file, description in self.test_env['data_files'].iteritems(): - tear_down_deps.append(data_file) - self.add_fragment( - dag, - data_file, - fun=lambda x, d=data_file, m=description: - self.run_subtest(d, m, x), - after=['build']) - self.add_fragment(dag, 'tear_down', after=tear_down_deps) - - def run_subtest(self, data_file, description, previous_values): - test_name = self.test_name + '.' + data_file - result = TestResult(test_name, env=self.test_env) - - if not previous_values['build']: - return TestStatus.FAIL - - process = check_call( - self, - [os.path.join(self.test_env['working_dir'], - self.test_env.get('validator', 'obj/test')), - os.path.join(self.test_env['test_dir'], data_file)], - result=result) - - return self.validate_result(process, data_file, result) - - def validate_result(self, process, data_file, result): - # Read data file - if '<=== TEST PASSED ===>' in process.out: - return TestStatus.PASS - else: - result.set_status(TestStatus.FAIL) - self.push_result(result) - return TestStatus.FAIL - - def tear_down(self, previous_values): - failures = [v for v in previous_values.values() if - not isinstance(v, TestStatus) or v != TestStatus.PASS] - if failures: - self.result.set_status(TestStatus.FAIL, - msg="%s subtests failed" % len(failures)) - else: - self.result.set_status(TestStatus.PASS) - - self.push_result() - - if self.env.enable_cleanup: - rm(self.test_env['working_dir'], recursive=True) - - def build(self, previous_values): - return gprbuild(self, gcov=self.env.gcov) diff -Nru libgnatcoll-18/testsuite/drivers/__init__.py libgnatcoll-19/testsuite/drivers/__init__.py --- libgnatcoll-18/testsuite/drivers/__init__.py 2018-03-05 13:06:24.000000000 +0000 +++ libgnatcoll-19/testsuite/drivers/__init__.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,98 +0,0 @@ -from e3.env import Env -from e3.fs import mkdir -from e3.os.process import Run -from e3.testsuite.process import check_call -import os -import logging - - -TESTSUITE_ROOT_DIR = os.path.dirname( - os.path.dirname(os.path.abspath(__file__))) -GNATCOLL_ROOT_DIR = os.path.dirname(TESTSUITE_ROOT_DIR) - - -def make_gnatcoll_for_gcov(work_dir): - """Build gnatcoll core with gcov instrumentation. - - :param work_dir: working directory. gnatcoll is built in `build` subdir - and installed in `install` subdir - :type work_dir: str - :return: a triplet (project path, source path, object path) - :rtype: (str, str, str) - :raise AssertError: in case compilation of installation fails - """ - logging.info('Compiling gnatcoll with gcov instrumentation') - build_dir = os.path.join(work_dir, 'build') - install_dir = os.path.join(work_dir, 'install') - mkdir(build_dir) - mkdir(install_dir) - - make_gnatcoll_cmd = [ - 'make', '-f', os.path.join(GNATCOLL_ROOT_DIR, 'Makefile'), - 'BUILD=DEBUG', - 'GPRBUILD_OPTIONS=-cargs -fprofile-arcs -ftest-coverage -gargs', - 'ENABLE_SHARED=no'] - - p = Run(make_gnatcoll_cmd, cwd=build_dir) - assert p.status == 0, "gnatcoll build failed:\n%s" % p.out - - p = Run(make_gnatcoll_cmd + ['prefix=%s' % install_dir, 'install'], - cwd=build_dir) - assert p.status == 0, "gnatcoll installation failed:\n%s" % p.out - - # Add the resulting library into the GPR path - Env().add_search_path('GPR_PROJECT_PATH', - os.path.join(install_dir, 'share', 'gpr')) - return (os.path.join(install_dir, 'share', 'gpr'), - os.path.join(install_dir, 'include', 'gnatcoll'), - os.path.join(build_dir, 'obj', 'gnatcoll', 'static')) - - -def gprbuild(driver, - project_file=None, - cwd=None, - gcov=False, - scenario=None, - **kwargs): - """Launch gprbuild. - - :param project_file: project file to compile. If None, we looks first for - a test.gpr in the test dir and otherwise fallback on the common - test.gpr project of the support subdir of the testsuite. - :type project_file: str - :param cwd: directory in which to run gprbuild. If None the gprbuild build - is run in the default working dir for the test. - :type cwd: str | None - :param gcov: if True link with gcov libraries - :type gcov: bool - :param scenario: scenario variable values - :type scenario: dict - """ - if scenario is None: - scenario = {} - - if project_file is None: - project_file = os.path.join(driver.test_env['test_dir'], - 'test.gpr') - if not os.path.isfile(project_file): - project_file = os.path.join(TESTSUITE_ROOT_DIR, - 'support', 'test.gpr') - scenario['TEST_SOURCES'] = driver.test_env['test_dir'] - - if cwd is None: - cwd = driver.test_env['working_dir'] - mkdir(cwd) - gprbuild_cmd = [ - 'gprbuild', '--relocate-build-tree', '-p', '-P', project_file] - for k, v in scenario.iteritems(): - gprbuild_cmd.append('-X%s=%s' % (k, v)) - if gcov: - gprbuild_cmd += ['-largs', '-lgcov', '-cargs', - '-fprofile-arcs', '-ftest-coverage'] - check_call( - driver, - gprbuild_cmd, - cwd=cwd, - **kwargs) - # If we get there it means the build succeeded. - return True diff -Nru libgnatcoll-18/testsuite/drivers/json_validation.py libgnatcoll-19/testsuite/drivers/json_validation.py --- libgnatcoll-18/testsuite/drivers/json_validation.py 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/drivers/json_validation.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -from e3.testsuite.result import TestStatus -from drivers.data_validation import DataValidationDriver -import os -import json -import logging - - -class JSONValidationDriver(DataValidationDriver): - - def validate_result(self, process, data_file, result): - # Read data file - with open(os.path.join(self.test_env['test_dir'], data_file)) as fd: - expected = json.load(fd) - - got = json.loads(process.out) - if got != expected: - logging.debug('%s\n<=>\n%s', got, expected) - result.set_status(TestStatus.FAIL) - self.push_result(result) - return TestStatus.FAIL - else: - return TestStatus.PASS diff -Nru libgnatcoll-18/testsuite/e3-test.yaml libgnatcoll-19/testsuite/e3-test.yaml --- libgnatcoll-18/testsuite/e3-test.yaml 2018-03-05 13:06:24.000000000 +0000 +++ libgnatcoll-19/testsuite/e3-test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -main: run-tests -default_args: [] diff -Nru libgnatcoll-18/testsuite/README.md libgnatcoll-19/testsuite/README.md --- libgnatcoll-18/testsuite/README.md 2018-03-08 12:41:30.000000000 +0000 +++ libgnatcoll-19/testsuite/README.md 1970-01-01 00:00:00.000000000 +0000 @@ -1,24 +0,0 @@ -Running GNATcoll Testsuite -========================== - -`The testsuite is currently under construction !` - -To run it you need to have Python installed along with the package -e3-testsuite. - -To install e3-testsuite: - -```sh -pip install git+https://github.com/AdaCore/e3-testsuite.git -``` - -Then do - -```sh -./run-tests -``` - -In order to have coverage information with gcov, just add `--gcov`. In that -case a summary of the coverage information is displayed at the end of the -testsuite. Full coverage information can be found in `gcov/results` -subdirectory. diff -Nru libgnatcoll-18/testsuite/run-tests libgnatcoll-19/testsuite/run-tests --- libgnatcoll-18/testsuite/run-tests 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/run-tests 1970-01-01 00:00:00.000000000 +0000 @@ -1,102 +0,0 @@ -#!/usr/bin/env python -from drivers import make_gnatcoll_for_gcov, TESTSUITE_ROOT_DIR -from drivers.basic import BasicTestDriver -from drivers.json_validation import JSONValidationDriver -from drivers.data_validation import DataValidationDriver -from e3.testsuite import Testsuite -from e3.fs import mkdir, ls, find -from e3.os.process import Run -import re -import os -import logging - - -class MyTestsuite(Testsuite): - CROSS_SUPPORT = True - TEST_SUBDIR = 'tests' - DRIVERS = { - 'json_validation': JSONValidationDriver, - 'data_validation': DataValidationDriver, - 'default': BasicTestDriver} - - def add_options(self): - self.main.argument_parser.add_argument( - '--gcov', - help="compute testsuite coverage of gnatcoll", - default=False, - action="store_true") - - def tear_up(self): - self.env.gcov = self.main.args.gcov - self.env.enable_cleanup = self.main.args.enable_cleanup - if self.main.args.gcov: - work_dir = os.path.join(TESTSUITE_ROOT_DIR, 'gcov') - gpr_dir, src_dir, obj_dir = make_gnatcoll_for_gcov(work_dir) - self.env.gnatcoll_gpr_dir = gpr_dir - self.env.gnatcoll_src_dir = src_dir - self.env.gnatcoll_obj_dir = obj_dir - - def tear_down(self): - if self.main.args.gcov: - wd = TESTSUITE_ROOT_DIR - - # We need to call gcov on gcda present both in gnatcoll itself and - # tests (for generics coverage). - gcda_files = \ - find(os.path.join(self.env.gnatcoll_obj_dir), '*.gcda') + \ - find(os.path.join(self.env.working_dir), '*.gcda') - mkdir(os.path.join(wd, 'gcov', 'results')) - gcr = os.path.join(wd, 'gcov', 'results') - Run(['gcov'] + gcda_files, - cwd=os.path.join(wd, 'gcov', 'results')) - total_sources = 0 - total_covered = 0 - - for source_file in ls( - os.path.join(self.env.gnatcoll_src_dir, '*')): - base_file = os.path.basename(source_file) - if not os.path.isfile(os.path.join(gcr, base_file + '.gcov')): - total = 1 - covered = 0 - with open(source_file) as fd: - total = len([line for line in fd - if line.strip() and - not re.match(r' *--', line)]) - else: - with open(os.path.join(gcr, base_file + '.gcov')) as fd: - total = 0 - covered = 0 - for line in fd: - if re.match(r' *-:', line): - pass - elif re.match(r' *[#=]{5}:', line): - total += 1 - else: - total += 1 - covered += 1 - total_sources += total - total_covered += covered - - logging.info('%6.2f %% %8d/%-8d %s', - float(covered) * 100.0 / float(total), - covered, - total, - os.path.basename(source_file)) - - logging.info('%6.2f %% %8d/%-8d %s', - float(total_covered) * 100.0 / float(total_sources), - total_covered, - total_sources, - 'TOTAL') - super(MyTestsuite, self).tear_down() - - @property - def default_driver(self): - return 'default' - - -if __name__ == '__main__': - suite = MyTestsuite(os.path.dirname(__file__)) - suite.testsuite_main() - for k, v in suite.test_status_counters.iteritems(): - print '%-24s: %d' % (k, v) diff -Nru libgnatcoll-18/testsuite/support/test_assert.adb libgnatcoll-19/testsuite/support/test_assert.adb --- libgnatcoll-18/testsuite/support/test_assert.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/support/test_assert.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,113 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2018, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - -with Ada.Text_IO; - -package body Test_Assert is - package IO renames Ada.Text_IO; - - ------------ - -- Assert -- - ------------ - - procedure Assert - (Success : Boolean; - Msg : String := ""; - Location : String := SI.Source_Location) - is - begin - IO.Put (Location & ": "); - if Success then - IO.Put ("PASSED:"); - else - IO.Put ("FAILED:"); - Final_Status := 1; - end if; - if Msg'Length > 0 then - IO.Put (" "); - IO.Put (Msg); - end if; - IO.New_Line; - end Assert; - - ------------ - -- Assert -- - ------------ - - procedure Assert - (Left, Right : String; - Msg : String := ""; - Location : String := SI.Source_Location) - is - Success : constant Boolean := Left = Right; - begin - Assert (Success, Msg, Location); - if not Success then - if Right'Length > 0 then - IO.Put_Line ("expected: " & Right); - else - IO.Put_Line ("expected empty string"); - end if; - - if Left'Length > 0 then - IO.Put_Line ("got: " & Left); - else - IO.Put_Line ("got empty string"); - end if; - end if; - end Assert; - - ------------ - -- Assert -- - ------------ - - procedure Assert - (Left, Right : VFS.Virtual_File; - Msg : String := ""; - Location : String := SI.Source_Location) - is - use type VFS.Virtual_File; - Success : constant Boolean := Left = Right; - begin - Assert (Success, Msg, Location); - if not Success then - IO.Put_Line ("expected: " & VFS.Display_Full_Name (Right)); - IO.Put_Line ("got: " & VFS.Display_Full_Name (Left)); - end if; - end Assert; - - ------------ - -- Report -- - ------------ - - function Report return Natural is - begin - if Final_Status = 0 then - IO.Put_Line ("<=== TEST PASSED ===>"); - else - IO.PUT_Line ("<=== TEST FAILED ===>"); - end if; - return Final_Status; - end Report; - -end Test_Assert; diff -Nru libgnatcoll-18/testsuite/support/test_assert.ads libgnatcoll-19/testsuite/support/test_assert.ads --- libgnatcoll-18/testsuite/support/test_assert.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/support/test_assert.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2018, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - --- Helper package to implement tests that comply with the expectations --- of the default test driver. - -with GNAT.Source_Info; -with GNATCOLL.VFS; - -package Test_Assert is - - package SI renames GNAT.Source_Info; - package VFS renames GNATCOLL.VFS; - - Final_Status : Natural := 0; - - procedure Assert - (Success : Boolean; - Msg : String := ""; - Location : String := SI.Source_Location); - -- If Success is True then test case is considered PASSED, otherwise - -- the test status is FAILED and Final_Status set to 1. - - procedure Assert - (Left, Right : String; - Msg : String := ""; - Location : String := SI.Source_Location); - -- If Left = Right then test case is considered PASSED, otherwise - -- the test status is FAILED and Final_Status set to 1. - - procedure Assert - (Left, Right : VFS.Virtual_File; - Msg : String := ""; - Location : String := SI.Source_Location); - -- If Left = Right then test case is considered PASSED, otherwise - -- the test status is FAILED and Final_Status set to 1. - - function Report return Natural; - -- Report should be called the following way at the end of a test - -- program main function: - -- - -- return Report; - -- - -- Testsuite driver will consider a test to PASS if all the - -- following conditions are met: - -- - -- * test program exit with status 0 - -- * all assert calls did succeed - -- * test program display the message "<=== TEST PASSED ===>" -end Test_Assert; diff -Nru libgnatcoll-18/testsuite/support/test.gpr libgnatcoll-19/testsuite/support/test.gpr --- libgnatcoll-18/testsuite/support/test.gpr 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/support/test.gpr 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ --- Default project use for tests --- --- The scenario variable TEST_SOURCES is automatically set by the --- driver to point to the test sources. -with "gnatcoll"; - -project Test is - Test_Sources := External("TEST_SOURCES"); - for Source_Dirs use (".", Test_Sources); - for Main use ("test.adb"); - for Languages use ("Ada"); - for Object_Dir use "obj"; -end Test; diff -Nru libgnatcoll-18/testsuite/support/test_remote.adb libgnatcoll-19/testsuite/support/test_remote.adb --- libgnatcoll-18/testsuite/support/test_remote.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/support/test_remote.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2018, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - -with GNAT.OS_Lib; -with GNAT.Directory_Operations; -with GNAT.Expect; -with GNAT.Expect.TTY; -with Ada.Text_IO; -with GNATCOLL.Utils; - -package body Test_Remote is - - package Expect renames GNAT.Expect; - package OS renames GNAT.OS_Lib; - package OS_Path renames GNAT.Directory_Operations; - package IO renames Ada.Text_IO; - - use type GVT.FS_String; - - -------------- - -- Nickname -- - -------------- - - function Nickname (Server : Local_Transport) return String is - begin - return "local"; - end Nickname; - - -------------- - -- Shell_FS -- - -------------- - - function Shell_FS (Server : Local_Transport) return GVT.FS_Type is - begin - return GVT.FS_Unix; - end Shell_FS; - - ---------------------- - -- Execute_Remotely -- - ---------------------- - - procedure Execute_Remotely - (Server : access Local_Transport; - Args : GNAT.Strings.String_List; - Status : out Boolean; - Execution_Directory : GVT.FS_String := "") - is - CWD : constant String := OS_Path.Get_Current_Dir; - Script : constant String := GNATCOLL.Utils.Join (" ", Args); - Program_Name : constant String := "/bin/bash"; - Program_Args : GNAT.Strings.String_List (1 .. 2) := - (1 => new String'("-c"), 2 => new String'(Script)); - begin - if Execution_Directory /= "" then - OS_Path.Change_Dir (String (Execution_Directory)); - end if; - OS.Spawn (Program_Name, Program_Args, Status); - if Execution_Directory /= "" then - OS_Path.Change_Dir (String (CWD)); - end if; - end Execute_Remotely; - - ---------------------- - -- Execute_Remotely -- - ---------------------- - - procedure Execute_Remotely - (Server : access Local_Transport; - Args : GNAT.Strings.String_List; - Result : out GNAT.Strings.String_Access; - Status : out Boolean; - Execution_Directory : GVT.FS_String := "") - is - CWD : constant String := OS_Path.Get_Current_Dir; - Program_Name : constant String := Args (1).all; - Program_Args : constant GNAT.Strings.String_List := - Args (2 .. Args'Last); - Int_Status : aliased Integer; - begin - if Execution_Directory /= "" then - OS_Path.Change_Dir (String (Execution_Directory)); - end if; - IO.Put_Line (Program_Name); - Result := - new String' - (Expect.Get_Command_Output - (Program_Name, Program_Args, "", Int_Status'Access, True)); - if Int_Status = 0 then - Status := True; - else - Status := False; - end if; - if Execution_Directory /= "" then - OS_Path.Change_Dir (String (CWD)); - end if; - end Execute_Remotely; - - -------------------- - -- Spawn_Remotely -- - -------------------- - - procedure Spawn_Remotely - (Server : access Local_Transport; - Descriptor : out GNAT.Expect.Process_Descriptor_Access; - Args : GNAT.Strings.String_List) - is - - Program_Name : constant String := Args (1).all; - Program_Args : constant GNAT.Strings.String_List := - Args (2 .. Args'Last); - begin - Descriptor := new GNAT.Expect.TTY.TTY_Process_Descriptor; - IO.Put_Line (Program_Name); - Expect.Non_Blocking_Spawn (Descriptor.all, Program_Name, Program_Args); - end Spawn_Remotely; - - ------------------- - -- Is_Configured -- - ------------------- - - function Is_Configured (Config : Local_DB; Nickname : String) return Boolean - is - begin - if Nickname = "local_test" then - return True; - else - return False; - end if; - end Is_Configured; - - ---------------- - -- Get_Server -- - ---------------- - - function Get_Server - (Config : Local_DB; - Nickname : String) return GR.Server_Access - is - begin - return new Local_Transport; - end Get_Server; - - --------------------- - -- Nb_Mount_Points -- - --------------------- - - function Nb_Mount_Points - (Config : Local_DB; - Nickname : String) return Natural - is - begin - return 1; - end Nb_Mount_Points; - - -------------------------------- - -- Get_Mount_Point_Local_Root -- - -------------------------------- - - function Get_Mount_Point_Local_Root - (Config : Local_DB; - Nickname : String; - Index : Natural) return GVT.FS_String - is - begin - return "/tmp/local_vfs"; - end Get_Mount_Point_Local_Root; - - ------------------------------- - -- Get_Mount_Point_Host_Root -- - ------------------------------- - - function Get_Mount_Point_Host_Root - (Config : Local_DB; - Nickname : String; - Index : Natural) return GVT.FS_String - is - begin - return "/tmp/remote_vfs"; - end Get_Mount_Point_Host_Root; - -end Test_Remote; diff -Nru libgnatcoll-18/testsuite/support/test_remote.ads libgnatcoll-19/testsuite/support/test_remote.ads --- libgnatcoll-18/testsuite/support/test_remote.ads 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/support/test_remote.ads 1970-01-01 00:00:00.000000000 +0000 @@ -1,93 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2018, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - --- The package provides remote support using only local resources. This --- allows to test remote functionalities without the need for a remote host. - -with GNAT.Expect; -with GNAT.Strings; -with GNATCOLL.Remote; -with GNATCOLL.VFS_Types; -with GNATCOLL.Remote.DB; - -package Test_Remote is - - package GR renames GNATCOLL.Remote; - package GRDB renames GNATCOLL.Remote.DB; - package GVT renames GNATCOLL.VFS_Types; - - -- Declare local transport protocol (basically spawn /bin/bash) - type Local_Transport is new GR.Server_Record with null record; - - function Nickname (Server : Local_Transport) return String; - function Shell_FS (Server : Local_Transport) return GVT.FS_Type; - - procedure Execute_Remotely - (Server : access Local_Transport; - Args : GNAT.Strings.String_List; - Status : out Boolean; - Execution_Directory : GVT.FS_String := ""); - - procedure Execute_Remotely - (Server : access Local_Transport; - Args : GNAT.Strings.String_List; - Result : out GNAT.Strings.String_Access; - Status : out Boolean; - Execution_Directory : GVT.FS_String := ""); - - procedure Spawn_Remotely - (Server : access Local_Transport; - Descriptor : out GNAT.Expect.Process_Descriptor_Access; - Args : GNAT.Strings.String_List); - - -- Declare local remote database which holds only one host nickname - -- called local_test - type Local_DB is new GRDB.Remote_Db_Interface with null record; - - function Is_Configured - (Config : Local_DB; - Nickname : String) - return Boolean; - - function Get_Server - (Config : Local_DB; - Nickname : String) - return GR.Server_Access; - - function Nb_Mount_Points - (Config : Local_DB; - Nickname : String) - return Natural; - - function Get_Mount_Point_Local_Root - (Config : Local_DB; - Nickname : String; - Index : Natural) - return GVT.FS_String; - - function Get_Mount_Point_Host_Root - (Config : Local_DB; - Nickname : String; - Index : Natural) return GVT.FS_String; - -end Test_Remote; diff -Nru libgnatcoll-18/testsuite/tests/config/test1.ini libgnatcoll-19/testsuite/tests/config/test1.ini --- libgnatcoll-18/testsuite/tests/config/test1.ini 2018-03-08 12:41:30.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test1.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -key1=value1 -section1.key2 = value2_no_section -int1 = 1 -bool1=true -bool2=False - -[section1] -key2 = value2 -key3 =value 3 -# This is a comment = -key4=value4 - # This is another comment -key[5=value5 -[key6=value6 - diff -Nru libgnatcoll-18/testsuite/tests/config/test2.ini libgnatcoll-19/testsuite/tests/config/test2.ini --- libgnatcoll-18/testsuite/tests/config/test2.ini 2018-03-08 12:41:30.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test2.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -invalid diff -Nru libgnatcoll-18/testsuite/tests/config/test3.ini libgnatcoll-19/testsuite/tests/config/test3.ini --- libgnatcoll-18/testsuite/tests/config/test3.ini 2018-03-08 12:41:30.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test3.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -key1 = value1_2 -key7=value7 diff -Nru libgnatcoll-18/testsuite/tests/config/test4.ini libgnatcoll-19/testsuite/tests/config/test4.ini --- libgnatcoll-18/testsuite/tests/config/test4.ini 2018-03-08 12:41:30.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test4.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -key8 = $e -key9 = $: -key10 = $( -key11 = ${a -=value12 -key12= diff -Nru libgnatcoll-18/testsuite/tests/config/test5.ini libgnatcoll-19/testsuite/tests/config/test5.ini --- libgnatcoll-18/testsuite/tests/config/test5.ini 2018-03-08 12:41:30.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test5.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ - #comment=key - key5_1 = value - [section5_1] - key5_1 = value2 -[sec#tion] -key5_2 = value3 diff -Nru libgnatcoll-18/testsuite/tests/config/test6.ini libgnatcoll-19/testsuite/tests/config/test6.ini --- libgnatcoll-18/testsuite/tests/config/test6.ini 2018-03-09 12:50:52.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test6.ini 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -[ -key=value diff -Nru libgnatcoll-18/testsuite/tests/config/test.adb libgnatcoll-19/testsuite/tests/config/test.adb --- libgnatcoll-18/testsuite/tests/config/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,158 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2010-2018, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - -with Ada.Text_IO; -with GNATCOLL.Config; -with Test_Assert; - -function Test return Integer is - - package IO renames Ada.Text_IO; - package A renames Test_Assert; - package Cfg renames GNATCOLL.Config; - - Ini : Cfg.INI_Parser; - Ini2 : Cfg.INI_Parser; - Ini3 : Cfg.INI_Parser; - Pool : Cfg.Config_Pool; - -begin - - -- Open non existing file - begin - Ini.Open ("non_existent.ini"); - A.Assert (False, "Name_Error should be raised"); - exception - when IO.Name_Error => - A.Assert (True, "Name_Error raised if ini file does not exist"); - when others => - A.Assert (False, "Name_Error should have been raised"); - end; - - -- Open a simple file - IO.Put_Line ("Loading test1.ini"); - Ini.Open ("test1.ini"); - Pool.Fill (Ini); - A.Assert (Pool.Get ("key1"), "value1", "check that key1=value1"); - A.Assert (Pool.Get ("key2", Section => "section1"), "value2", - "check that key2=value2 in section1"); - A.Assert (Pool.Get ("key3", Section => "section1"), "value 3", - "check that trailing spaces are ignored"); - A.Assert (Pool.Get ("section1.key2", - Section=> Cfg.Section_From_Key), - "value2", - "check that sections1.key2=value2 (dot notation)"); - A.Assert (Pool.Get ("section1.key4"), - "value4", - "check that comments around key " & - "declaration do not have impacts"); - - A.Assert (Pool.Get ("section1.key[5"), - "value5", - "key can contain ["); - - A.Assert (Pool.Get ("section1.[key6"), - "value6", - "key can start with ["); - - -- Try to read invalid file (parser is very laxist and does not crash) - Ini.Open ("test2.ini"); - Pool.Fill (Ini); - A.Assert (Pool.Get ("key1"), "value1", "check if key1=value1 is preserved"); - A.Assert (Pool.Get ("invalid"), "", "check if invalid key exist"); - - -- Check if we can override values. - -- The test reuse the same INI_Parser instance and thus check that on - -- call to Open parser state is reset - IO.Put_Line ("Loading test3.ini (parser reuse)"); - Ini.Open ("test3.ini"); - Pool.Fill (Ini); - A.Assert (Pool.Get ("key1"), "value1_2", - "check if key1 is overwritten"); - A.Assert (Pool.Get ("key7"), "value7", "check addition of new key key7"); - A.Assert (Pool.Get ("section1.key2"), - "value2", "check if section1.key2=value2 is preserved"); - - -- Check if we can override values - -- Use a new parser instance - IO.Put_Line ("Loading test3.ini (new parser)"); - Ini2.Open ("test3.ini"); - Pool.Fill (Ini2); - A.Assert (Pool.Get ("key1"), "value1_2", - "check if key1 value is overwritten"); - A.Assert (Pool.Get ("key7"), "value7", "check addtion of new key key7"); - A.Assert (Pool.Get ("section1.key2"), - "value2", "check if section1.key2=value2 is preserved"); - - -- Test non string values - A.Assert (Pool.Get_Boolean ("bool1"), "boolean value (true)"); - A.Assert (not Pool.Get_Boolean ("bool2"), "boolean value (false)"); - A.Assert (Pool.Get_Integer ("int1") = 1, "integer value"); - - -- Test Config_Key creation - declare - CK1 : Cfg.Config_Key := Cfg.Create ("key1"); - begin - A.Assert (CK1.Get (Pool), "value1_2", "basic config_key test"); - end; - - -- Check that introducing invalid gnatcoll templates strings do - -- not crash the parser. - IO.Put_Line ("Loading test4.ini (crashing the gnatcoll-template)"); - begin - Ini3.Open ("test4.ini"); - Pool.Fill (Ini3); - A.Assert (True, "parsing test4.ini"); - exception - when others => - A.Assert (False, "parsing test4.ini"); - end; - -- Check some corner cases involving leading whitespaces for example - IO.Put_Line ("Loading test5.ini"); - begin - Ini3.Open ("test5.ini"); - Pool.Fill (Ini3); - A.Assert (True, "parsing test5.ini"); - A.Assert (Pool.Get("#comment") /= "key", - "ensure comment was parsed correctly"); - A.Assert (Pool.Get("key5_1") /= "value2", - "ensure section was parsed correctly"); - A.Assert (Pool.Get("tion#key5_2", Section => "sec") /= "value3", - "ensure # is not considered as a special character"); - exception - when others => - A.Assert (False, "parsing test5.ini"); - end; - - -- Check that a line containing only [ will not crash the parser - begin - Ini3.Open ("test6.ini"); - Pool.Fill (Ini3); - A.Assert (True, "parsing test6.ini"); - exception - when others => - A.Assert (False, "parsing test6.ini"); - end; - return A.Report; - -end Test; diff -Nru libgnatcoll-18/testsuite/tests/config/test.yaml libgnatcoll-19/testsuite/tests/config/test.yaml --- libgnatcoll-18/testsuite/tests/config/test.yaml 2018-03-08 12:41:30.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/config/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -description: Test for GNATCOLL.Config -data: - - "*.ini" diff -Nru libgnatcoll-18/testsuite/tests/geometry/test.adb libgnatcoll-19/testsuite/tests/geometry/test.adb --- libgnatcoll-18/testsuite/tests/geometry/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/geometry/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,441 +0,0 @@ ------------------------------------------------------------------------------- --- G N A T C O L L -- --- -- --- Copyright (C) 2010-2018, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- -- --- -- --- -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - -with Ada.Text_IO; -with GNATCOLL.Geometry; -with Test_Assert; - -function Test return Integer is - - package IO renames Ada.Text_IO; - package A renames Test_Assert; - - generic - type Coordinate is digits <>; - with package G is new GNATCOLL.Geometry (Coordinate); - package Asserts is - use type G.Point; - - Tolerance : constant G.Distance_Type := 1.0E-5; - -- Tolerance when comparing distances - - procedure Put (P : G.Point); - -- Put image of a point on stdout - - procedure Put (C : G.Circle); - -- Put image of a circle on stdout - - procedure Assert (P1, P2 : G.Point; Error : String); - -- Check if two points are equals - - procedure Assert_Inside - (P : G.Point; - S : G.Segment; - On_Line : Boolean := True; - On_Segment : Boolean := True; - Error : String := ""); - - procedure Assert_Inside_Triangle - (P : G.Point; - T : G.Triangle; - Result : Boolean := True; - Error : String := ""); - - procedure Assert_Intersection - (S1, S2 : G.Segment; - On_Line, On_Segment : G.Point; - Error : String); - - procedure Assert_Intersect_Triangle - (T1, T2 : G.Triangle; Result : Boolean; Error : String); - procedure Assert_Intersect_Rectangle - (R1, R2 : G.Rectangle; Result : Boolean; Error : String); - procedure Assert_Same_Side - (P1, P2 : G.Point; S : G.Segment; Result : Boolean; Error : String); - procedure Assert (D1, D2 : Coordinate'Base; Error : String); - procedure Assert_Distance - (P : G.Point; S : G.Segment; On_Line, On_Segment : Coordinate; - Error : String); - procedure Assert_Area - (P : G.Polygon; D : Coordinate; Error : String); - procedure Assert - (C1, C2 : G.Circle; Error : String); - end Asserts; - - package body Asserts is - - --------- - -- Put -- - --------- - - procedure Put (P : G.Point) is - begin - if P = G.No_Point then - IO.Put ("(No point)"); - elsif P = G.Infinity_Points then - IO.Put ("(Infinity of points)"); - else - IO.Put ("(" & P.X'Img & "," & P.Y'Img & ")"); - end if; - end Put; - - --------- - -- Put -- - --------- - - procedure Put (C : G.Circle) is - begin - IO.Put ("(c="); Put (C.Center); - IO.Put (" r=" & C.Radius'Img); - end Put; - - ------------ - -- Assert -- - ------------ - - procedure Assert (P1, P2 : G.Point; Error : String) is - Success : constant Boolean := P1 = P2; - begin - A.Assert (Success, Error); - if not Success then - IO.Put ("expected: "); Put (P1); IO.New_Line; - IO.Put ("got: "); Put (P2); IO.New_Line; - end if; - end Assert; - - procedure Assert_Inside - (P : G.Point; - S : G.Segment; - On_Line : Boolean := True; - On_Segment : Boolean := True; - Error : String := "") - is - SR : constant G.Segment := (S (2), S (1)); - begin - A.Assert (G.Inside (P, G.To_Line (S)) = On_Line, Error & " (line test)"); - A.Assert (G.Inside (P, G.To_Line (SR)) = On_Line, Error & " (reverse line test)"); - A.Assert (G.Inside (P, S) = On_Segment, - Error & " (segment test)"); - A.Assert (G.Inside (P, SR) = On_Segment, - Error & " (reverse segment test)"); - end Assert_Inside; - - procedure Assert_Inside_Triangle - (P : G.Point; T : G.Triangle; - Result : Boolean := True; - Error : String := "") - is - T2 : constant G.Triangle := (T (3), T (2), T (1)); - begin - A.Assert (G.Inside (P, T) = Result, Error & " (triangle test)"); - A.Assert (G.Inside (P, T2) = Result, Error & " (reverse triangle test)"); - A.Assert (G.Inside (P, G.Polygon (T)) = Result, Error & " (polygon test)"); - A.Assert (G.Inside (P, G.Polygon (T2)) = Result, Error & " (reverse polygon test)"); - end Assert_Inside_Triangle; - - procedure Assert_Intersection - (S1, S2 : G.Segment; - On_Line : G.Point; - On_Segment : G.Point; - Error : String) - is - begin - A.Assert (G.Intersection (G.To_Line (S1), G.To_Line (S2)) = On_Line, - Error & " (line test)"); - A.Assert (G.Intersection (G.To_Line (S2), G.To_Line (S1)) = On_Line, - Error & " (reverse line test)"); - A.Assert (G.Intersection (S1, S2) = On_Segment, - Error & " (segment test)"); - A.Assert (G.Intersection (S2, S1) = On_Segment, - Error & " (reverse segment test)"); - end Assert_Intersection; - - procedure Assert_Intersect_Triangle - (T1, T2 : G.Triangle; Result : Boolean; Error : String) - is - T3 : constant G.Triangle := (T1 (2), T1 (3), T1 (1)); - begin - A.Assert (G.Intersect (T1, T2) = Result, Error & " (test1)"); - A.Assert (G.Intersect (T2, T1) = Result, Error & " (test2)"); - A.Assert (G.Intersect (T3, T2) = Result, Error & " (test3)"); - A.Assert (G.Intersect (T2, T3) = Result, Error & " (test4)"); - end Assert_Intersect_Triangle; - - procedure Assert_Intersect_Rectangle - (R1, R2 : G.Rectangle; Result : Boolean; Error : String) - is - begin - A.Assert (G.Intersect (R1, R2) = Result, Error); - end Assert_Intersect_Rectangle; - - procedure Assert_Same_Side - (P1, P2 : G.Point; S : G.Segment; Result : Boolean; Error : String) is - begin - A.Assert (G.Same_Side (P1, P2, S) = Result, Error & " (segment test)"); - A.Assert (G.Same_Side (P1, P2, G.To_Line (S)) = Result, Error & " (line test)"); - end Assert_Same_Side; - - procedure Assert (D1, D2 : Coordinate'Base; Error : String) is - Success : constant Boolean := abs (D1 - D2) <= Tolerance; - begin - A.Assert (Success, Error); - if not Success then - IO.Put_Line ("expected: " & D1'Img); - IO.Put_Line ("got: " & D2'Img); - end if; - end Assert; - - procedure Assert_Distance - (P : G.Point; - S : G.Segment; - On_Line, On_Segment : Coordinate; - Error : String) - is - SR : constant G.Segment := (S (2), S (1)); - begin - A.Assert (G.Distance (P, G.To_Line (S)) = On_Line, Error & " (line test)"); - A.Assert (G.Distance (P, G.To_Line (SR)) = On_Line, - Error & " (reverse line test)"); - A.Assert (G.Distance (P, S) = On_Segment, - Error & " (segment test)"); - A.Assert (G.Distance (P, SR) = On_Segment, - Error & " (reverse segment test)"); - end Assert_Distance; - - procedure Assert_Area - (P : G.Polygon; D : Coordinate; Error : String) is - begin - Assert (G.Area (P), abs (D), Error & " (poly test)"); - if P'Length = 3 then - Assert (G.Area (G.Triangle (P)), D, - Error & " (triangle test)"); - end if; - end Assert_Area; - - procedure Assert (C1, C2 : G.Circle; Error : String) is - use type G.Circle; - Success : constant Boolean := C1 = C2; - begin - A.Assert (Success, Error); - if not Success then - IO.Put ("expected: "); Put (C1); IO.New_Line; - IO.Put ("got: "); Put (C2); IO.New_Line; - end if; - end Assert; - end Asserts; - - generic - type Coordinate is digits <>; - procedure Tests; - - procedure Tests is - package G is new GNATCOLL.Geometry (Coordinate); - package Assertions is new Asserts (Coordinate, G); - use Assertions, G, G.Coordinate_Elementary_Functions; - begin - Assert_Inside ((2.0, 0.0), ((0.0, 0.0), (10.0, 0.0)), True, True, - "Point on vertical line"); - Assert_Inside ((-1.0, 0.0), ((0.0, 0.0), (10.0, 0.0)), True, False, - "Point on vertical line, but not on segment"); - Assert_Inside ((0.0, 0.0), ((0.0, 0.0), (10.0, 0.0)), True, True, - "Point on vertical line at one end"); - Assert_Inside ((0.0, 2.0), ((0.0, 0.0), (0.0, 10.0)), True, True, - "Point on horizontal line"); - Assert_Inside ((0.0, -1.0), ((0.0, 0.0), (0.0, 10.0)), True, False, - "Point on horizontal line, but not on segment"); - Assert_Inside ((0.0, 0.0), ((0.0, 0.0), (0.0, 10.0)), True, True, - "Point on horizontal line at one end"); - Assert_Inside ((0.0, 0.0), ((-2.0, 2.0), (2.0, 2.0)), False, False, - "Not on line nor segment"); - Assert_Intersection - (((0.0, 0.0), (10.0, 0.0)), ((0.0, 0.0), (10.0, 0.0)), - Infinity_Points, Infinity_Points, - "Intersection of same horizontal line is infinite"); - Assert_Intersection - (((0.0, 0.0), (10.0, 0.0)), ((0.0, 0.0), (5.0, 0.0)), - Infinity_Points, Infinity_Points, - "Intersection of overlapping horizontal line is infinite"); - Assert_Intersection - (((0.0, 0.0), (0.0, 10.0)), ((0.0, 0.0), (0.0, 10.0)), - Infinity_Points, Infinity_Points, - "Intersection of same vertical line is infinite"); - Assert_Intersection - (((0.0, 0.0), (0.0, 10.0)), ((0.0, 0.0), (0.0, 5.0)), - Infinity_Points, Infinity_Points, - "Intersection of overlapping vertical vectors is infinite"); - Assert_Intersection - (((0.0, 0.0), (10.0, 0.0)), ((-2.0, 2.0), (2.0, 2.0)), - No_Point, No_Point, - "No intersection of parallel vectors"); - Assert_Intersection - (((0.0, 0.0), (10.0, 0.0)), ((11.0, 0.0), (20.0, 0.0)), - Infinity_Points, No_Point, - "Intersection of aligned vectors"); - Assert_Intersection - (((0.0, 0.0), (0.0, 10.0)), ((-2.0, 2.0), (2.0, 2.0)), - Point'(0.0, 2.0), Point'(0.0, 2.0), - "Simple segment intersection"); - Assert_Intersection - (((0.0, 0.0), (0.0, 10.0)), ((-2.0, 0.0), (2.0, 0.0)), - Point'(0.0, 0.0), Point'(0.0, 0.0), - "Intersection at one end of the vectors"); - Assert_Intersection - (((0.0, 0.0), (10.0, 0.0)), ((-2.0, 2.0), (2.0, 2.0)), - No_Point, No_Point, - "Parallel lines have no intersection"); - Assert_Distance - ((0.0, 0.0), ((-2.0, 2.0), (2.0, 2.0)), 2.0, 2.0, - "Simple distance to line"); - Assert_Distance - ((0.0, 2.0), ((-2.0, 2.0), (2.0, 2.0)), 0.0, 0.0, - "Distance when point on line"); - Assert_Distance - ((-3.0, 2.0), ((-2.0, 2.0), (2.0, 2.0)), 0.0, 1.0, - "Distance when point on line, not on segment"); - Assert_Distance - ((-3.0, 0.0), ((-2.0, 2.0), (2.0, 2.0)), 2.0, Sqrt (5.0), - "Distance when orthogonal projection not on segment"); - Assert_Area - (((0.0, 0.0), (4.0, 0.0), (0.0, 3.0)), 6.0, - "Area of a counter-clockwise triangle"); - Assert_Area - (((0.0, 0.0), (0.0, 3.0), (4.0, 0.0)), 6.0, - "Area of clockwise triangle"); - Assert_Area - (((0.0, 0.0), (0.0, 3.0), (2.0, 3.0), (2.0, 4.0), - (3.0, 4.0), (3.0, 0.0)), 10.0, - "Area for two squares (non-convex)"); - Assert - (To_Circle ((0.0, 0.0), (1.0, 0.0), (0.0, 1.0)), - ((0.5, 0.5), Sqrt (0.5)), - "Circle from point"); - Assert_Inside_Triangle - ((0.0, 0.0), ((0.0, 0.0), (0.0, 1.0), (1.0, 0.0)), - True, "Point on boundary of triangle"); - Assert_Inside_Triangle - ((0.1, 0.1), ((0.0, 0.0), (0.0, 1.0), (1.0, 0.0)), - True, "Point inside triangle"); - Assert_Inside_Triangle - ((0.5, 1.0), ((0.0, 0.0), (0.0, 1.0), (1.0, 0.0)), - False, "Point outside triangle"); - A.Assert - (G.Inside ((2.5, 3.5), - Poly => ((0.0, 0.0), (0.0, 3.0), (2.0, 3.0), (2.0, 4.0), - (3.0, 4.0), (3.0, 0.0))), - "Point inside non-convex polygon"); - A.Assert - (G.Inside ((2.0, 2.5), - Poly => ((0.0, 0.0), (0.0, 3.0), (2.0, 3.0), (2.0, 4.0), - (3.0, 4.0), (3.0, 0.0))), - "Point inside non-convex polygon, vertically below vertex"); - Assert_Same_Side - ((0.0, 0.0), (4.0, 0.0), ((-2.0, 2.0), (2.0, 2.0)), True, - "Same side of horizontal line"); - Assert_Same_Side - ((0.0, 0.0), (0.0, 4.0), ((-2.0, 2.0), (-2.0, -2.0)), True, - "Same side of vertical line"); - Assert_Same_Side - ((0.0, 0.0), (4.0, 0.0), ((2.0, 2.0), (2.0, -2.0)), False, - "Not same side of vertical line"); - Assert - (Centroid (((0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0))), - (0.5, 0.5), - "Centroid of rectangle"); - Assert - (Centroid (((0.0, 0.0), (1.0, 0.0), (0.0, 1.0))), - (1.0 / 3.0, 1.0 / 3.0), - "Centroid of triangle"); - Assert_Intersect_Triangle - (((0.0, 0.0), (1.0, 0.0), (0.0, 1.0)), - ((0.5, 0.0), (1.5, 0.0), (0.5, 1.0)), - True, "Intersection of two triangles"); - Assert_Intersect_Triangle - (((0.0, 0.0), (1.0, 0.0), (0.0, 1.0)), - ((1.0, 0.0), (2.0, 0.0), (1.0, 1.0)), - True, "Intersection with one common vertex"); - Assert_Intersect_Triangle - (((0.0, 0.0), (1.0, 0.0), (0.0, 1.0)), - ((1.1, 0.0), (2.1, 0.0), (1.1, 1.0)), - False, "No Intersection"); - Assert_Intersect_Rectangle - (((0.0, 0.0), (1.0, 1.0)), - ((0.5, 0.0), (1.5, 2.0)), - True, "Intersection of rectangles"); - Assert_Intersect_Rectangle - (((0.0, 0.0), (1.0, 1.0)), - ((0.5, 1.0), (1.5, 2.0)), - True, "Intersection of rectangles with common edge"); - Assert_Intersect_Rectangle - (((0.0, 0.0), (1.0, 1.0)), - ((0.5, 1.1), (1.5, 2.0)), - False, "No intersection of rectangles"); - - -- From the documentation of Boost geometry - -- http://geometrylibrary.geodan.nl/ - - declare - P1 : constant Point := (1.0, 1.0); - P2 : constant Point := (2.0, 3.0); - P3 : constant Point := (3.7, 2.0); - P : constant Polygon := - ((2.0, 1.3), (4.1, 3.0), (5.3, 2.6), (2.9, 0.7)); - begin - Assert (2.23607, Distance (P1, P2), "Distance P1-P2"); - Assert (3.015, Area (P), "Area of polygon"); - A.Assert (Inside (P3, P), "Point inside polygon"); - Assert (1.04403, Distance (P1, P), "Distance point-polygon"); - end; - end Tests; - -begin - declare - subtype Coordinate is Float; - procedure Float_Tests is new Tests (Coordinate); - begin - Float_Tests; - end; - - -- Check we can instantiate with more restricted types - - declare - type Coordinate is digits 1 range -500.0 .. 500.0; - procedure Float_Tests is new Tests (Coordinate); - begin - Float_Tests; - end; - - declare - type Coordinate is digits 1 range -500.0 .. -200.0; - package Geom is new GNATCOLL.Geometry (Coordinate); - package Assertions is new Asserts (Coordinate, Geom); - use Geom, Assertions; - P1 : constant Point := (-401.0, -401.0); - P2 : constant Point := (-402.0, -403.0); - begin - Assert (2.23607, Distance (P1, P2), "Distance P1-P2"); - end; - - return A.Report; -end Test; - - diff -Nru libgnatcoll-18/testsuite/tests/geometry/test.yaml libgnatcoll-19/testsuite/tests/geometry/test.yaml --- libgnatcoll-18/testsuite/tests/geometry/test.yaml 2018-03-05 13:06:25.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/geometry/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -description: Test for GNATCOLL.Geometry diff -Nru libgnatcoll-18/testsuite/tests/json/integer_number/test.adb libgnatcoll-19/testsuite/tests/json/integer_number/test.adb --- libgnatcoll-18/testsuite/tests/json/integer_number/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/integer_number/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,28 +0,0 @@ -with Ada.Text_IO; -with GNATCOLL.JSON; -with Test_Assert; - -function Test return Integer is - - package A renames Test_Assert; - package JSON renames GNATCOLL.JSON; - - use type JSON.JSON_Value_Type; - - Content : constant String := "14"; -begin - declare - Value : JSON.JSON_Value := JSON.Read - (Strm => Content, - Filename => ""); - Result : Integer; - Result2 : JSON.JSON_Value; - begin - A.Assert (True, "passed"); - A.Assert (JSON.Kind (Value) = JSON.JSON_Int_Type, - "check if type is JSON_Int_Type (got " & JSON.Kind (Value)'Img & ")"); - Result := JSON.Get (Value); - A.Assert (Result = 14, "check that result is equal to 14"); - end; - return A.Report; -end Test; diff -Nru libgnatcoll-18/testsuite/tests/json/integer_number/test.yaml libgnatcoll-19/testsuite/tests/json/integer_number/test.yaml --- libgnatcoll-18/testsuite/tests/json/integer_number/test.yaml 2018-03-28 07:43:17.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/integer_number/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -Description: Ensure that obvious integers are not converted to float diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_1_true_without_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_1_true_without_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_1_true_without_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_1_true_without_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1 true] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_a_invalid_utf8.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_a_invalid_utf8.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_a_invalid_utf8.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_a_invalid_utf8.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[a] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_colon_instead_of_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_colon_instead_of_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_colon_instead_of_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_colon_instead_of_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["": 1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_comma_after_close.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_comma_after_close.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_comma_after_close.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_comma_after_close.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[""], \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_comma_and_number.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_comma_and_number.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_comma_and_number.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_comma_and_number.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[,1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_double_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_double_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_double_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_double_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1,,2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_double_extra_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_double_extra_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_double_extra_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_double_extra_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["x",,] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_extra_close.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_extra_close.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_extra_close.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_extra_close.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["x"]] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_extra_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_extra_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_extra_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_extra_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["",] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_incomplete_invalid_value.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_incomplete_invalid_value.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_incomplete_invalid_value.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_incomplete_invalid_value.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[x \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_incomplete.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_incomplete.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_incomplete.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_incomplete.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["x" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_inner_array_no_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_inner_array_no_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_inner_array_no_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_inner_array_no_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[3[4]] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_invalid_utf8.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_invalid_utf8.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_invalid_utf8.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_invalid_utf8.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_items_separated_by_semicolon.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_items_separated_by_semicolon.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_items_separated_by_semicolon.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_items_separated_by_semicolon.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1:2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_just_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_just_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_just_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_just_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[,] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_just_minus.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_just_minus.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_just_minus.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_just_minus.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_missing_value.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_missing_value.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_missing_value.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_missing_value.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ , ""] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_newlines_unclosed.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_newlines_unclosed.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_newlines_unclosed.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_newlines_unclosed.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -["a", -4 -,1, \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_number_and_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_number_and_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_number_and_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_number_and_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1,] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_number_and_several_commas.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_number_and_several_commas.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_number_and_several_commas.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_number_and_several_commas.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1,,] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_spaces_vertical_tab_formfeed.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_spaces_vertical_tab_formfeed.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_spaces_vertical_tab_formfeed.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_spaces_vertical_tab_formfeed.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[" a"\f] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_star_inside.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_star_inside.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_star_inside.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_star_inside.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[*] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed_trailing_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed_trailing_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed_trailing_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed_trailing_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1, \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed_with_new_lines.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed_with_new_lines.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed_with_new_lines.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed_with_new_lines.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -[1, -1 -,1 \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed_with_object_inside.json libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed_with_object_inside.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_array_unclosed_with_object_inside.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_array_unclosed_with_object_inside.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[{} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_false.json libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_false.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_false.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_false.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[fals] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_null.json libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_null.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[nul] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_null_token.json libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_null_token.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_null_token.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_null_token.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -nu \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_true.json libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_true.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_incomplete_true.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_incomplete_true.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[tru] \ No newline at end of file Binary files /tmp/tmp_lBYMo/EL1mHvlt7O/libgnatcoll-18/testsuite/tests/json/invalid/n_multidigit_number_then_00.json and /tmp/tmp_lBYMo/wbl3aIt2po/libgnatcoll-19/testsuite/tests/json/invalid/n_multidigit_number_then_00.json differ diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_multiple_tokens.json libgnatcoll-19/testsuite/tests/json/invalid/n_multiple_tokens.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_multiple_tokens.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_multiple_tokens.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -truetrue diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.1.2.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.1.2.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.1.2.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.1.2.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0.1.2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_-01.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_-01.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_-01.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_-01.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-01] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.3e.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.3e.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.3e.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.3e.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0.3e] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.3e+.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.3e+.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.3e+.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.3e+.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0.3e+] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0_capital_E.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0_capital_E.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0_capital_E.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0_capital_E.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0E] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0_capital_E+.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0_capital_E+.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0_capital_E+.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0_capital_E+.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0E+] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.e1.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.e1.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0.e1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0.e1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0.e1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0e.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0e.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0e.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0e.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0e] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_0e+.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_0e+.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_0e+.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_0e+.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0e+] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_1_000.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_1_000.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_1_000.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_1_000.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1 000.0] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_1.0e-.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_1.0e-.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_1.0e-.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_1.0e-.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1.0e-] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_1.0e.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_1.0e.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_1.0e.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_1.0e.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1.0e] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_1.0e+.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_1.0e+.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_1.0e+.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_1.0e+.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1.0e+] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_-1.0..json libgnatcoll-19/testsuite/tests/json/invalid/n_number_-1.0..json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_-1.0..json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_-1.0..json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-1.0.] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_1eE2.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_1eE2.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_1eE2.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_1eE2.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1eE2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_.-1.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_.-1.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_.-1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_.-1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[.-1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_+1.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_+1.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_+1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_+1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[+1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_.2e-3.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_.2e-3.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_.2e-3.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_.2e-3.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[.2e-3] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_2.e-3.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_2.e-3.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_2.e-3.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_2.e-3.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[2.e-3] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_2.e+3.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_2.e+3.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_2.e+3.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_2.e+3.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[2.e+3] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_2.e3.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_2.e3.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_2.e3.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_2.e3.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[2.e3] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_2e-.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_2e-.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_2e-.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_2e-.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -2e- \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_2E.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_2E.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_2E.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_2E.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -2E \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_-2..json libgnatcoll-19/testsuite/tests/json/invalid/n_number_-2..json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_-2..json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_-2..json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-2.] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_9.e+.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_9.e+.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_9.e+.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_9.e+.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[9.e+] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_expression.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_expression.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_expression.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_expression.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1+2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_hex_1_digit.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_hex_1_digit.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_hex_1_digit.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_hex_1_digit.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0x1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_hex_2_digits.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_hex_2_digits.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_hex_2_digits.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_hex_2_digits.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0x42] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_infinity.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_infinity.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_infinity.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_infinity.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[Infinity] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_+Inf.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_+Inf.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_+Inf.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_+Inf.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[+Inf] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_Inf.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_Inf.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_Inf.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_Inf.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[Inf] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid+-.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid+-.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid+-.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid+-.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0e+-1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-negative-real.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-negative-real.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-negative-real.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-negative-real.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-123.123foo] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-bigger-int.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-bigger-int.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-bigger-int.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-bigger-int.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[123] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-exponent.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-exponent.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-exponent.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-exponent.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1e1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-int.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-int.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-int.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_invalid-utf-8-in-int.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0] diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_-.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_-.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_-.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_-.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -- \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_++.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_++.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_++.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_++.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[++1234] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_minus_infinity.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_minus_infinity.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_minus_infinity.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_minus_infinity.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-Infinity] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_minus_sign_with_trailing_garbage.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_minus_sign_with_trailing_garbage.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_minus_sign_with_trailing_garbage.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_minus_sign_with_trailing_garbage.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-foo] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_minus_space_1.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_minus_space_1.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_minus_space_1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_minus_space_1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[- 1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_-NaN.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_-NaN.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_-NaN.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_-NaN.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-NaN] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_NaN.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_NaN.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_NaN.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_NaN.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[NaN] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_neg_int_starting_with_zero.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_neg_int_starting_with_zero.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_neg_int_starting_with_zero.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_neg_int_starting_with_zero.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-012] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_neg_real_without_int_part.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_neg_real_without_int_part.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_neg_real_without_int_part.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_neg_real_without_int_part.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-.123] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_neg_with_garbage_at_end.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_neg_with_garbage_at_end.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_neg_with_garbage_at_end.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_neg_with_garbage_at_end.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-1x] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_real_garbage_after_e.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_real_garbage_after_e.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_real_garbage_after_e.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_real_garbage_after_e.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1ea] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_real_with_invalid_utf8_after_e.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_real_with_invalid_utf8_after_e.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_real_with_invalid_utf8_after_e.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_real_with_invalid_utf8_after_e.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1e] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_real_without_fractional_part.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_real_without_fractional_part.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_real_without_fractional_part.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_real_without_fractional_part.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1.] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_starting_with_dot.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_starting_with_dot.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_starting_with_dot.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_starting_with_dot.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[.123] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_U+FF11_fullwidth_digit_one.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_U+FF11_fullwidth_digit_one.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_U+FF11_fullwidth_digit_one.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_U+FF11_fullwidth_digit_one.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_with_alpha_char.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_with_alpha_char.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_with_alpha_char.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_with_alpha_char.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1.8011670033376514H-308] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_with_alpha.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_with_alpha.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_with_alpha.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_with_alpha.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1.2a-3] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_number_with_leading_zero.json libgnatcoll-19/testsuite/tests/json/invalid/n_number_with_leading_zero.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_number_with_leading_zero.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_number_with_leading_zero.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[012] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_bad_value.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_bad_value.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_bad_value.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_bad_value.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["x", truth] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_bracket_key.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_bracket_key.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_bracket_key.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_bracket_key.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{[: "x"} diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_comma_instead_of_colon.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_comma_instead_of_colon.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_comma_instead_of_colon.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_comma_instead_of_colon.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"x", null} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_double_colon.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_double_colon.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_double_colon.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_double_colon.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"x"::"b"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_emoji.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_emoji.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_emoji.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_emoji.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{🇨🇭} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_garbage_at_end.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_garbage_at_end.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_garbage_at_end.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_garbage_at_end.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"a" 123} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_key_with_single_quotes.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_key_with_single_quotes.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_key_with_single_quotes.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_key_with_single_quotes.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{key: 'value'} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_colon.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_colon.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_colon.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_colon.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a" b} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_key.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_key.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_key.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_key.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{:"b"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_semicolon.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_semicolon.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_semicolon.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_semicolon.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a" "b"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_value.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_value.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_missing_value.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_missing_value.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a": \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_no-colon.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_no-colon.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_no-colon.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_no-colon.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_non_string_key_but_huge_number_instead.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_non_string_key_but_huge_number_instead.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_non_string_key_but_huge_number_instead.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_non_string_key_but_huge_number_instead.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{9999E9999:1} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_non_string_key.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_non_string_key.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_non_string_key.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_non_string_key.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{1:1} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_pi_in_key_and_trailing_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_pi_in_key_and_trailing_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_pi_in_key_and_trailing_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_pi_in_key_and_trailing_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"":"0",} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_repeated_null_null.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_repeated_null_null.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_repeated_null_null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_repeated_null_null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{null:null,null:null} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_several_trailing_commas.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_several_trailing_commas.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_several_trailing_commas.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_several_trailing_commas.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"id":0,,,,,} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_single_quote.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_single_quote.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_single_quote.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_single_quote.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{'a':0} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"id":0,} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b"}/**/ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment_open.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment_open.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment_open.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment_open.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b"}/**// \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open_incomplete.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open_incomplete.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open_incomplete.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open_incomplete.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b"}/ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_trailing_comment_slash_open.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b"}// \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_two_commas_in_a_row.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_two_commas_in_a_row.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_two_commas_in_a_row.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_two_commas_in_a_row.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b",,"c":"d"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_unquoted_key.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_unquoted_key.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_unquoted_key.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_unquoted_key.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{a: "b"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_unterminated-value.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_unterminated-value.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_unterminated-value.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_unterminated-value.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"a \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_with_single_string.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_with_single_string.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_with_single_string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_with_single_string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{ "foo" : "bar", "a" } \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_object_with_trailing_garbage.json libgnatcoll-19/testsuite/tests/json/invalid/n_object_with_trailing_garbage.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_object_with_trailing_garbage.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_object_with_trailing_garbage.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b"}# \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_single_space.json libgnatcoll-19/testsuite/tests/json/invalid/n_single_space.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_single_space.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_single_space.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD800\"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD800\u1"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1x.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1x.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1x.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u1x.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD800\u1x"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_1_surrogate_then_escape_u.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD800\u"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_accentuated_char_no_quotes.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_accentuated_char_no_quotes.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_accentuated_char_no_quotes.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_accentuated_char_no_quotes.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[é] \ No newline at end of file Binary files /tmp/tmp_lBYMo/EL1mHvlt7O/libgnatcoll-18/testsuite/tests/json/invalid/n_string_backslash_00.json and /tmp/tmp_lBYMo/wbl3aIt2po/libgnatcoll-19/testsuite/tests/json/invalid/n_string_backslash_00.json differ diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_escaped_backslash_bad.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_escaped_backslash_bad.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_escaped_backslash_bad.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_escaped_backslash_bad.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\\\"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_escaped_ctrl_char_tab.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_escaped_ctrl_char_tab.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_escaped_ctrl_char_tab.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_escaped_ctrl_char_tab.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\ "] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_escaped_emoji.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_escaped_emoji.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_escaped_emoji.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_escaped_emoji.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\🌀"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_escape_x.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_escape_x.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_escape_x.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_escape_x.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\x00"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_escaped_character.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_escaped_character.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_escaped_character.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_escaped_character.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u00A"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_escape.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_escape.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_escape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_escape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_surrogate_escape_invalid.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_surrogate_escape_invalid.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_surrogate_escape_invalid.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_surrogate_escape_invalid.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD800\uD800\x"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_surrogate.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_surrogate.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_incomplete_surrogate.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_incomplete_surrogate.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD834\uDd"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid_backslash_esc.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid_backslash_esc.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid_backslash_esc.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid_backslash_esc.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\a"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid_unicode_escape.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid_unicode_escape.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid_unicode_escape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid_unicode_escape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uqqqq"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid_utf8_after_escape.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid_utf8_after_escape.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid_utf8_after_escape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid_utf8_after_escape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid-utf-8-in-escape.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid-utf-8-in-escape.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_invalid-utf-8-in-escape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_invalid-utf-8-in-escape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_leading_uescaped_thinspace.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_leading_uescaped_thinspace.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_leading_uescaped_thinspace.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_leading_uescaped_thinspace.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[\u0020"asd"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_no_quotes_with_bad_escape.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_no_quotes_with_bad_escape.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_no_quotes_with_bad_escape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_no_quotes_with_bad_escape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[\n] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_single_doublequote.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_single_doublequote.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_single_doublequote.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_single_doublequote.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_single_quote.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_single_quote.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_single_quote.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_single_quote.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -['single quote'] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_single_string_no_double_quotes.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_single_string_no_double_quotes.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_single_string_no_double_quotes.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_single_string_no_double_quotes.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -abc \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_start_escape_unclosed.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_start_escape_unclosed.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_start_escape_unclosed.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_start_escape_unclosed.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\ \ No newline at end of file Binary files /tmp/tmp_lBYMo/EL1mHvlt7O/libgnatcoll-18/testsuite/tests/json/invalid/n_string_unescaped_crtl_char.json and /tmp/tmp_lBYMo/wbl3aIt2po/libgnatcoll-19/testsuite/tests/json/invalid/n_string_unescaped_crtl_char.json differ diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_unescaped_newline.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_unescaped_newline.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_unescaped_newline.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_unescaped_newline.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -["new -line"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_unescaped_tab.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_unescaped_tab.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_unescaped_tab.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_unescaped_tab.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[" "] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_unicode_CapitalU.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_unicode_CapitalU.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_unicode_CapitalU.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_unicode_CapitalU.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -"\UA66D" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_string_with_trailing_garbage.json libgnatcoll-19/testsuite/tests/json/invalid/n_string_with_trailing_garbage.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_string_with_trailing_garbage.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_string_with_trailing_garbage.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -""x \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_100000_opening_arrays.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_100000_opening_arrays.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_100000_opening_arrays.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_100000_opening_arrays.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_angle_bracket_..json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_angle_bracket_..json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_angle_bracket_..json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_angle_bracket_..json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -<.> \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_angle_bracket_null.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_angle_bracket_null.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_angle_bracket_null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_angle_bracket_null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_array_trailing_garbage.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_array_trailing_garbage.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_array_trailing_garbage.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_array_trailing_garbage.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1]x \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_array_with_extra_array_close.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_array_with_extra_array_close.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_array_with_extra_array_close.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_array_with_extra_array_close.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1]] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_array_with_unclosed_string.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_array_with_unclosed_string.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_array_with_unclosed_string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_array_with_unclosed_string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["asd] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_ascii-unicode-identifier.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_ascii-unicode-identifier.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_ascii-unicode-identifier.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_ascii-unicode-identifier.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -aå \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_capitalized_True.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_capitalized_True.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_capitalized_True.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_capitalized_True.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[True] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_close_unopened_array.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_close_unopened_array.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_close_unopened_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_close_unopened_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_comma_instead_of_closing_brace.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_comma_instead_of_closing_brace.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_comma_instead_of_closing_brace.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_comma_instead_of_closing_brace.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"x": true, \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_double_array.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_double_array.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_double_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_double_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[][] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_end_array.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_end_array.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_end_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_end_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_incomplete_UTF8_BOM.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_incomplete_UTF8_BOM.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_incomplete_UTF8_BOM.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_incomplete_UTF8_BOM.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_lone-invalid-utf-8.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_lone-invalid-utf-8.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_lone-invalid-utf-8.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_lone-invalid-utf-8.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_lone-open-bracket.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_lone-open-bracket.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_lone-open-bracket.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_lone-open-bracket.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ \ No newline at end of file Binary files /tmp/tmp_lBYMo/EL1mHvlt7O/libgnatcoll-18/testsuite/tests/json/invalid/n_structure_null-byte-outside-string.json and /tmp/tmp_lBYMo/wbl3aIt2po/libgnatcoll-19/testsuite/tests/json/invalid/n_structure_null-byte-outside-string.json differ diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_number_with_trailing_garbage.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_number_with_trailing_garbage.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_number_with_trailing_garbage.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_number_with_trailing_garbage.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -2@ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_followed_by_closing_object.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_followed_by_closing_object.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_followed_by_closing_object.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_followed_by_closing_object.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{}} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_unclosed_no_value.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_unclosed_no_value.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_unclosed_no_value.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_unclosed_no_value.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"": \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_with_comment.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_with_comment.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_with_comment.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_with_comment.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":/*comment*/"b"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_with_trailing_garbage.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_with_trailing_garbage.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_object_with_trailing_garbage.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_object_with_trailing_garbage.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a": true} "x" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_apostrophe.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_apostrophe.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_apostrophe.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_apostrophe.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[' \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[, \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_object.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_object.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_object.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_object.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"": diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_open_object.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_open_object.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_open_object.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_open_object.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[{ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_open_string.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_open_string.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_open_string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_open_string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["a \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_string.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_string.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_array_string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_array_string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["a" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_close_array.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_close_array.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_close_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_close_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_comma.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_comma.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_comma.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_comma.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{, \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_open_array.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_open_array.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_open_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_open_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{[ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_open_string.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_open_string.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_open_string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_open_string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_string_with_apostrophes.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_string_with_apostrophes.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_object_string_with_apostrophes.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_object_string_with_apostrophes.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{'a' \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_open.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_open.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_open_open.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_open_open.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\{["\{["\{["\{ \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_single_eacute.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_single_eacute.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_single_eacute.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_single_eacute.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_single_star.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_single_star.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_single_star.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_single_star.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -* \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_trailing_#.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_trailing_#.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_trailing_#.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_trailing_#.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b"}#{} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_U+2060_word_joined.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_U+2060_word_joined.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_U+2060_word_joined.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_U+2060_word_joined.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[⁠] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_uescaped_LF_before_string.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_uescaped_LF_before_string.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_uescaped_LF_before_string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_uescaped_LF_before_string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[\u000A""] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1 \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array_partial_null.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array_partial_null.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array_partial_null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array_partial_null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ false, nul \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_false.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_false.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_false.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_false.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ true, fals \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_true.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_true.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_true.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_array_unfinished_true.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ false, tru \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_object.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_object.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unclosed_object.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unclosed_object.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"asd":"asd" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unicode-identifier.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unicode-identifier.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_unicode-identifier.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_unicode-identifier.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -å \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_UTF8_BOM_no_data.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_UTF8_BOM_no_data.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_UTF8_BOM_no_data.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_UTF8_BOM_no_data.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_whitespace_formfeed.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_whitespace_formfeed.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_whitespace_formfeed.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_whitespace_formfeed.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ ] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/n_structure_whitespace_U+2060_word_joiner.json libgnatcoll-19/testsuite/tests/json/invalid/n_structure_whitespace_U+2060_word_joiner.json --- libgnatcoll-18/testsuite/tests/json/invalid/n_structure_whitespace_U+2060_word_joiner.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/n_structure_whitespace_U+2060_word_joiner.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[⁠] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/test.adb libgnatcoll-19/testsuite/tests/json/invalid/test.adb --- libgnatcoll-18/testsuite/tests/json/invalid/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,35 +0,0 @@ -with Test_Assert; -with GNATCOLL.JSON; -with GNATCOLL.VFS; -with GNAT.Strings; -with Ada.Command_Line; -with Ada.Exceptions; - -function Test return Integer is - package A renames Test_Assert; - package JSON renames GNATCOLL.JSON; - package VFS renames GNATCOLL.VFS; - - procedure Test (JSON_String : String); - - procedure Test (JSON_String : String) is - begin - declare - V : JSON.JSON_Value; - begin - V := JSON.Read(JSON_String); - A.Assert (False, "invalid json (exception not raised)"); - exception - when JSON.Invalid_JSON_Stream => - A.Assert (True, "failed with Invalid_JSON_Stream"); - when E : others => - A.Assert (False, "invalid json: (wrong exception)" & ASCII.LF & - Ada.Exceptions.Exception_Information (E)); - end; - end Test; - - File_Content : GNAT.Strings.String_Access := VFS.Read_File (VFS.Create(VFS."+"(Ada.Command_Line.Argument (1)))); -begin - Test (File_Content.all); - return A.Report; -end Test; diff -Nru libgnatcoll-18/testsuite/tests/json/invalid/test.yaml libgnatcoll-19/testsuite/tests/json/invalid/test.yaml --- libgnatcoll-18/testsuite/tests/json/invalid/test.yaml 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/invalid/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1,194 +0,0 @@ -description: Check behavior of JSON parser on invalid JSON -driver: data_validation -data_files: - "n_array_1_true_without_comma.json": "n array 1 true without comma" - "n_array_a_invalid_utf8.json": "n array a invalid utf8" - "n_array_colon_instead_of_comma.json": "n array colon instead of comma" - "n_array_comma_after_close.json": "n array comma after close" - "n_array_comma_and_number.json": "n array comma and number" - "n_array_double_comma.json": "n array double comma" - "n_array_double_extra_comma.json": "n array double extra comma" - "n_array_extra_close.json": "n array extra close" - "n_array_extra_comma.json": "n array extra comma" - "n_array_incomplete.json": "n array incomplete" - "n_array_incomplete_invalid_value.json": "n array incomplete invalid value" - "n_array_inner_array_no_comma.json": "n array inner array no comma" - "n_array_invalid_utf8.json": "n array invalid utf8" - "n_array_items_separated_by_semicolon.json": "n array items separated by semicolon" - "n_array_just_comma.json": "n array just comma" - "n_array_just_minus.json": "n array just minus" - "n_array_missing_value.json": "n array missing value" - "n_array_newlines_unclosed.json": "n array newlines unclosed" - "n_array_number_and_comma.json": "n array number and comma" - "n_array_number_and_several_commas.json": "n array number and several commas" - "n_array_spaces_vertical_tab_formfeed.json": "n array spaces vertical tab formfeed" - "n_array_star_inside.json": "n array star inside" - "n_array_unclosed.json": "n array unclosed" - "n_array_unclosed_trailing_comma.json": "n array unclosed trailing comma" - "n_array_unclosed_with_new_lines.json": "n array unclosed with new lines" - "n_array_unclosed_with_object_inside.json": "n array unclosed with object inside" - "n_incomplete_false.json": "n incomplete false" - "n_incomplete_null.json": "n incomplete null" - "n_incomplete_true.json": "n incomplete true" - "n_multidigit_number_then_00.json": "n multidigit number then 00" - "n_number_++.json": "n number ++" - "n_number_-.json": "n number -" - "n_number_2E.json": "n number 2E" - "n_number_2e-.json": "n number 2e-" - "n_number_+1.json": "n number +1" - "n_number_+Inf.json": "n number +Inf" - "n_number_-01.json": "n number -01" - "n_number_-1.0..json": "n number -1.0." - "n_number_-2..json": "n number -2." - "n_number_-NaN.json": "n number -NaN" - "n_number_.-1.json": "n number .-1" - "n_number_.2e-3.json": "n number .2e-3" - "n_number_0.1.2.json": "n number 0.1.2" - "n_number_0.3e+.json": "n number 0.3e+" - "n_number_0.3e.json": "n number 0.3e" - "n_number_0.e1.json": "n number 0.e1" - "n_number_0_capital_E+.json": "n number 0 capital E+" - "n_number_0_capital_E.json": "n number 0 capital E" - "n_number_0e+.json": "n number 0e+" - "n_number_0e.json": "n number 0e" - "n_number_1.0e+.json": "n number 1.0e+" - "n_number_1.0e-.json": "n number 1.0e-" - "n_number_1.0e.json": "n number 1.0e" - "n_number_1_000.json": "n number 1 000" - "n_number_1eE2.json": "n number 1eE2" - "n_number_2.e+3.json": "n number 2.e+3" - "n_number_2.e-3.json": "n number 2.e-3" - "n_number_2.e3.json": "n number 2.e3" - "n_number_9.e+.json": "n number 9.e+" - "n_number_Inf.json": "n number Inf" - "n_number_NaN.json": "n number NaN" - "n_number_U+FF11_fullwidth_digit_one.json": "n number U+FF11 fullwidth digit one" - "n_number_expression.json": "n number expression" - "n_number_hex_1_digit.json": "n number hex 1 digit" - "n_number_hex_2_digits.json": "n number hex 2 digits" - "n_number_infinity.json": "n number infinity" - "n_number_invalid+-.json": "n number invalid+-" - "n_number_invalid-negative-real.json": "n number invalid-negative-real" - "n_number_invalid-utf-8-in-bigger-int.json": "n number invalid-utf-8-in-bigger-int" - "n_number_invalid-utf-8-in-exponent.json": "n number invalid-utf-8-in-exponent" - "n_number_invalid-utf-8-in-int.json": "n number invalid-utf-8-in-int" - "n_number_minus_infinity.json": "n number minus infinity" - "n_number_minus_sign_with_trailing_garbage.json": "n number minus sign with trailing garbage" - "n_number_minus_space_1.json": "n number minus space 1" - "n_number_neg_int_starting_with_zero.json": "n number neg int starting with zero" - "n_number_neg_real_without_int_part.json": "n number neg real without int part" - "n_number_neg_with_garbage_at_end.json": "n number neg with garbage at end" - "n_number_real_garbage_after_e.json": "n number real garbage after e" - "n_number_real_with_invalid_utf8_after_e.json": "n number real with invalid utf8 after e" - "n_number_real_without_fractional_part.json": "n number real without fractional part" - "n_number_starting_with_dot.json": "n number starting with dot" - "n_number_with_alpha.json": "n number with alpha" - "n_number_with_alpha_char.json": "n number with alpha char" - "n_number_with_leading_zero.json": "n number with leading zero" - "n_object_bad_value.json": "n object bad value" - "n_object_bracket_key.json": "n object bracket key" - "n_object_comma_instead_of_colon.json": "n object comma instead of colon" - "n_object_double_colon.json": "n object double colon" - "n_object_emoji.json": "n object emoji" - "n_object_garbage_at_end.json": "n object garbage at end" - "n_object_key_with_single_quotes.json": "n object key with single quotes" - "n_object_missing_colon.json": "n object missing colon" - "n_object_missing_key.json": "n object missing key" - "n_object_missing_semicolon.json": "n object missing semicolon" - "n_object_missing_value.json": "n object missing value" - "n_object_no-colon.json": "n object no-colon" - "n_object_non_string_key.json": "n object non string key" - "n_object_non_string_key_but_huge_number_instead.json": "n object non string key but huge number instead" - "n_object_pi_in_key_and_trailing_comma.json": "n object pi in key and trailing comma" - "n_object_repeated_null_null.json": "n object repeated null null" - "n_object_several_trailing_commas.json": "n object several trailing commas" - "n_object_single_quote.json": "n object single quote" - "n_object_trailing_comma.json": "n object trailing comma" - "n_object_trailing_comment.json": "n object trailing comment" - "n_object_trailing_comment_open.json": "n object trailing comment open" - "n_object_trailing_comment_slash_open.json": "n object trailing comment slash open" - "n_object_trailing_comment_slash_open_incomplete.json": "n object trailing comment slash open incomplete" - "n_object_two_commas_in_a_row.json": "n object two commas in a row" - "n_object_unquoted_key.json": "n object unquoted key" - "n_object_unterminated-value.json": "n object unterminated-value" - "n_object_with_single_string.json": "n object with single string" - "n_object_with_trailing_garbage.json": "n object with trailing garbage" - "n_single_space.json": "n single space" - "n_string_1_surrogate_then_escape.json": "n string 1 surrogate then escape" - "n_string_1_surrogate_then_escape_u.json": "n string 1 surrogate then escape u" - "n_string_1_surrogate_then_escape_u1.json": "n string 1 surrogate then escape u1" - "n_string_1_surrogate_then_escape_u1x.json": "n string 1 surrogate then escape u1x" - "n_string_accentuated_char_no_quotes.json": "n string accentuated char no quotes" - "n_string_backslash_00.json": "n string backslash 00" - "n_string_escape_x.json": "n string escape x" - "n_string_escaped_backslash_bad.json": "n string escaped backslash bad" - "n_string_escaped_ctrl_char_tab.json": "n string escaped ctrl char tab" - "n_string_escaped_emoji.json": "n string escaped emoji" - "n_string_incomplete_escape.json": "n string incomplete escape" - "n_string_incomplete_escaped_character.json": "n string incomplete escaped character" - "n_string_incomplete_surrogate.json": "n string incomplete surrogate" - "n_string_incomplete_surrogate_escape_invalid.json": "n string incomplete surrogate escape invalid" - "n_string_invalid-utf-8-in-escape.json": "n string invalid-utf-8-in-escape" - "n_string_invalid_backslash_esc.json": "n string invalid backslash esc" - "n_string_invalid_unicode_escape.json": "n string invalid unicode escape" - "n_string_invalid_utf8_after_escape.json": "n string invalid utf8 after escape" - "n_string_leading_uescaped_thinspace.json": "n string leading uescaped thinspace" - "n_string_no_quotes_with_bad_escape.json": "n string no quotes with bad escape" - "n_string_single_doublequote.json": "n string single doublequote" - "n_string_single_quote.json": "n string single quote" - "n_string_single_string_no_double_quotes.json": "n string single string no double quotes" - "n_string_start_escape_unclosed.json": "n string start escape unclosed" - "n_string_unescaped_crtl_char.json": "n string unescaped crtl char" - "n_string_unescaped_newline.json": "n string unescaped newline" - "n_string_unescaped_tab.json": "n string unescaped tab" - "n_string_unicode_CapitalU.json": "n string unicode CapitalU" - "n_string_with_trailing_garbage.json": "n string with trailing garbage" - "n_structure_U+2060_word_joined.json": "n structure U+2060 word joined" - "n_structure_UTF8_BOM_no_data.json": "n structure UTF8 BOM no data" - "n_structure_angle_bracket_..json": "n structure angle bracket ." - "n_structure_angle_bracket_null.json": "n structure angle bracket null" - "n_structure_array_trailing_garbage.json": "n structure array trailing garbage" - "n_structure_array_with_extra_array_close.json": "n structure array with extra array close" - "n_structure_array_with_unclosed_string.json": "n structure array with unclosed string" - "n_structure_ascii-unicode-identifier.json": "n structure ascii-unicode-identifier" - "n_structure_capitalized_True.json": "n structure capitalized True" - "n_structure_close_unopened_array.json": "n structure close unopened array" - "n_structure_comma_instead_of_closing_brace.json": "n structure comma instead of closing brace" - "n_structure_double_array.json": "n structure double array" - "n_structure_end_array.json": "n structure end array" - "n_structure_incomplete_UTF8_BOM.json": "n structure incomplete UTF8 BOM" - "n_structure_lone-invalid-utf-8.json": "n structure lone-invalid-utf-8" - "n_structure_lone-open-bracket.json": "n structure lone-open-bracket" - "n_structure_no_data.json": "n structure no data" - "n_structure_null-byte-outside-string.json": "n structure null-byte-outside-string" - "n_structure_number_with_trailing_garbage.json": "n structure number with trailing garbage" - "n_structure_object_followed_by_closing_object.json": "n structure object followed by closing object" - "n_structure_object_unclosed_no_value.json": "n structure object unclosed no value" - "n_structure_object_with_comment.json": "n structure object with comment" - "n_structure_object_with_trailing_garbage.json": "n structure object with trailing garbage" - "n_structure_open_array_apostrophe.json": "n structure open array apostrophe" - "n_structure_open_array_comma.json": "n structure open array comma" - "n_structure_open_array_open_object.json": "n structure open array open object" - "n_structure_open_array_open_string.json": "n structure open array open string" - "n_structure_open_array_string.json": "n structure open array string" - "n_structure_open_object.json": "n structure open object" - "n_structure_open_object_close_array.json": "n structure open object close array" - "n_structure_open_object_comma.json": "n structure open object comma" - "n_structure_open_object_open_array.json": "n structure open object open array" - "n_structure_open_object_open_string.json": "n structure open object open string" - "n_structure_open_object_string_with_apostrophes.json": "n structure open object string with apostrophes" - "n_structure_open_open.json": "n structure open open" - "n_structure_single_eacute.json": "n structure single eacute" - "n_structure_single_star.json": "n structure single star" - "n_structure_trailing_#.json": "n structure trailing #" - "n_structure_uescaped_LF_before_string.json": "n structure uescaped LF before string" - "n_structure_unclosed_array.json": "n structure unclosed array" - "n_structure_unclosed_array_partial_null.json": "n structure unclosed array partial null" - "n_structure_unclosed_array_unfinished_false.json": "n structure unclosed array unfinished false" - "n_structure_unclosed_array_unfinished_true.json": "n structure unclosed array unfinished true" - "n_structure_unclosed_object.json": "n structure unclosed object" - "n_structure_unicode-identifier.json": "n structure unicode-identifier" - "n_structure_whitespace_U+2060_word_joiner.json": "n structure whitespace U+2060 word joiner" - "n_structure_whitespace_formfeed.json": "n structure whitespace formfeed" - "n_multiple_tokens.json": "concatenated tokens" - "n_incomplete_null_token.json": "incomplete null token" diff -Nru libgnatcoll-18/testsuite/tests/json/validation/basic_object.json libgnatcoll-19/testsuite/tests/json/validation/basic_object.json --- libgnatcoll-18/testsuite/tests/json/validation/basic_object.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/basic_object.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,5 +0,0 @@ -{"a": 1, - "b": "a tringg", - "c": [1, 2, 3], - "d": {"a": "a"}, - "e": null} diff -Nru libgnatcoll-18/testsuite/tests/json/validation/false.json libgnatcoll-19/testsuite/tests/json/validation/false.json --- libgnatcoll-18/testsuite/tests/json/validation/false.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/false.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -false diff -Nru libgnatcoll-18/testsuite/tests/json/validation/keyword_seq.json libgnatcoll-19/testsuite/tests/json/validation/keyword_seq.json --- libgnatcoll-18/testsuite/tests/json/validation/keyword_seq.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/keyword_seq.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[true, false, null] diff -Nru libgnatcoll-18/testsuite/tests/json/validation/null.json libgnatcoll-19/testsuite/tests/json/validation/null.json --- libgnatcoll-18/testsuite/tests/json/validation/null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -null diff -Nru libgnatcoll-18/testsuite/tests/json/validation/numbers.json libgnatcoll-19/testsuite/tests/json/validation/numbers.json --- libgnatcoll-18/testsuite/tests/json/validation/numbers.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/numbers.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -[0, - 12345643, - 1E+2, - 1e-2, - -41, - -0, - 1.000, - 1E4, - 1e21, - 0.6E4, - -6] diff -Nru libgnatcoll-18/testsuite/tests/json/validation/string.json libgnatcoll-19/testsuite/tests/json/validation/string.json --- libgnatcoll-18/testsuite/tests/json/validation/string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -"Hello\n\r\t" diff -Nru libgnatcoll-18/testsuite/tests/json/validation/test1.json libgnatcoll-19/testsuite/tests/json/validation/test1.json --- libgnatcoll-18/testsuite/tests/json/validation/test1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/test1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{ } diff -Nru libgnatcoll-18/testsuite/tests/json/validation/test2.json libgnatcoll-19/testsuite/tests/json/validation/test2.json --- libgnatcoll-18/testsuite/tests/json/validation/test2.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/test2.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[] diff -Nru libgnatcoll-18/testsuite/tests/json/validation/test.adb libgnatcoll-19/testsuite/tests/json/validation/test.adb --- libgnatcoll-18/testsuite/tests/json/validation/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Command_Line; -with Ada.Text_IO; -with GNATCOLL.JSON; -with GNAT.OS_Lib; - -procedure Test is - - package JSON renames GNATCOLL.JSON; - package IO renames Ada.Text_IO; - - function Read_File (Filename : String) return Unbounded_String is - use GNAT.OS_Lib; - F : constant File_Descriptor := Open_Read (Filename, Binary); - Expected_Bytes_Read : Integer; - Bytes_Read : Integer; - begin - Expected_Bytes_Read := Integer (File_Length (F)); - - declare - Buffer_Str : aliased String (1 .. Expected_Bytes_Read); - begin - Bytes_Read := Read (F, Buffer_Str'Address, Expected_Bytes_Read); - Close (F); - - return To_Unbounded_String (Buffer_Str); - end; - end Read_File; - - -- Read json filename passed as first argument - Filename : constant String := Ada.Command_Line.Argument(1); - JSON_Data : Unbounded_String := Read_File (Filename); -begin - - -- Parse the json - declare - Value : JSON.JSON_Value := JSON.Read (Strm => JSON_Data, - Filename => Filename); - begin - -- Dump JSON back to stdout for validation by the python json - -- parser - declare - New_JSON_Data : constant Unbounded_String := - JSON.Write (Item => Value, Compact => False); - begin - Ada.Text_IO.Put_Line(To_String(New_JSON_Data)); - end; - end; -end Test; diff -Nru libgnatcoll-18/testsuite/tests/json/validation/test.yaml libgnatcoll-19/testsuite/tests/json/validation/test.yaml --- libgnatcoll-18/testsuite/tests/json/validation/test.yaml 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1,106 +0,0 @@ -driver: 'json_validation' -data_files: - test1.json: "Minimal test" - test2.json: "Minimal test2" - false.json: "null keyword" - null.json: "false keyword" - true.json: "true keyword" - keyword_seq.json: "an array of null, false and true" - basic_object.json: "a basic JSON object" - string.json: "a string with some escape sequences" - numbers.json: "an array of various kind of numbers" - "y_array_arraysWithSpaces.json": "y array arraysWithSpaces" - "y_array_empty-string.json": "y array empty-string" - "y_array_empty.json": "y array empty" - "y_array_ending_with_newline.json": "y array ending with newline" - "y_array_false.json": "y array false" - "y_array_heterogeneous.json": "y array heterogeneous" - "y_array_null.json": "y array null" - "y_array_with_1_and_newline.json": "y array with 1 and newline" - "y_array_with_leading_space.json": "y array with leading space" - "y_array_with_several_null.json": "y array with several null" - "y_array_with_trailing_space.json": "y array with trailing space" - "y_number.json": "y number" - "y_number_0e+1.json": "y number 0e+1" - "y_number_0e1.json": "y number 0e1" - "y_number_after_space.json": "y number after space" - "y_number_double_close_to_zero.json": "y number double close to zero" - "y_number_int_with_exp.json": "y number int with exp" - "y_number_minus_zero.json": "y number minus zero" - "y_number_negative_int.json": "y number negative int" - "y_number_negative_one.json": "y number negative one" - "y_number_negative_zero.json": "y number negative zero" - "y_number_real_capital_e.json": "y number real capital e" - "y_number_real_capital_e_neg_exp.json": "y number real capital e neg exp" - "y_number_real_capital_e_pos_exp.json": "y number real capital e pos exp" - "y_number_real_exponent.json": "y number real exponent" - "y_number_real_fraction_exponent.json": "y number real fraction exponent" - "y_number_real_neg_exp.json": "y number real neg exp" - "y_number_real_pos_exponent.json": "y number real pos exponent" - "y_number_simple_int.json": "y number simple int" - "y_number_simple_real.json": "y number simple real" - "y_object.json": "y object" - "y_object_basic.json": "y object basic" - "y_object_duplicated_key.json": "y object duplicated key" - "y_object_duplicated_key_and_value.json": "y object duplicated key and value" - "y_object_empty.json": "y object empty" - "y_object_empty_key.json": "y object empty key" - "y_object_escaped_null_in_key.json": "y object escaped null in key" - "y_object_extreme_numbers.json": "y object extreme numbers" - "y_object_long_strings.json": "y object long strings" - "y_object_simple.json": "y object simple" - "y_object_string_unicode.json": "y object string unicode" - "y_object_with_newlines.json": "y object with newlines" - "y_string_1_2_3_bytes_UTF-8_sequences.json": "y string 1 2 3 bytes UTF-8 sequences" - "y_string_accepted_surrogate_pair.json": "y string accepted surrogate pair" - "y_string_accepted_surrogate_pairs.json": "y string accepted surrogate pairs" - "y_string_allowed_escapes.json": "y string allowed escapes" - "y_string_backslash_and_u_escaped_zero.json": "y string backslash and u escaped zero" - "y_string_backslash_doublequotes.json": "y string backslash doublequotes" - "y_string_comments.json": "y string comments" - "y_string_double_escape_a.json": "y string double escape a" - "y_string_double_escape_n.json": "y string double escape n" - "y_string_escaped_control_character.json": "y string escaped control character" - "y_string_escaped_noncharacter.json": "y string escaped noncharacter" - "y_string_in_array.json": "y string in array" - "y_string_in_array_with_leading_space.json": "y string in array with leading space" - "y_string_last_surrogates_1_and_2.json": "y string last surrogates 1 and 2" - "y_string_nbsp_uescaped.json": "y string nbsp uescaped" - "y_string_nonCharacterInUTF-8_U+10FFFF.json": "y string nonCharacterInUTF-8 U+10FFFF" - "y_string_nonCharacterInUTF-8_U+1FFFF.json": "y string nonCharacterInUTF-8 U+1FFFF" - "y_string_nonCharacterInUTF-8_U+FFFF.json": "y string nonCharacterInUTF-8 U+FFFF" - "y_string_null_escape.json": "y string null escape" - "y_string_one-byte-utf-8.json": "y string one-byte-utf-8" - "y_string_pi.json": "y string pi" - "y_string_simple_ascii.json": "y string simple ascii" - "y_string_space.json": "y string space" - "y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json": "y string surrogates U+1D11E MUSICAL SYMBOL G CLEF" - "y_string_three-byte-utf-8.json": "y string three-byte-utf-8" - "y_string_two-byte-utf-8.json": "y string two-byte-utf-8" - "y_string_u+2028_line_sep.json": "y string u+2028 line sep" - "y_string_u+2029_par_sep.json": "y string u+2029 par sep" - "y_string_uEscape.json": "y string uEscape" - "y_string_uescaped_newline.json": "y string uescaped newline" - "y_string_unescaped_char_delete.json": "y string unescaped char delete" - "y_string_unicode.json": "y string unicode" - "y_string_unicodeEscapedBackslash.json": "y string unicodeEscapedBackslash" - "y_string_unicode_2.json": "y string unicode 2" - "y_string_unicode_U+10FFFE_nonchar.json": "y string unicode U+10FFFE nonchar" - "y_string_unicode_U+1FFFE_nonchar.json": "y string unicode U+1FFFE nonchar" - "y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json": "y string unicode U+200B ZERO WIDTH SPACE" - "y_string_unicode_U+2064_invisible_plus.json": "y string unicode U+2064 invisible plus" - "y_string_unicode_U+FDD0_nonchar.json": "y string unicode U+FDD0 nonchar" - "y_string_unicode_U+FFFE_nonchar.json": "y string unicode U+FFFE nonchar" - "y_string_unicode_escaped_double_quote.json": "y string unicode escaped double quote" - "y_string_utf8.json": "y string utf8" - "y_string_with_del_character.json": "y string with del character" - "y_structure_lonely_false.json": "y structure lonely false" - "y_structure_lonely_int.json": "y structure lonely int" - "y_structure_lonely_negative_real.json": "y structure lonely negative real" - "y_structure_lonely_null.json": "y structure lonely null" - "y_structure_lonely_string.json": "y structure lonely string" - "y_structure_lonely_true.json": "y structure lonely true" - "y_structure_string_empty.json": "y structure string empty" - "y_structure_trailing_newline.json": "y structure trailing newline" - "y_structure_true_in_array.json": "y structure true in array" - "y_structure_whitespace_array.json": "y structure whitespace array" diff -Nru libgnatcoll-18/testsuite/tests/json/validation/true.json libgnatcoll-19/testsuite/tests/json/validation/true.json --- libgnatcoll-18/testsuite/tests/json/validation/true.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/true.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -true diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_arraysWithSpaces.json libgnatcoll-19/testsuite/tests/json/validation/y_array_arraysWithSpaces.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_arraysWithSpaces.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_arraysWithSpaces.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[[] ] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_empty.json libgnatcoll-19/testsuite/tests/json/validation/y_array_empty.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_empty.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_empty.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_empty-string.json libgnatcoll-19/testsuite/tests/json/validation/y_array_empty-string.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_empty-string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_empty-string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[""] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_ending_with_newline.json libgnatcoll-19/testsuite/tests/json/validation/y_array_ending_with_newline.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_ending_with_newline.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_ending_with_newline.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["a"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_false.json libgnatcoll-19/testsuite/tests/json/validation/y_array_false.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_false.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_false.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[false] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_heterogeneous.json libgnatcoll-19/testsuite/tests/json/validation/y_array_heterogeneous.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_heterogeneous.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_heterogeneous.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[null, 1, "1", {}] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_null.json libgnatcoll-19/testsuite/tests/json/validation/y_array_null.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[null] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_with_1_and_newline.json libgnatcoll-19/testsuite/tests/json/validation/y_array_with_1_and_newline.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_with_1_and_newline.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_with_1_and_newline.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -[1 -] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_with_leading_space.json libgnatcoll-19/testsuite/tests/json/validation/y_array_with_leading_space.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_with_leading_space.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_with_leading_space.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - [1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_with_several_null.json libgnatcoll-19/testsuite/tests/json/validation/y_array_with_several_null.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_with_several_null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_with_several_null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1,null,null,null,2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_array_with_trailing_space.json libgnatcoll-19/testsuite/tests/json/validation/y_array_with_trailing_space.json --- libgnatcoll-18/testsuite/tests/json/validation/y_array_with_trailing_space.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_array_with_trailing_space.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_0e+1.json libgnatcoll-19/testsuite/tests/json/validation/y_number_0e+1.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_0e+1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_0e+1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0e+1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_0e1.json libgnatcoll-19/testsuite/tests/json/validation/y_number_0e1.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_0e1.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_0e1.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[0e1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_after_space.json libgnatcoll-19/testsuite/tests/json/validation/y_number_after_space.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_after_space.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_after_space.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ 4] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_double_close_to_zero.json libgnatcoll-19/testsuite/tests/json/validation/y_number_double_close_to_zero.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_double_close_to_zero.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_double_close_to_zero.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001] diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_int_with_exp.json libgnatcoll-19/testsuite/tests/json/validation/y_number_int_with_exp.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_int_with_exp.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_int_with_exp.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[20e1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number.json libgnatcoll-19/testsuite/tests/json/validation/y_number.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[123e65] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_minus_zero.json libgnatcoll-19/testsuite/tests/json/validation/y_number_minus_zero.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_minus_zero.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_minus_zero.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-0] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_negative_int.json libgnatcoll-19/testsuite/tests/json/validation/y_number_negative_int.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_negative_int.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_negative_int.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-123] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_negative_one.json libgnatcoll-19/testsuite/tests/json/validation/y_number_negative_one.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_negative_one.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_negative_one.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-1] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_negative_zero.json libgnatcoll-19/testsuite/tests/json/validation/y_number_negative_zero.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_negative_zero.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_negative_zero.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[-0] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_real_capital_e.json libgnatcoll-19/testsuite/tests/json/validation/y_number_real_capital_e.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_real_capital_e.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_real_capital_e.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1E22] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_real_capital_e_neg_exp.json libgnatcoll-19/testsuite/tests/json/validation/y_number_real_capital_e_neg_exp.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_real_capital_e_neg_exp.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_real_capital_e_neg_exp.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1E-2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_real_capital_e_pos_exp.json libgnatcoll-19/testsuite/tests/json/validation/y_number_real_capital_e_pos_exp.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_real_capital_e_pos_exp.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_real_capital_e_pos_exp.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1E+2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_real_exponent.json libgnatcoll-19/testsuite/tests/json/validation/y_number_real_exponent.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_real_exponent.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_real_exponent.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[123e45] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_real_fraction_exponent.json libgnatcoll-19/testsuite/tests/json/validation/y_number_real_fraction_exponent.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_real_fraction_exponent.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_real_fraction_exponent.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[123.456e78] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_real_neg_exp.json libgnatcoll-19/testsuite/tests/json/validation/y_number_real_neg_exp.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_real_neg_exp.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_real_neg_exp.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1e-2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_real_pos_exponent.json libgnatcoll-19/testsuite/tests/json/validation/y_number_real_pos_exponent.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_real_pos_exponent.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_real_pos_exponent.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[1e+2] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_simple_int.json libgnatcoll-19/testsuite/tests/json/validation/y_number_simple_int.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_simple_int.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_simple_int.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[123] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_number_simple_real.json libgnatcoll-19/testsuite/tests/json/validation/y_number_simple_real.json --- libgnatcoll-18/testsuite/tests/json/validation/y_number_simple_real.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_number_simple_real.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[123.456789] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_basic.json libgnatcoll-19/testsuite/tests/json/validation/y_object_basic.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_basic.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_basic.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"asd":"sdf"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_duplicated_key_and_value.json libgnatcoll-19/testsuite/tests/json/validation/y_object_duplicated_key_and_value.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_duplicated_key_and_value.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_duplicated_key_and_value.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b","a":"b"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_duplicated_key.json libgnatcoll-19/testsuite/tests/json/validation/y_object_duplicated_key.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_duplicated_key.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_duplicated_key.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":"b","a":"c"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_empty.json libgnatcoll-19/testsuite/tests/json/validation/y_object_empty.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_empty.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_empty.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_empty_key.json libgnatcoll-19/testsuite/tests/json/validation/y_object_empty_key.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_empty_key.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_empty_key.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"":0} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_escaped_null_in_key.json libgnatcoll-19/testsuite/tests/json/validation/y_object_escaped_null_in_key.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_escaped_null_in_key.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_escaped_null_in_key.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"foo\u0000bar": 42} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_extreme_numbers.json libgnatcoll-19/testsuite/tests/json/validation/y_object_extreme_numbers.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_extreme_numbers.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_extreme_numbers.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{ "min": -1.0e+28, "max": 1.0e+28 } \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object.json libgnatcoll-19/testsuite/tests/json/validation/y_object.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"asd":"sdf", "dfg":"fgh"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_long_strings.json libgnatcoll-19/testsuite/tests/json/validation/y_object_long_strings.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_long_strings.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_long_strings.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_simple.json libgnatcoll-19/testsuite/tests/json/validation/y_object_simple.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_simple.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_simple.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"a":[]} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_string_unicode.json libgnatcoll-19/testsuite/tests/json/validation/y_object_string_unicode.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_string_unicode.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_string_unicode.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -{"title":"\u041f\u043e\u043b\u0442\u043e\u0440\u0430 \u0417\u0435\u043c\u043b\u0435\u043a\u043e\u043f\u0430" } \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_object_with_newlines.json libgnatcoll-19/testsuite/tests/json/validation/y_object_with_newlines.json --- libgnatcoll-18/testsuite/tests/json/validation/y_object_with_newlines.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_object_with_newlines.json 1970-01-01 00:00:00.000000000 +0000 @@ -1,3 +0,0 @@ -{ -"a": "b" -} \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_1_2_3_bytes_UTF-8_sequences.json libgnatcoll-19/testsuite/tests/json/validation/y_string_1_2_3_bytes_UTF-8_sequences.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_1_2_3_bytes_UTF-8_sequences.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_1_2_3_bytes_UTF-8_sequences.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u0060\u012a\u12AB"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_accepted_surrogate_pair.json libgnatcoll-19/testsuite/tests/json/validation/y_string_accepted_surrogate_pair.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_accepted_surrogate_pair.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_accepted_surrogate_pair.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD801\udc37"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_accepted_surrogate_pairs.json libgnatcoll-19/testsuite/tests/json/validation/y_string_accepted_surrogate_pairs.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_accepted_surrogate_pairs.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_accepted_surrogate_pairs.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\ud83d\ude39\ud83d\udc8d"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_allowed_escapes.json libgnatcoll-19/testsuite/tests/json/validation/y_string_allowed_escapes.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_allowed_escapes.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_allowed_escapes.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\"\\\/\b\f\n\r\t"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_backslash_and_u_escaped_zero.json libgnatcoll-19/testsuite/tests/json/validation/y_string_backslash_and_u_escaped_zero.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_backslash_and_u_escaped_zero.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_backslash_and_u_escaped_zero.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\\u0000"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_backslash_doublequotes.json libgnatcoll-19/testsuite/tests/json/validation/y_string_backslash_doublequotes.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_backslash_doublequotes.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_backslash_doublequotes.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\""] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_comments.json libgnatcoll-19/testsuite/tests/json/validation/y_string_comments.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_comments.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_comments.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["a/*b*/c/*d//e"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_double_escape_a.json libgnatcoll-19/testsuite/tests/json/validation/y_string_double_escape_a.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_double_escape_a.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_double_escape_a.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\\a"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_double_escape_n.json libgnatcoll-19/testsuite/tests/json/validation/y_string_double_escape_n.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_double_escape_n.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_double_escape_n.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\\n"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_escaped_control_character.json libgnatcoll-19/testsuite/tests/json/validation/y_string_escaped_control_character.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_escaped_control_character.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_escaped_control_character.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u0012"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_escaped_noncharacter.json libgnatcoll-19/testsuite/tests/json/validation/y_string_escaped_noncharacter.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_escaped_noncharacter.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_escaped_noncharacter.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uFFFF"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_in_array.json libgnatcoll-19/testsuite/tests/json/validation/y_string_in_array.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_in_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_in_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["asd"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_in_array_with_leading_space.json libgnatcoll-19/testsuite/tests/json/validation/y_string_in_array_with_leading_space.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_in_array_with_leading_space.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_in_array_with_leading_space.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[ "asd"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_last_surrogates_1_and_2.json libgnatcoll-19/testsuite/tests/json/validation/y_string_last_surrogates_1_and_2.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_last_surrogates_1_and_2.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_last_surrogates_1_and_2.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uDBFF\uDFFF"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_nbsp_uescaped.json libgnatcoll-19/testsuite/tests/json/validation/y_string_nbsp_uescaped.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_nbsp_uescaped.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_nbsp_uescaped.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["new\u00A0line"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+10FFFF.json libgnatcoll-19/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+10FFFF.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+10FFFF.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+10FFFF.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["􏿿"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+1FFFF.json libgnatcoll-19/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+1FFFF.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+1FFFF.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+1FFFF.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["𛿿"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+FFFF.json libgnatcoll-19/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+FFFF.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+FFFF.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_nonCharacterInUTF-8_U+FFFF.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["￿"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_null_escape.json libgnatcoll-19/testsuite/tests/json/validation/y_string_null_escape.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_null_escape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_null_escape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u0000"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_one-byte-utf-8.json libgnatcoll-19/testsuite/tests/json/validation/y_string_one-byte-utf-8.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_one-byte-utf-8.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_one-byte-utf-8.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u002c"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_pi.json libgnatcoll-19/testsuite/tests/json/validation/y_string_pi.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_pi.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_pi.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["π"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_simple_ascii.json libgnatcoll-19/testsuite/tests/json/validation/y_string_simple_ascii.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_simple_ascii.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_simple_ascii.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["asd "] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_space.json libgnatcoll-19/testsuite/tests/json/validation/y_string_space.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_space.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_space.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -" " \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json libgnatcoll-19/testsuite/tests/json/validation/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD834\uDd1e"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_three-byte-utf-8.json libgnatcoll-19/testsuite/tests/json/validation/y_string_three-byte-utf-8.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_three-byte-utf-8.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_three-byte-utf-8.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u0821"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_two-byte-utf-8.json libgnatcoll-19/testsuite/tests/json/validation/y_string_two-byte-utf-8.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_two-byte-utf-8.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_two-byte-utf-8.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u0123"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_u+2028_line_sep.json libgnatcoll-19/testsuite/tests/json/validation/y_string_u+2028_line_sep.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_u+2028_line_sep.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_u+2028_line_sep.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["
"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_u+2029_par_sep.json libgnatcoll-19/testsuite/tests/json/validation/y_string_u+2029_par_sep.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_u+2029_par_sep.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_u+2029_par_sep.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["
"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_uescaped_newline.json libgnatcoll-19/testsuite/tests/json/validation/y_string_uescaped_newline.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_uescaped_newline.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_uescaped_newline.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["new\u000Aline"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_uEscape.json libgnatcoll-19/testsuite/tests/json/validation/y_string_uEscape.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_uEscape.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_uEscape.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u0061\u30af\u30EA\u30b9"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unescaped_char_delete.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unescaped_char_delete.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unescaped_char_delete.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unescaped_char_delete.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[""] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_2.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_2.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_2.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_2.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["⍂㈴⍂"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicodeEscapedBackslash.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicodeEscapedBackslash.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicodeEscapedBackslash.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicodeEscapedBackslash.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u005C"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_escaped_double_quote.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_escaped_double_quote.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_escaped_double_quote.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_escaped_double_quote.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u0022"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uA66D"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+10FFFE_nonchar.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+10FFFE_nonchar.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+10FFFE_nonchar.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+10FFFE_nonchar.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uDBFF\uDFFE"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+1FFFE_nonchar.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+1FFFE_nonchar.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+1FFFE_nonchar.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+1FFFE_nonchar.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uD83F\uDFFE"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u200B"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+2064_invisible_plus.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+2064_invisible_plus.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+2064_invisible_plus.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+2064_invisible_plus.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\u2064"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+FDD0_nonchar.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+FDD0_nonchar.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+FDD0_nonchar.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+FDD0_nonchar.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uFDD0"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+FFFE_nonchar.json libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+FFFE_nonchar.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_unicode_U+FFFE_nonchar.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_unicode_U+FFFE_nonchar.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["\uFFFE"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_utf8.json libgnatcoll-19/testsuite/tests/json/validation/y_string_utf8.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_utf8.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_utf8.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["€𝄞"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_string_with_del_character.json libgnatcoll-19/testsuite/tests/json/validation/y_string_with_del_character.json --- libgnatcoll-18/testsuite/tests/json/validation/y_string_with_del_character.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_string_with_del_character.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["aa"] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_false.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_false.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_false.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_false.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -false \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_int.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_int.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_int.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_int.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -42 \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_negative_real.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_negative_real.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_negative_real.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_negative_real.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ --0.1 \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_null.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_null.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_null.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_null.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -null \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_string.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_string.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_string.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_string.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -"asd" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_true.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_true.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_lonely_true.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_lonely_true.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -true \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_string_empty.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_string_empty.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_string_empty.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_string_empty.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -"" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_trailing_newline.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_trailing_newline.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_trailing_newline.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_trailing_newline.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -["a"] diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_true_in_array.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_true_in_array.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_true_in_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_true_in_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -[true] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/json/validation/y_structure_whitespace_array.json libgnatcoll-19/testsuite/tests/json/validation/y_structure_whitespace_array.json --- libgnatcoll-18/testsuite/tests/json/validation/y_structure_whitespace_array.json 2018-03-27 08:27:29.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/json/validation/y_structure_whitespace_array.json 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ - [] \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/projects/external_default_value/p.gpr libgnatcoll-19/testsuite/tests/projects/external_default_value/p.gpr --- libgnatcoll-18/testsuite/tests/projects/external_default_value/p.gpr 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/external_default_value/p.gpr 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -with "q.gpr"; -project P is - -end P; diff -Nru libgnatcoll-18/testsuite/tests/projects/external_default_value/q.gpr libgnatcoll-19/testsuite/tests/projects/external_default_value/q.gpr --- libgnatcoll-18/testsuite/tests/projects/external_default_value/q.gpr 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/external_default_value/q.gpr 1970-01-01 00:00:00.000000000 +0000 @@ -1,8 +0,0 @@ -project Q is - for Source_Files use (); - - Path := project'Project_Dir & "some_dir"; - Var1 := external ("NONEXISTINGVAR1", Path); - - Var2 := external ("NONEXISTINGVAR2", project'Project_Dir & "some_dir"); -end Q; diff -Nru libgnatcoll-18/testsuite/tests/projects/external_default_value/test.adb libgnatcoll-19/testsuite/tests/projects/external_default_value/test.adb --- libgnatcoll-18/testsuite/tests/projects/external_default_value/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/external_default_value/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,43 +0,0 @@ -with GNATCOLL.Projects; use GNATCOLL.Projects; -with GNATCOLL.VFS; use GNATCOLL.VFS; - -with Test_Assert; - -function Test return Integer is - PT : Project_Tree; - My_Root_Project : Project_Type; - Env : Project_Environment_Access; -begin - Initialize (Env); - - GNATCOLL.Projects.Load - (PT, - Root_Project_Path => Create ("p.gpr"), - Env => Env); - - declare - UV_Array : constant Untyped_Variable_Array := - PT.Untyped_Variables; - UV : Untyped_Variable; - Expected_Value : constant String := - PT.Project_From_Name ("Q").Project_Path.Display_Dir_Name - & "some_dir"; - begin - Test_Assert.Assert - (UV_Array'Length = 2, "Wrong number of Untyped Variables"); - if UV_Array'Length = 2 then - UV := UV_Array (UV_Array'First); - Test_Assert.Assert - (External_Default (UV), Expected_Value, - "Default external value is wrong for " & External_Name (UV)); - - UV := UV_Array (UV_Array'Last); - Test_Assert.Assert - (External_Default (UV), Expected_Value, - "Default external value is wrong for " & External_Name (UV)); - end if; - end; - - return Test_Assert.Report; - -end Test; diff -Nru libgnatcoll-18/testsuite/tests/projects/external_default_value/test.yaml libgnatcoll-19/testsuite/tests/projects/external_default_value/test.yaml --- libgnatcoll-18/testsuite/tests/projects/external_default_value/test.yaml 2018-03-29 07:17:15.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/external_default_value/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -description: Complex default value of external in imported project -data: - - "p.gpr" - - "q.gpr" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/projects/file_from_unit/my__proc.txt libgnatcoll-19/testsuite/tests/projects/file_from_unit/my__proc.txt --- libgnatcoll-18/testsuite/tests/projects/file_from_unit/my__proc.txt 2018-03-24 08:28:47.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/file_from_unit/my__proc.txt 1970-01-01 00:00:00.000000000 +0000 @@ -1,17 +0,0 @@ -procedure Proc is - function F (I : Integer) return Integer is - begin - return I + 1; - end; - - function G (I : Integer) return Integer is (I + 1); - - procedure P is - begin - null; - end; - - procedure Q is null; -begin - null; -end; diff -Nru libgnatcoll-18/testsuite/tests/projects/file_from_unit/test1.gpr libgnatcoll-19/testsuite/tests/projects/file_from_unit/test1.gpr --- libgnatcoll-18/testsuite/tests/projects/file_from_unit/test1.gpr 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/file_from_unit/test1.gpr 1970-01-01 00:00:00.000000000 +0000 @@ -1,9 +0,0 @@ -project Test1 is - - package Naming is - for Body ("proc") use "my__proc.txt"; - for Body_Suffix ("ada") use ".ada"; - end Naming; - -end Test1; - diff -Nru libgnatcoll-18/testsuite/tests/projects/file_from_unit/test.adb libgnatcoll-19/testsuite/tests/projects/file_from_unit/test.adb --- libgnatcoll-18/testsuite/tests/projects/file_from_unit/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/file_from_unit/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,27 +0,0 @@ -with Gnat.Strings; use Gnat.Strings; -with Gnatcoll.Projects; use Gnatcoll.Projects; -with Gnatcoll.VFS; use Gnatcoll.VFS; - -with Test_Assert; - -function Test return Integer is - Tree : Gnatcoll.Projects.Project_Tree; -begin - Load (Tree, Root_Project_Path => Create (+"test1.gpr")); - - declare - File_Name : constant String := - +File_From_Unit (Project => Root_Project (Tree), - Unit_Name => "PrOc", - Part => Unit_Body, - Language => "ada", - File_Must_Exist => False); - begin - Test_Assert.Assert - (File_Name, "my__proc.txt", "Wrong file name for unit Proc"); - end; - - return Test_Assert.Report; - -end Test; - diff -Nru libgnatcoll-18/testsuite/tests/projects/file_from_unit/test.yaml libgnatcoll-19/testsuite/tests/projects/file_from_unit/test.yaml --- libgnatcoll-18/testsuite/tests/projects/file_from_unit/test.yaml 2018-03-24 08:28:47.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/projects/file_from_unit/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -description: File_From_Unit argument Unit name is case insensitive -data: - - "test1.gpr" - - "my__proc.txt" \ No newline at end of file diff -Nru libgnatcoll-18/testsuite/tests/vfs/create_from_dir/test.adb libgnatcoll-19/testsuite/tests/vfs/create_from_dir/test.adb --- libgnatcoll-18/testsuite/tests/vfs/create_from_dir/test.adb 2018-05-25 05:42:27.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/vfs/create_from_dir/test.adb 1970-01-01 00:00:00.000000000 +0000 @@ -1,114 +0,0 @@ -with GNAT.OS_Lib; use GNAT.OS_Lib; -with GNATCOLL.VFS; use GNATCOLL.VFS; -with Ada.Text_IO; use Ada.Text_IO; -with Test_Assert; - -function Test return Integer is - - package A renames Test_Assert; - - DS : constant Character := GNAT.OS_Lib.Directory_Separator; - - Folder : Virtual_File; - F : Virtual_File; -begin - - ------------ - -- Case 1 -- - ------------ - -- Using a directory that is not a full name (and where the .. cannot - -- be resolved) - - Folder := Create (+".." & DS & ".." & DS & "foo" & DS); - - F := Create_From_Dir - (Dir => Folder, Base_name => +"file.ads"); - A.Assert (".." & DS & ".." & DS & "foo" & DS & "file.ads", - F.Display_Full_Name, - "With base name and relative directory"); - A.Assert (".." & DS & ".." & DS & "foo" & DS & "file.ads", - F.Display_Full_Name (Normalize => True), - "Normalized with base name and relative directory"); - - F := Create_From_Dir - (Dir => Folder, Base_name => +"file.ads", Normalize => True); - A.Assert (".." & DS & ".." & DS & "foo" & DS & "file.ads", - F.Display_Full_Name, - "With base name and relative directory"); - A.Assert (".." & DS & ".." & DS & "foo" & DS & "file.ads", - F.Display_Full_Name (Normalize => True), - "Normalized with base name and relative directory"); - - ------------ - -- Case 2 -- - ------------ - - Folder := Create (+"foo1" & DS & "foo2" & DS & "foo3" & DS & ""); - - F := Create_From_Dir - (Dir => Folder, Base_name => +".." & DS & ".." & DS & "file.ads"); - A.Assert ("foo1" & DS & "foo2" & DS & "foo3" & DS - & ".." & DS & ".." & DS & "file.ads", - F.Display_Full_Name, - "When file is relative to absolute directory"); - A.Assert ("foo1" & DS & "file.ads", - F.Display_Full_Name (Normalize => True), - "Normalized name when file is relative to absolute directory"); - - F := Create_From_Dir ( - Dir => Folder, Base_name => +".." & DS & ".." & DS & "file.ads", - Normalize => True); - A.Assert ("foo1" & DS & "foo2" & DS & "foo3" & DS & ".." - & DS & ".." & DS & "file.ads", - F.Display_Full_Name, - "When file is relative to normalized absolute directory"); - A.Assert ("foo1" & DS & "file.ads", - F.Display_Full_Name (Normalize => True), - "Normalized name when file is relative to normalized absolute" - & " directory"); - - ------------ - -- Case 3 -- - ------------ - -- Using an absolute directory, where the .. can be resolved - - Folder := Create - (+"" & DS & "foo1" & DS & "foo2" & DS & "foo3" & DS - & ".." & DS & ".." & DS & "foo" & DS & ""); - - F := Create_From_Dir - (Dir => Folder, Base_name => +"file.ads"); - A.Assert ("" & DS & "foo1" & DS & "foo2" & DS & "foo3" & DS & ".." - & DS & ".." & DS & "foo" & DS & "file.ads", - F.Display_Full_Name, - "When file is relative to absolute directory with .."); - A.Assert ("" & DS & "foo1" & DS & "foo" & DS & "file.ads", - F.Display_Full_Name (Normalize => True), - "Normalized name when file is relative to absolute directory" - & " with .."); - - F := Create_From_Dir - (Dir => Folder, Base_name => +"file.ads", Normalize => True); - A.Assert ("" & DS & "foo1" & DS & "foo" & DS & "file.ads", - F.Display_Full_Name, - "When file is relative to normalized absolute directory with .."); - A.Assert ("" & DS & "foo1" & DS & "foo" & DS & "file.ads", - F.Display_Full_Name (Normalize => True), - "Normalized name when file is relative to normalized absolute" - & " directory with .."); - - -- Check Create_From_Dir with a No_File entry - declare - Test_Success : Boolean := False; - begin - begin - F := Create_From_Dir (No_File, +"file.ads"); - exception - when VFS_Invalid_File_Error => - Test_Success := True; - end; - A.Assert (Test_Success, "Should raise Invalid_File_Error"); - end; - - return A.Report; -end Test; diff -Nru libgnatcoll-18/testsuite/tests/vfs/create_from_dir/test.yaml libgnatcoll-19/testsuite/tests/vfs/create_from_dir/test.yaml --- libgnatcoll-18/testsuite/tests/vfs/create_from_dir/test.yaml 2018-03-05 13:06:25.000000000 +0000 +++ libgnatcoll-19/testsuite/tests/vfs/create_from_dir/test.yaml 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -description: Test Create_From_Dir diff -Nru libgnatcoll-18/version_information libgnatcoll-19/version_information --- libgnatcoll-18/version_information 2018-05-25 05:42:18.000000000 +0000 +++ libgnatcoll-19/version_information 2019-05-16 17:43:58.000000000 +0000 @@ -1 +1 @@ -2018 \ No newline at end of file +2019 \ No newline at end of file