From 9b153e567771eb35636727784368f0dbfa2665cf Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 6 May 2026 11:01:09 +0000 Subject: [PATCH 1/4] Convert plugin into a syndication feed parser Replace the JSONC parser with @jsonic/feed: an RSS (0.90, 0.91, 0.92, 1.0, 2.0) and Atom (0.3, 1.0) parser built on top of @jsonic/xml. By default every dialect is normalised to an Atom-shaped result; a `format: 'native'` option preserves the source dialect's structure and `format: 'raw'` returns the underlying XmlElement tree. - src/feed.ts: typed AtomFeed / Rss2Feed / Rss1Feed shapes, dialect detection, native parsers for each format, and best-effort RSS-to-Atom conversion mappings (guid -> id, enclosure -> link[rel], managingEditor -> authors, lastBuildDate -> updated, etc.). - Plugin form (`Jsonic.use(Feed)` adds a `.feed(src)` method) and a standalone `parseFeed(src, options)` helper. - test/feed.test.ts: hand-curated samples covering each dialect, the three output formats, the plugin form, and xhtml content extraction. - test/feedparser-wellformed/: focused subset of well-formed feed samples vendored from kurtmckee/feedparser (BSD 2-Clause); upstream LICENSE preserved alongside, attribution recorded in THIRD_PARTY_NOTICES.md. - test/feedparser.test.ts: dialect detection, no-error parse, and targeted value checks against the vendored corpus. Removed jsonc grammar, embed script, Go module, and JSONTestSuite corpus, all of which were specific to the previous JSONC parser. --- .github/workflows/build.yml | 22 - .gitignore | 3 - Makefile | 48 +- README.md | 340 +++--- THIRD_PARTY_NOTICES.md | 74 +- embed-grammar.js | 74 -- go/go.mod | 5 - go/go.sum | 2 - go/jsonc.go | 82 -- go/jsonc_test.go | 634 ----------- jsonc-grammar.jsonic | 34 - package.json | 32 +- src/feed.ts | 981 ++++++++++++++++++ src/jsonc.ts | 71 -- test/JSONTestSuite/LICENSE | 21 - test/JSONTestSuite/README.md | 55 - .../i_number_double_huge_neg_exp.json | 1 - .../test_parsing/i_number_huge_exp.json | 1 - .../i_number_neg_int_huge_exp.json | 1 - .../i_number_pos_double_huge_exp.json | 1 - .../i_number_real_neg_overflow.json | 1 - .../i_number_real_pos_overflow.json | 1 - .../test_parsing/i_number_real_underflow.json | 1 - .../i_number_too_big_neg_int.json | 1 - .../i_number_too_big_pos_int.json | 1 - .../i_number_very_big_negative_int.json | 1 - .../i_object_key_lone_2nd_surrogate.json | 1 - ..._string_1st_surrogate_but_2nd_missing.json | 1 - ...tring_1st_valid_surrogate_2nd_invalid.json | 1 - .../i_string_UTF-16LE_with_BOM.json | Bin 12 -> 0 bytes .../i_string_UTF-8_invalid_sequence.json | 1 - .../i_string_UTF8_surrogate_U+D800.json | 1 - ...incomplete_surrogate_and_escape_valid.json | 1 - .../i_string_incomplete_surrogate_pair.json | 1 - ...ng_incomplete_surrogates_escape_valid.json | 1 - .../i_string_invalid_lonely_surrogate.json | 1 - .../i_string_invalid_surrogate.json | 1 - .../test_parsing/i_string_invalid_utf-8.json | 1 - .../i_string_inverted_surrogates_U+1D11E.json | 1 - .../test_parsing/i_string_iso_latin_1.json | 1 - .../i_string_lone_second_surrogate.json | 1 - .../i_string_lone_utf8_continuation_byte.json | 1 - .../i_string_not_in_unicode_range.json | 1 - .../i_string_overlong_sequence_2_bytes.json | 1 - .../i_string_overlong_sequence_6_bytes.json | 1 - ...string_overlong_sequence_6_bytes_null.json | 1 - .../i_string_truncated-utf-8.json | 1 - .../test_parsing/i_string_utf16BE_no_BOM.json | Bin 10 -> 0 bytes .../test_parsing/i_string_utf16LE_no_BOM.json | Bin 10 -> 0 bytes .../i_structure_500_nested_arrays.json | 1 - .../i_structure_UTF-8_BOM_empty_object.json | 1 - .../n_array_1_true_without_comma.json | 1 - .../test_parsing/n_array_a_invalid_utf8.json | 1 - .../n_array_colon_instead_of_comma.json | 1 - .../n_array_comma_after_close.json | 1 - .../n_array_comma_and_number.json | 1 - .../test_parsing/n_array_double_comma.json | 1 - .../n_array_double_extra_comma.json | 1 - .../test_parsing/n_array_extra_close.json | 1 - .../test_parsing/n_array_extra_comma.json | 1 - .../test_parsing/n_array_incomplete.json | 1 - .../n_array_incomplete_invalid_value.json | 1 - .../n_array_inner_array_no_comma.json | 1 - .../test_parsing/n_array_invalid_utf8.json | 1 - .../n_array_items_separated_by_semicolon.json | 1 - .../test_parsing/n_array_just_comma.json | 1 - .../test_parsing/n_array_just_minus.json | 1 - .../test_parsing/n_array_missing_value.json | 1 - .../n_array_newlines_unclosed.json | 3 - .../n_array_number_and_comma.json | 1 - .../n_array_number_and_several_commas.json | 1 - .../n_array_spaces_vertical_tab_formfeed.json | 1 - .../test_parsing/n_array_star_inside.json | 1 - .../test_parsing/n_array_unclosed.json | 1 - .../n_array_unclosed_trailing_comma.json | 1 - .../n_array_unclosed_with_new_lines.json | 3 - .../n_array_unclosed_with_object_inside.json | 1 - .../test_parsing/n_incomplete_false.json | 1 - .../test_parsing/n_incomplete_null.json | 1 - .../test_parsing/n_incomplete_true.json | 1 - .../n_multidigit_number_then_00.json | Bin 4 -> 0 bytes .../test_parsing/n_number_++.json | 1 - .../test_parsing/n_number_+1.json | 1 - .../test_parsing/n_number_+Inf.json | 1 - .../test_parsing/n_number_-01.json | 1 - .../test_parsing/n_number_-1.0..json | 1 - .../test_parsing/n_number_-2..json | 1 - .../test_parsing/n_number_-NaN.json | 1 - .../test_parsing/n_number_.-1.json | 1 - .../test_parsing/n_number_.2e-3.json | 1 - .../test_parsing/n_number_0.1.2.json | 1 - .../test_parsing/n_number_0.3e+.json | 1 - .../test_parsing/n_number_0.3e.json | 1 - .../test_parsing/n_number_0.e1.json | 1 - .../test_parsing/n_number_0_capital_E+.json | 1 - .../test_parsing/n_number_0_capital_E.json | 1 - .../test_parsing/n_number_0e+.json | 1 - .../test_parsing/n_number_0e.json | 1 - .../test_parsing/n_number_1.0e+.json | 1 - .../test_parsing/n_number_1.0e-.json | 1 - .../test_parsing/n_number_1.0e.json | 1 - .../test_parsing/n_number_1_000.json | 1 - .../test_parsing/n_number_1eE2.json | 1 - .../test_parsing/n_number_2.e+3.json | 1 - .../test_parsing/n_number_2.e-3.json | 1 - .../test_parsing/n_number_2.e3.json | 1 - .../test_parsing/n_number_9.e+.json | 1 - .../test_parsing/n_number_Inf.json | 1 - .../test_parsing/n_number_NaN.json | 1 - .../n_number_U+FF11_fullwidth_digit_one.json | 1 - .../test_parsing/n_number_expression.json | 1 - .../test_parsing/n_number_hex_1_digit.json | 1 - .../test_parsing/n_number_hex_2_digits.json | 1 - .../test_parsing/n_number_infinity.json | 1 - .../test_parsing/n_number_invalid+-.json | 1 - .../n_number_invalid-negative-real.json | 1 - .../n_number_invalid-utf-8-in-bigger-int.json | 1 - .../n_number_invalid-utf-8-in-exponent.json | 1 - .../n_number_invalid-utf-8-in-int.json | 1 - .../test_parsing/n_number_minus_infinity.json | 1 - ...mber_minus_sign_with_trailing_garbage.json | 1 - .../test_parsing/n_number_minus_space_1.json | 1 - .../n_number_neg_int_starting_with_zero.json | 1 - .../n_number_neg_real_without_int_part.json | 1 - .../n_number_neg_with_garbage_at_end.json | 1 - .../n_number_real_garbage_after_e.json | 1 - ...number_real_with_invalid_utf8_after_e.json | 1 - ...n_number_real_without_fractional_part.json | 1 - .../n_number_starting_with_dot.json | 1 - .../test_parsing/n_number_with_alpha.json | 1 - .../n_number_with_alpha_char.json | 1 - .../n_number_with_leading_zero.json | 1 - .../test_parsing/n_object_bad_value.json | 1 - .../test_parsing/n_object_bracket_key.json | 1 - .../n_object_comma_instead_of_colon.json | 1 - .../test_parsing/n_object_double_colon.json | 1 - .../test_parsing/n_object_emoji.json | 1 - .../test_parsing/n_object_garbage_at_end.json | 1 - .../n_object_key_with_single_quotes.json | 1 - ...uation_byte_in_key_and_trailing_comma.json | 1 - .../test_parsing/n_object_missing_colon.json | 1 - .../test_parsing/n_object_missing_key.json | 1 - .../n_object_missing_semicolon.json | 1 - .../test_parsing/n_object_missing_value.json | 1 - .../test_parsing/n_object_no-colon.json | 1 - .../test_parsing/n_object_non_string_key.json | 1 - ...on_string_key_but_huge_number_instead.json | 1 - .../n_object_repeated_null_null.json | 1 - .../n_object_several_trailing_commas.json | 1 - .../test_parsing/n_object_single_quote.json | 1 - .../test_parsing/n_object_trailing_comma.json | 1 - .../n_object_trailing_comment.json | 1 - .../n_object_trailing_comment_open.json | 1 - .../n_object_trailing_comment_slash_open.json | 1 - ...railing_comment_slash_open_incomplete.json | 1 - .../n_object_two_commas_in_a_row.json | 1 - .../test_parsing/n_object_unquoted_key.json | 1 - .../n_object_unterminated-value.json | 1 - .../n_object_with_single_string.json | 1 - .../n_object_with_trailing_garbage.json | 1 - .../test_parsing/n_single_space.json | 1 - .../n_string_1_surrogate_then_escape.json | 1 - .../n_string_1_surrogate_then_escape_u.json | 1 - .../n_string_1_surrogate_then_escape_u1.json | 1 - .../n_string_1_surrogate_then_escape_u1x.json | 1 - .../n_string_accentuated_char_no_quotes.json | 1 - .../test_parsing/n_string_backslash_00.json | Bin 6 -> 0 bytes .../test_parsing/n_string_escape_x.json | 1 - .../n_string_escaped_backslash_bad.json | 1 - .../n_string_escaped_ctrl_char_tab.json | 1 - .../test_parsing/n_string_escaped_emoji.json | 1 - .../n_string_incomplete_escape.json | 1 - ...n_string_incomplete_escaped_character.json | 1 - .../n_string_incomplete_surrogate.json | 1 - ...g_incomplete_surrogate_escape_invalid.json | 1 - .../n_string_invalid-utf-8-in-escape.json | 1 - .../n_string_invalid_backslash_esc.json | 1 - .../n_string_invalid_unicode_escape.json | 1 - .../n_string_invalid_utf8_after_escape.json | 1 - .../n_string_leading_uescaped_thinspace.json | 1 - .../n_string_no_quotes_with_bad_escape.json | 1 - .../n_string_single_doublequote.json | 1 - .../test_parsing/n_string_single_quote.json | 1 - ...string_single_string_no_double_quotes.json | 1 - .../n_string_start_escape_unclosed.json | 1 - .../n_string_unescaped_ctrl_char.json | Bin 7 -> 0 bytes .../n_string_unescaped_newline.json | 2 - .../test_parsing/n_string_unescaped_tab.json | 1 - .../n_string_unicode_CapitalU.json | 1 - .../n_string_with_trailing_garbage.json | 1 - .../n_structure_100000_opening_arrays.json | 1 - .../n_structure_U+2060_word_joined.json | 1 - .../n_structure_UTF8_BOM_no_data.json | 1 - .../n_structure_angle_bracket_..json | 1 - .../n_structure_angle_bracket_null.json | 1 - .../n_structure_array_trailing_garbage.json | 1 - ...tructure_array_with_extra_array_close.json | 1 - ..._structure_array_with_unclosed_string.json | 1 - .../n_structure_ascii-unicode-identifier.json | 1 - .../n_structure_capitalized_True.json | 1 - .../n_structure_close_unopened_array.json | 1 - ...ucture_comma_instead_of_closing_brace.json | 1 - .../n_structure_double_array.json | 1 - .../test_parsing/n_structure_end_array.json | 1 - .../n_structure_incomplete_UTF8_BOM.json | 1 - .../n_structure_lone-invalid-utf-8.json | 1 - .../n_structure_lone-open-bracket.json | 1 - .../test_parsing/n_structure_no_data.json | 0 .../n_structure_null-byte-outside-string.json | Bin 3 -> 0 bytes ...tructure_number_with_trailing_garbage.json | 1 - ...ure_object_followed_by_closing_object.json | 1 - .../n_structure_object_unclosed_no_value.json | 1 - .../n_structure_object_with_comment.json | 1 - ...tructure_object_with_trailing_garbage.json | 1 - .../n_structure_open_array_apostrophe.json | 1 - .../n_structure_open_array_comma.json | 1 - .../n_structure_open_array_object.json | 1 - .../n_structure_open_array_open_object.json | 1 - .../n_structure_open_array_open_string.json | 1 - .../n_structure_open_array_string.json | 1 - .../test_parsing/n_structure_open_object.json | 1 - .../n_structure_open_object_close_array.json | 1 - .../n_structure_open_object_comma.json | 1 - .../n_structure_open_object_open_array.json | 1 - .../n_structure_open_object_open_string.json | 1 - ...e_open_object_string_with_apostrophes.json | 1 - .../test_parsing/n_structure_open_open.json | 1 - .../n_structure_single_eacute.json | 1 - .../test_parsing/n_structure_single_star.json | 1 - .../test_parsing/n_structure_trailing_#.json | 1 - ...n_structure_uescaped_LF_before_string.json | 1 - .../n_structure_unclosed_array.json | 1 - ...structure_unclosed_array_partial_null.json | 1 - ...cture_unclosed_array_unfinished_false.json | 1 - ...ucture_unclosed_array_unfinished_true.json | 1 - .../n_structure_unclosed_object.json | 1 - .../n_structure_unicode-identifier.json | 1 - ...ructure_whitespace_U+2060_word_joiner.json | 1 - .../n_structure_whitespace_formfeed.json | 1 - .../y_array_arraysWithSpaces.json | 1 - .../test_parsing/y_array_empty-string.json | 1 - .../test_parsing/y_array_empty.json | 1 - .../y_array_ending_with_newline.json | 1 - .../test_parsing/y_array_false.json | 1 - .../test_parsing/y_array_heterogeneous.json | 1 - .../test_parsing/y_array_null.json | 1 - .../y_array_with_1_and_newline.json | 2 - .../y_array_with_leading_space.json | 1 - .../y_array_with_several_null.json | 1 - .../y_array_with_trailing_space.json | 1 - test/JSONTestSuite/test_parsing/y_number.json | 1 - .../test_parsing/y_number_0e+1.json | 1 - .../test_parsing/y_number_0e1.json | 1 - .../test_parsing/y_number_after_space.json | 1 - .../y_number_double_close_to_zero.json | 1 - .../test_parsing/y_number_int_with_exp.json | 1 - .../test_parsing/y_number_minus_zero.json | 1 - .../test_parsing/y_number_negative_int.json | 1 - .../test_parsing/y_number_negative_one.json | 1 - .../test_parsing/y_number_negative_zero.json | 1 - .../test_parsing/y_number_real_capital_e.json | 1 - .../y_number_real_capital_e_neg_exp.json | 1 - .../y_number_real_capital_e_pos_exp.json | 1 - .../test_parsing/y_number_real_exponent.json | 1 - .../y_number_real_fraction_exponent.json | 1 - .../test_parsing/y_number_real_neg_exp.json | 1 - .../y_number_real_pos_exponent.json | 1 - .../test_parsing/y_number_simple_int.json | 1 - .../test_parsing/y_number_simple_real.json | 1 - test/JSONTestSuite/test_parsing/y_object.json | 1 - .../test_parsing/y_object_basic.json | 1 - .../test_parsing/y_object_duplicated_key.json | 1 - .../y_object_duplicated_key_and_value.json | 1 - .../test_parsing/y_object_empty.json | 1 - .../test_parsing/y_object_empty_key.json | 1 - .../y_object_escaped_null_in_key.json | 1 - .../y_object_extreme_numbers.json | 1 - .../test_parsing/y_object_long_strings.json | 1 - .../test_parsing/y_object_simple.json | 1 - .../test_parsing/y_object_string_unicode.json | 1 - .../test_parsing/y_object_with_newlines.json | 3 - .../y_string_1_2_3_bytes_UTF-8_sequences.json | 1 - .../y_string_accepted_surrogate_pair.json | 1 - .../y_string_accepted_surrogate_pairs.json | 1 - .../y_string_allowed_escapes.json | 1 - ...y_string_backslash_and_u_escaped_zero.json | 1 - .../y_string_backslash_doublequotes.json | 1 - .../test_parsing/y_string_comments.json | 1 - .../y_string_double_escape_a.json | 1 - .../y_string_double_escape_n.json | 1 - .../y_string_escaped_control_character.json | 1 - .../y_string_escaped_noncharacter.json | 1 - .../test_parsing/y_string_in_array.json | 1 - .../y_string_in_array_with_leading_space.json | 1 - .../y_string_last_surrogates_1_and_2.json | 1 - .../test_parsing/y_string_nbsp_uescaped.json | 1 - ...y_string_nonCharacterInUTF-8_U+10FFFF.json | 1 - .../y_string_nonCharacterInUTF-8_U+FFFF.json | 1 - .../test_parsing/y_string_null_escape.json | 1 - .../test_parsing/y_string_one-byte-utf-8.json | 1 - .../test_parsing/y_string_pi.json | 1 - ...ring_reservedCharacterInUTF-8_U+1BFFF.json | 1 - .../test_parsing/y_string_simple_ascii.json | 1 - .../test_parsing/y_string_space.json | 1 - ...rogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json | 1 - .../y_string_three-byte-utf-8.json | 1 - .../test_parsing/y_string_two-byte-utf-8.json | 1 - .../y_string_u+2028_line_sep.json | 1 - .../test_parsing/y_string_u+2029_par_sep.json | 1 - .../test_parsing/y_string_uEscape.json | 1 - .../y_string_uescaped_newline.json | 1 - .../y_string_unescaped_char_delete.json | 1 - .../test_parsing/y_string_unicode.json | 1 - .../y_string_unicodeEscapedBackslash.json | 1 - .../test_parsing/y_string_unicode_2.json | 1 - .../y_string_unicode_U+10FFFE_nonchar.json | 1 - .../y_string_unicode_U+1FFFE_nonchar.json | 1 - ...tring_unicode_U+200B_ZERO_WIDTH_SPACE.json | 1 - ..._string_unicode_U+2064_invisible_plus.json | 1 - .../y_string_unicode_U+FDD0_nonchar.json | 1 - .../y_string_unicode_U+FFFE_nonchar.json | 1 - ...y_string_unicode_escaped_double_quote.json | 1 - .../test_parsing/y_string_utf8.json | 1 - .../y_string_with_del_character.json | 1 - .../y_structure_lonely_false.json | 1 - .../test_parsing/y_structure_lonely_int.json | 1 - .../y_structure_lonely_negative_real.json | 1 - .../test_parsing/y_structure_lonely_null.json | 1 - .../y_structure_lonely_string.json | 1 - .../test_parsing/y_structure_lonely_true.json | 1 - .../y_structure_string_empty.json | 1 - .../y_structure_trailing_newline.json | 1 - .../y_structure_true_in_array.json | 1 - .../y_structure_whitespace_array.json | 1 - test/feed.test.ts | 429 ++++++++ test/feedparser-wellformed/LICENSE | 65 ++ .../atom/atom_namespace_1.xml | 7 + .../atom/entry_author_email.xml | 13 + .../atom/entry_author_name.xml | 13 + .../atom/entry_content_value.xml | 9 + test/feedparser-wellformed/atom/entry_id.xml | 9 + .../atom/entry_issued.xml | 9 + .../atom/entry_modified.xml | 9 + .../atom/entry_title.xml | 9 + .../atom10/atom10_namespace.xml | 7 + .../atom10/atom10_version.xml | 6 + .../atom10/entry_author_email.xml | 13 + .../atom10/entry_author_name.xml | 13 + .../atom10/entry_author_uri.xml | 13 + .../atom10/entry_content_type.xml | 9 + .../atom10/entry_content_value.xml | 9 + .../feedparser-wellformed/atom10/entry_id.xml | 9 + .../atom10/entry_link_href.xml | 9 + .../atom10/entry_summary.xml | 9 + .../atom10/entry_title.xml | 9 + .../rdf/rdf_channel_description.xml | 9 + .../rdf/rdf_channel_link.xml | 9 + .../rdf/rdf_channel_title.xml | 9 + .../rdf/rdf_item_description.xml | 16 + .../rdf/rdf_item_link.xml | 16 + .../rdf/rdf_item_rdf_about.xml | 15 + .../rdf/rdf_item_title.xml | 16 + .../rdf/rss090_channel_title.xml | 12 + .../rdf/rss090_item_title.xml | 12 + .../rdf/rss_version_10.xml | 6 + .../rss/channel_copyright.xml | 9 + .../rss/channel_description.xml | 9 + .../rss/channel_generator.xml | 9 + .../rss/channel_image_url.xml | 16 + .../rss/channel_link.xml | 9 + .../rss/channel_pubDate.xml | 9 + .../rss/channel_title.xml | 9 + .../feedparser-wellformed/rss/item_author.xml | 11 + .../rss/item_category.xml | 11 + .../rss/item_description.xml | 11 + .../rss/item_enclosure_url.xml | 12 + test/feedparser-wellformed/rss/item_guid.xml | 11 + test/feedparser-wellformed/rss/item_link.xml | 11 + .../rss/item_pubDate.xml | 11 + test/feedparser-wellformed/rss/item_title.xml | 11 + .../rss/rss_version_091_netscape.xml | 7 + .../rss/rss_version_091_userland.xml | 6 + .../rss/rss_version_092.xml | 6 + .../rss/rss_version_20.xml | 6 + test/feedparser.test.ts | 288 +++++ test/jsonc.test.ts | 265 ----- test/jsontestsuite.test.ts | 117 --- 387 files changed, 2488 insertions(+), 1960 deletions(-) delete mode 100644 embed-grammar.js delete mode 100644 go/go.mod delete mode 100644 go/go.sum delete mode 100644 go/jsonc.go delete mode 100644 go/jsonc_test.go delete mode 100644 jsonc-grammar.jsonic create mode 100644 src/feed.ts delete mode 100644 src/jsonc.ts delete mode 100644 test/JSONTestSuite/LICENSE delete mode 100644 test/JSONTestSuite/README.md delete mode 100644 test/JSONTestSuite/test_parsing/i_number_double_huge_neg_exp.json delete mode 100644 test/JSONTestSuite/test_parsing/i_number_huge_exp.json delete mode 100755 test/JSONTestSuite/test_parsing/i_number_neg_int_huge_exp.json delete mode 100755 test/JSONTestSuite/test_parsing/i_number_pos_double_huge_exp.json delete mode 100644 test/JSONTestSuite/test_parsing/i_number_real_neg_overflow.json delete mode 100644 test/JSONTestSuite/test_parsing/i_number_real_pos_overflow.json delete mode 100644 test/JSONTestSuite/test_parsing/i_number_real_underflow.json delete mode 100644 test/JSONTestSuite/test_parsing/i_number_too_big_neg_int.json delete mode 100644 test/JSONTestSuite/test_parsing/i_number_too_big_pos_int.json delete mode 100755 test/JSONTestSuite/test_parsing/i_number_very_big_negative_int.json delete mode 100644 test/JSONTestSuite/test_parsing/i_object_key_lone_2nd_surrogate.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_1st_surrogate_but_2nd_missing.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_UTF-16LE_with_BOM.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_UTF-8_invalid_sequence.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_UTF8_surrogate_U+D800.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_pair.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_incomplete_surrogates_escape_valid.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_invalid_lonely_surrogate.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_invalid_surrogate.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_invalid_utf-8.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_inverted_surrogates_U+1D11E.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_iso_latin_1.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_lone_second_surrogate.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_lone_utf8_continuation_byte.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_not_in_unicode_range.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_overlong_sequence_2_bytes.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes.json delete mode 100755 test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes_null.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_truncated-utf-8.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_utf16BE_no_BOM.json delete mode 100644 test/JSONTestSuite/test_parsing/i_string_utf16LE_no_BOM.json delete mode 100644 test/JSONTestSuite/test_parsing/i_structure_500_nested_arrays.json delete mode 100755 test/JSONTestSuite/test_parsing/i_structure_UTF-8_BOM_empty_object.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_1_true_without_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_a_invalid_utf8.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_colon_instead_of_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_comma_after_close.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_comma_and_number.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_double_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_double_extra_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_extra_close.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_extra_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_incomplete.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_incomplete_invalid_value.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_inner_array_no_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_invalid_utf8.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_items_separated_by_semicolon.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_just_comma.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_just_minus.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_missing_value.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_newlines_unclosed.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_number_and_comma.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_number_and_several_commas.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_spaces_vertical_tab_formfeed.json delete mode 100755 test/JSONTestSuite/test_parsing/n_array_star_inside.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_unclosed.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_unclosed_trailing_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_unclosed_with_new_lines.json delete mode 100644 test/JSONTestSuite/test_parsing/n_array_unclosed_with_object_inside.json delete mode 100644 test/JSONTestSuite/test_parsing/n_incomplete_false.json delete mode 100644 test/JSONTestSuite/test_parsing/n_incomplete_null.json delete mode 100644 test/JSONTestSuite/test_parsing/n_incomplete_true.json delete mode 100644 test/JSONTestSuite/test_parsing/n_multidigit_number_then_00.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_++.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_+1.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_+Inf.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_-01.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_-1.0..json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_-2..json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_-NaN.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_.-1.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_.2e-3.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_0.1.2.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_0.3e+.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_0.3e.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_0.e1.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_0_capital_E+.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_0_capital_E.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_0e+.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_0e.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_1.0e+.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_1.0e-.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_1.0e.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_1_000.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_1eE2.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_2.e+3.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_2.e-3.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_2.e3.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_9.e+.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_Inf.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_NaN.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_U+FF11_fullwidth_digit_one.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_expression.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_hex_1_digit.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_hex_2_digits.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_infinity.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_invalid+-.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_invalid-negative-real.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-bigger-int.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-exponent.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-int.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_minus_infinity.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_minus_sign_with_trailing_garbage.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_minus_space_1.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_neg_int_starting_with_zero.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_neg_real_without_int_part.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_neg_with_garbage_at_end.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_real_garbage_after_e.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_real_with_invalid_utf8_after_e.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_real_without_fractional_part.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_starting_with_dot.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_with_alpha.json delete mode 100644 test/JSONTestSuite/test_parsing/n_number_with_alpha_char.json delete mode 100755 test/JSONTestSuite/test_parsing/n_number_with_leading_zero.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_bad_value.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_bracket_key.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_comma_instead_of_colon.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_double_colon.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_emoji.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_garbage_at_end.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_key_with_single_quotes.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_missing_colon.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_missing_key.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_missing_semicolon.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_missing_value.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_no-colon.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_non_string_key.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_non_string_key_but_huge_number_instead.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_repeated_null_null.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_several_trailing_commas.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_single_quote.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_trailing_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_trailing_comment.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_trailing_comment_open.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open_incomplete.json delete mode 100755 test/JSONTestSuite/test_parsing/n_object_two_commas_in_a_row.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_unquoted_key.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_unterminated-value.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_with_single_string.json delete mode 100644 test/JSONTestSuite/test_parsing/n_object_with_trailing_garbage.json delete mode 100755 test/JSONTestSuite/test_parsing/n_single_space.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1x.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_accentuated_char_no_quotes.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_backslash_00.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_escape_x.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_escaped_backslash_bad.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_escaped_ctrl_char_tab.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_escaped_emoji.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_incomplete_escape.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_incomplete_escaped_character.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate_escape_invalid.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_invalid-utf-8-in-escape.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_invalid_backslash_esc.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_invalid_unicode_escape.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_invalid_utf8_after_escape.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_leading_uescaped_thinspace.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_no_quotes_with_bad_escape.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_single_doublequote.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_single_quote.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_single_string_no_double_quotes.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_start_escape_unclosed.json delete mode 100755 test/JSONTestSuite/test_parsing/n_string_unescaped_ctrl_char.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_unescaped_newline.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_unescaped_tab.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_unicode_CapitalU.json delete mode 100644 test/JSONTestSuite/test_parsing/n_string_with_trailing_garbage.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_100000_opening_arrays.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_U+2060_word_joined.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_UTF8_BOM_no_data.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_angle_bracket_..json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_angle_bracket_null.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_array_trailing_garbage.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_array_with_extra_array_close.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_array_with_unclosed_string.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_ascii-unicode-identifier.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_capitalized_True.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_close_unopened_array.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_comma_instead_of_closing_brace.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_double_array.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_end_array.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_incomplete_UTF8_BOM.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_lone-invalid-utf-8.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_lone-open-bracket.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_no_data.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_null-byte-outside-string.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_number_with_trailing_garbage.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_object_followed_by_closing_object.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_object_unclosed_no_value.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_object_with_comment.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_object_with_trailing_garbage.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_array_apostrophe.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_array_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_array_object.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_array_open_object.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_array_open_string.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_array_string.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_object.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_open_object_close_array.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_object_comma.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_object_open_array.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_object_open_string.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_object_string_with_apostrophes.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_open_open.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_single_eacute.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_single_star.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_trailing_#.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_uescaped_LF_before_string.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_unclosed_array.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_unclosed_array_partial_null.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_false.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_true.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_unclosed_object.json delete mode 100644 test/JSONTestSuite/test_parsing/n_structure_unicode-identifier.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_whitespace_U+2060_word_joiner.json delete mode 100755 test/JSONTestSuite/test_parsing/n_structure_whitespace_formfeed.json delete mode 100755 test/JSONTestSuite/test_parsing/y_array_arraysWithSpaces.json delete mode 100644 test/JSONTestSuite/test_parsing/y_array_empty-string.json delete mode 100755 test/JSONTestSuite/test_parsing/y_array_empty.json delete mode 100755 test/JSONTestSuite/test_parsing/y_array_ending_with_newline.json delete mode 100644 test/JSONTestSuite/test_parsing/y_array_false.json delete mode 100755 test/JSONTestSuite/test_parsing/y_array_heterogeneous.json delete mode 100644 test/JSONTestSuite/test_parsing/y_array_null.json delete mode 100644 test/JSONTestSuite/test_parsing/y_array_with_1_and_newline.json delete mode 100755 test/JSONTestSuite/test_parsing/y_array_with_leading_space.json delete mode 100755 test/JSONTestSuite/test_parsing/y_array_with_several_null.json delete mode 100755 test/JSONTestSuite/test_parsing/y_array_with_trailing_space.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number.json delete mode 100755 test/JSONTestSuite/test_parsing/y_number_0e+1.json delete mode 100755 test/JSONTestSuite/test_parsing/y_number_0e1.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_after_space.json delete mode 100755 test/JSONTestSuite/test_parsing/y_number_double_close_to_zero.json delete mode 100755 test/JSONTestSuite/test_parsing/y_number_int_with_exp.json delete mode 100755 test/JSONTestSuite/test_parsing/y_number_minus_zero.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_negative_int.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_negative_one.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_negative_zero.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_real_capital_e.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_real_capital_e_neg_exp.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_real_exponent.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_real_fraction_exponent.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_real_neg_exp.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_real_pos_exponent.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_simple_int.json delete mode 100644 test/JSONTestSuite/test_parsing/y_number_simple_real.json delete mode 100755 test/JSONTestSuite/test_parsing/y_object.json delete mode 100755 test/JSONTestSuite/test_parsing/y_object_basic.json delete mode 100755 test/JSONTestSuite/test_parsing/y_object_duplicated_key.json delete mode 100755 test/JSONTestSuite/test_parsing/y_object_duplicated_key_and_value.json delete mode 100644 test/JSONTestSuite/test_parsing/y_object_empty.json delete mode 100755 test/JSONTestSuite/test_parsing/y_object_empty_key.json delete mode 100644 test/JSONTestSuite/test_parsing/y_object_escaped_null_in_key.json delete mode 100644 test/JSONTestSuite/test_parsing/y_object_extreme_numbers.json delete mode 100644 test/JSONTestSuite/test_parsing/y_object_long_strings.json delete mode 100644 test/JSONTestSuite/test_parsing/y_object_simple.json delete mode 100644 test/JSONTestSuite/test_parsing/y_object_string_unicode.json delete mode 100644 test/JSONTestSuite/test_parsing/y_object_with_newlines.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pair.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pairs.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_allowed_escapes.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_backslash_and_u_escaped_zero.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_backslash_doublequotes.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_comments.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_double_escape_a.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_double_escape_n.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_escaped_control_character.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_escaped_noncharacter.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_in_array.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_in_array_with_leading_space.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_last_surrogates_1_and_2.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_nbsp_uescaped.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_null_escape.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_one-byte-utf-8.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_pi.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_simple_ascii.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_space.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_three-byte-utf-8.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_two-byte-utf-8.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_u+2028_line_sep.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_u+2029_par_sep.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_uEscape.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_uescaped_newline.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_unescaped_char_delete.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_unicodeEscapedBackslash.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode_2.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode_U+10FFFE_nonchar.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode_U+1FFFE_nonchar.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode_U+FDD0_nonchar.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_unicode_U+FFFE_nonchar.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_unicode_escaped_double_quote.json delete mode 100644 test/JSONTestSuite/test_parsing/y_string_utf8.json delete mode 100755 test/JSONTestSuite/test_parsing/y_string_with_del_character.json delete mode 100644 test/JSONTestSuite/test_parsing/y_structure_lonely_false.json delete mode 100755 test/JSONTestSuite/test_parsing/y_structure_lonely_int.json delete mode 100755 test/JSONTestSuite/test_parsing/y_structure_lonely_negative_real.json delete mode 100644 test/JSONTestSuite/test_parsing/y_structure_lonely_null.json delete mode 100755 test/JSONTestSuite/test_parsing/y_structure_lonely_string.json delete mode 100755 test/JSONTestSuite/test_parsing/y_structure_lonely_true.json delete mode 100644 test/JSONTestSuite/test_parsing/y_structure_string_empty.json delete mode 100644 test/JSONTestSuite/test_parsing/y_structure_trailing_newline.json delete mode 100644 test/JSONTestSuite/test_parsing/y_structure_true_in_array.json delete mode 100644 test/JSONTestSuite/test_parsing/y_structure_whitespace_array.json create mode 100644 test/feed.test.ts create mode 100644 test/feedparser-wellformed/LICENSE create mode 100644 test/feedparser-wellformed/atom/atom_namespace_1.xml create mode 100644 test/feedparser-wellformed/atom/entry_author_email.xml create mode 100644 test/feedparser-wellformed/atom/entry_author_name.xml create mode 100644 test/feedparser-wellformed/atom/entry_content_value.xml create mode 100644 test/feedparser-wellformed/atom/entry_id.xml create mode 100644 test/feedparser-wellformed/atom/entry_issued.xml create mode 100644 test/feedparser-wellformed/atom/entry_modified.xml create mode 100644 test/feedparser-wellformed/atom/entry_title.xml create mode 100644 test/feedparser-wellformed/atom10/atom10_namespace.xml create mode 100644 test/feedparser-wellformed/atom10/atom10_version.xml create mode 100644 test/feedparser-wellformed/atom10/entry_author_email.xml create mode 100644 test/feedparser-wellformed/atom10/entry_author_name.xml create mode 100644 test/feedparser-wellformed/atom10/entry_author_uri.xml create mode 100644 test/feedparser-wellformed/atom10/entry_content_type.xml create mode 100644 test/feedparser-wellformed/atom10/entry_content_value.xml create mode 100644 test/feedparser-wellformed/atom10/entry_id.xml create mode 100644 test/feedparser-wellformed/atom10/entry_link_href.xml create mode 100644 test/feedparser-wellformed/atom10/entry_summary.xml create mode 100644 test/feedparser-wellformed/atom10/entry_title.xml create mode 100644 test/feedparser-wellformed/rdf/rdf_channel_description.xml create mode 100644 test/feedparser-wellformed/rdf/rdf_channel_link.xml create mode 100644 test/feedparser-wellformed/rdf/rdf_channel_title.xml create mode 100644 test/feedparser-wellformed/rdf/rdf_item_description.xml create mode 100644 test/feedparser-wellformed/rdf/rdf_item_link.xml create mode 100644 test/feedparser-wellformed/rdf/rdf_item_rdf_about.xml create mode 100644 test/feedparser-wellformed/rdf/rdf_item_title.xml create mode 100644 test/feedparser-wellformed/rdf/rss090_channel_title.xml create mode 100644 test/feedparser-wellformed/rdf/rss090_item_title.xml create mode 100644 test/feedparser-wellformed/rdf/rss_version_10.xml create mode 100644 test/feedparser-wellformed/rss/channel_copyright.xml create mode 100644 test/feedparser-wellformed/rss/channel_description.xml create mode 100644 test/feedparser-wellformed/rss/channel_generator.xml create mode 100644 test/feedparser-wellformed/rss/channel_image_url.xml create mode 100644 test/feedparser-wellformed/rss/channel_link.xml create mode 100644 test/feedparser-wellformed/rss/channel_pubDate.xml create mode 100644 test/feedparser-wellformed/rss/channel_title.xml create mode 100644 test/feedparser-wellformed/rss/item_author.xml create mode 100644 test/feedparser-wellformed/rss/item_category.xml create mode 100644 test/feedparser-wellformed/rss/item_description.xml create mode 100644 test/feedparser-wellformed/rss/item_enclosure_url.xml create mode 100644 test/feedparser-wellformed/rss/item_guid.xml create mode 100644 test/feedparser-wellformed/rss/item_link.xml create mode 100644 test/feedparser-wellformed/rss/item_pubDate.xml create mode 100644 test/feedparser-wellformed/rss/item_title.xml create mode 100644 test/feedparser-wellformed/rss/rss_version_091_netscape.xml create mode 100644 test/feedparser-wellformed/rss/rss_version_091_userland.xml create mode 100644 test/feedparser-wellformed/rss/rss_version_092.xml create mode 100644 test/feedparser-wellformed/rss/rss_version_20.xml create mode 100644 test/feedparser.test.ts delete mode 100644 test/jsonc.test.ts delete mode 100644 test/jsontestsuite.test.ts diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 86381d6..dfa7b49 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,25 +26,3 @@ jobs: - run: npm i - run: npm run build --if-present - run: npm test - - build-go: - - strategy: - fail-fast: false - matrix: - os: [ubuntu-latest, windows-latest, macos-latest] - - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v4 - - name: Set up Go - uses: actions/setup-go@v5 - with: - go-version: '1.24' - - name: Build - working-directory: go - run: go build ./... - - name: Test - working-directory: go - run: go test -v ./... diff --git a/.gitignore b/.gitignore index aa45c2f..e6358a0 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,3 @@ dist-test package-lock.json yarn.lock - -# Go -go/vendor/ diff --git a/Makefile b/Makefile index 3558e3d..137b5db 100644 --- a/Makefile +++ b/Makefile @@ -1,55 +1,15 @@ -.PHONY: all build test clean embed build-ts build-go test-ts test-go clean-ts clean-go publish-go tags-go tidy-go reset +.PHONY: all build test clean reset all: build test -build: build-ts build-go - -test: test-ts test-go - -clean: clean-ts clean-go - -# Embed jsonc-grammar.jsonic into src/jsonc.ts and go/jsonc.go. -embed: - node embed-grammar.js - -# TypeScript -build-ts: +build: npm run build -test-ts: +test: npm test -clean-ts: +clean: rm -rf dist dist-test -# Go -build-go: embed - cd go && go build ./... - -test-go: - cd go && go test ./... - -clean-go: - cd go && go clean -cache - -# Publish Go module: make publish-go V=0.1.1 -publish-go: test-go - @test -n "$(V)" || (echo "Usage: make publish-go V=x.y.z" && exit 1) - sed -i '' 's/^const Version = ".*"/const Version = "$(V)"/' go/jsonc.go - git add go/jsonc.go - git commit -m "go: v$(V)" - git tag go/v$(V) - git push origin main go/v$(V) - if command -v gh >/dev/null 2>&1; then gh release create go/v$(V) --title "go/v$(V)" --notes "Go module release v$(V)"; fi - -tidy-go: - cd go && go mod tidy - -tags-go: - git tag -l 'go/v*' --sort=-version:refname - reset: npm run reset - cd go && go clean -cache - cd go && go build ./... - cd go && go test -v ./... diff --git a/README.md b/README.md index c722c0e..9ab6c13 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,15 @@ -# @jsonic/jsonc +# @jsonic/feed This plugin allows the [Jsonic](https://jsonic.senecajs.org) JSON parser -to parse [JSONC](https://github.com/microsoft/node-jsonc-parser) format -files (JSON with Comments). +(via [`@jsonic/xml`](https://github.com/jsonicjs/xml)) to parse +syndication feeds — **RSS 0.90, 0.91, 0.92, 1.0, 2.0** and **Atom 0.3, +1.0** — into a typed structure. By default every dialect is normalised +to an Atom-shaped result; pass `format: 'native'` to keep the source +dialect's structure, or `format: 'raw'` to get back the underlying +`XmlElement` tree from `@jsonic/xml`. -JSONC is a strict superset of JSON that adds single-line (`//`) and -block (`/* */`) comments. Trailing commas in objects and arrays can be -optionally enabled. - -[![npm version](https://img.shields.io/npm/v/@jsonic/jsonc.svg)](https://npmjs.com/package/@jsonic/jsonc) -[![build](https://github.com/jsonicjs/jsonc/actions/workflows/build.yml/badge.svg)](https://github.com/jsonicjs/jsonc/actions/workflows/build.yml) -[![Coverage Status](https://coveralls.io/repos/github/jsonicjs/jsonc/badge.svg?branch=main)](https://coveralls.io/github/jsonicjs/jsonc?branch=main) -[![Known Vulnerabilities](https://snyk.io/test/github/jsonicjs/jsonc/badge.svg)](https://snyk.io/test/github/jsonicjs/jsonc) +[![npm version](https://img.shields.io/npm/v/@jsonic/feed.svg)](https://npmjs.com/package/@jsonic/feed) +[![build](https://github.com/jsonicjs/feed/actions/workflows/build.yml/badge.svg)](https://github.com/jsonicjs/feed/actions/workflows/build.yml) | ![Voxgig](https://www.voxgig.com/res/img/vgt01r.png) | This open source module is sponsored and supported by [Voxgig](https://www.voxgig.com). | @@ -24,218 +22,240 @@ The documentation below is organized along the - [Quick start](#quick-start) — tutorial - [How-to guides](#how-to-guides) — task recipes - [Reference](#reference) — API surface -- [JSONC format](#jsonc-format) — explanation +- [Format mapping](#format-mapping) — explanation ## Quick start -### TypeScript - Install: ```bash -npm install @jsonic/jsonc @jsonic/jsonic-next +npm install @jsonic/feed jsonic @jsonic/xml ``` -Parse: +Parse a feed in any supported dialect — the result is an Atom-shaped +object regardless of input format: ```typescript -import { Jsonic } from '@jsonic/jsonic-next' -import { Jsonc } from '@jsonic/jsonc' - -const j = Jsonic.make().use(Jsonc) - -const result = j('{ "name": "app", /* version */ "version": "1.0" }') -// => { name: 'app', version: '1.0' } -``` - -### Go - -Install: - -```bash -go get github.com/jsonicjs/jsonc/go +import { parseFeed } from '@jsonic/feed' + +const atom = parseFeed(` + + + My Blog + https://example.com/ + Posts + + Hello + https://example.com/1 + https://example.com/1 + Wed, 13 Dec 2003 18:30:02 GMT + + + +`) + +// atom.format === 'atom' +// atom.title.value === 'My Blog' +// atom.entries[0].id === 'https://example.com/1' +// atom.entries[0].links[0] === { href: 'https://example.com/1', rel: 'alternate' } ``` -Parse: +Or wire it into a Jsonic instance via the plugin form, which adds a +`feed(src)` method: -```go -package main - -import ( - "fmt" - jsonic "github.com/jsonicjs/jsonic/go" - jsonc "github.com/jsonicjs/jsonc/go" -) - -func main() { - j := jsonic.Make() - j.Use(jsonc.Jsonc) +```typescript +import { Jsonic } from 'jsonic' +import { Feed } from '@jsonic/feed' - result, err := j.Parse(`{ "name": "app", /* version */ "version": "1.0" }`) - if err != nil { - panic(err) - } - fmt.Println(result) - // => map[name:app version:1.0] -} +const j = Jsonic.make().use(Feed) +const atom = j.feed(rssSource) ``` ## How-to guides -### Allow trailing commas - -TypeScript: +### Keep the source dialect's structure (no Atom conversion) ```typescript -const j = Jsonic.make().use(Jsonc, { allowTrailingComma: true }) -j('{ "debug": true, "verbose": false, }') -// => { debug: true, verbose: false } -``` - -Go: +import { parseFeed, type Rss2Feed } from '@jsonic/feed' -```go -j := jsonic.Make() -j.Use(jsonc.Jsonc, map[string]any{"allowTrailingComma": true}) -result, _ := j.Parse(`{ "debug": true, "verbose": false, }`) +const native = parseFeed(rssSource, { format: 'native' }) as Rss2Feed +// native.format === 'rss' +// native.version === '2.0' +// native.items[0].guid?.value === 'item-1-guid' ``` -### Parse strict JSON (disable comments) +The native return type is a discriminated union on `format`: -TypeScript: +| Input dialect | Native return type | `format` | `version` | +|---------------------|--------------------|-----------|-------------------| +| Atom 1.0 / Atom 0.3 | `AtomFeed` | `'atom'` | `'1.0'` / `'0.3'` | +| RSS 2.0 / 0.92 / 0.91 | `Rss2Feed` | `'rss'` | `'2.0'` / `'0.92'` / `'0.91'` | +| RSS 1.0 / 0.90 | `Rss1Feed` | `'rdf'` | `'1.0'` / `'0.90'` | -```typescript -const j = Jsonic.make().use(Jsonc, { disallowComments: true }) -j('{ "foo": /* not allowed */ true }') // throws -``` +### Get the raw XML tree -Go: +```typescript +import { parseFeed } from '@jsonic/feed' -```go -j := jsonic.Make() -j.Use(jsonc.Jsonc, map[string]any{"disallowComments": true}) +const tree = parseFeed(rssSource, { format: 'raw' }) +// tree.localName === 'rss' +// tree.children === [...] ``` -### Handle parse errors +This is the `XmlElement` produced by `@jsonic/xml` with no further +processing, useful when you want to handle non-standard extensions. -TypeScript — parse errors throw: +### Detect a dialect without converting ```typescript -try { - j('{ "bad": }') -} catch (err) { - console.error(err.message) -} -``` - -Go — errors are returned: +import { Jsonic } from 'jsonic' +import { Xml } from '@jsonic/xml' +import { detect } from '@jsonic/feed' -```go -if _, err := j.Parse(`{ "bad": }`); err != nil { - fmt.Println(err) -} +const root = Jsonic.make().use(Xml)(rssSource) +const { dialect, version } = detect(root) +// e.g. { dialect: 'rss', version: 'rss20' } ``` -### Parse a file +### Configure the plugin form -TypeScript: +The plugin's options are set once at `use()` time: ```typescript -import { readFileSync } from 'node:fs' -const j = Jsonic.make().use(Jsonc, { allowTrailingComma: true }) -const config = j(readFileSync('tsconfig.json', 'utf8')) -``` +import { Jsonic } from 'jsonic' +import { Feed } from '@jsonic/feed' -Go: - -```go -src, _ := os.ReadFile("tsconfig.json") -j := jsonic.Make() -j.Use(jsonc.Jsonc, map[string]any{"allowTrailingComma": true}) -config, _ := j.Parse(string(src)) +const j = Jsonic.make().use(Feed, { format: 'native' }) +const native = j.feed(rssSource) ``` ## Reference -### TypeScript - ```typescript -function Jsonc(jsonic: Jsonic, options?: JsoncOptions): void +function parseFeed(src: string, options?: FeedOptions): FeedResult +function detect(root: XmlElement): { dialect: FeedDialect; version: FeedVersion } +const Feed: Plugin -type JsoncOptions = { - allowTrailingComma?: boolean // default: false - disallowComments?: boolean // default: false +type FeedOptions = { + format?: 'atom' | 'native' | 'raw' // default: 'atom' } -``` -Register with `jsonic.use(Jsonc, options?)`. After registration, invoke -the jsonic instance as a function on a source string; it returns the -parsed value or throws on syntax errors. +type FeedResult = AtomFeed | Rss2Feed | Rss1Feed | XmlElement -| Option | Type | Default | Effect | -|--------|------|---------|--------| -| `allowTrailingComma` | `boolean` | `false` | Permit a trailing comma before `}` and `]` | -| `disallowComments` | `boolean` | `false` | Reject `//` and `/* */` comments (strict JSON) | +type FeedDialect = 'atom' | 'rss' | 'rdf' | 'unknown' -### Go - -```go -func Jsonc(j *jsonic.Jsonic, pluginOpts map[string]any) error +type FeedVersion = + | 'atom10' | 'atom03' + | 'rss20' | 'rss092' | 'rss091u' | 'rss091n' + | 'rss10' | 'rss090' + | 'unknown' ``` -Register with `j.Use(jsonc.Jsonc)` or `j.Use(jsonc.Jsonc, opts)` where -`opts` is a `map[string]any`. `Parse` then returns `(any, error)` — -`map[string]any` for objects, `[]any` for arrays, `float64` for numbers, -`string`, `bool`, or `nil`. - -| Key | Type | Default | Effect | -|-----|------|---------|--------| -| `allowTrailingComma` | `bool` | `false` | Permit a trailing comma before `}` and `]` | -| `disallowComments` | `bool` | `false` | Reject `//` and `/* */` comments (strict JSON) | +Atom shape (the default output) follows RFC 4287 closely: +```typescript +type AtomFeed = { + format: 'atom' + version: '1.0' | '0.3' | string + id?: string + title?: AtomText + updated?: string + authors?: AtomPerson[] + contributors?: AtomPerson[] + categories?: AtomCategory[] + generator?: AtomGenerator + icon?: string + logo?: string + rights?: AtomText + subtitle?: AtomText + links?: AtomLink[] + entries: AtomEntry[] +} -## JSONC format - -JSONC follows [RFC 8259](https://tools.ietf.org/html/rfc8259) (JSON) -with these extensions: - -- **Line comments**: `//` to end of line -- **Block comments**: `/* */` (non-nesting) -- **Trailing commas**: optional, in objects and arrays - -All other JSON rules apply: - -- Strings must be double-quoted -- Standard escapes only: `\"` `\\` `\/` `\b` `\f` `\n` `\r` `\t` `\uXXXX` -- Numbers: integer, decimal, scientific notation (no hex, octal, binary) -- Keywords: `true`, `false`, `null` (case-sensitive) -- Property names must be double-quoted strings +type AtomEntry = { + id?: string + title?: AtomText + updated?: string + published?: string + authors?: AtomPerson[] + contributors?: AtomPerson[] + categories?: AtomCategory[] + content?: AtomContent + links?: AtomLink[] + rights?: AtomText + summary?: AtomText + source?: Partial +} -### Conformance notes +type AtomText = { type: 'text' | 'html' | 'xhtml'; value: string } +type AtomPerson = { name: string; uri?: string; email?: string } +type AtomLink = { href: string; rel?: string; type?: string; + hreflang?: string; title?: string; length?: number } +type AtomCategory = { term: string; scheme?: string; label?: string } +type AtomGenerator = { uri?: string; version?: string; value: string } +type AtomContent = { type: string; src?: string; value?: string } +``` -The plugin layers JSONC rules on top of jsonic, which is intentionally -lenient in some places vs. strict RFC 8259. The test suite runs the -[nst/JSONTestSuite](https://github.com/nst/JSONTestSuite) corpus in -strict mode (`disallowComments: true`) and pins the known-lenient -cases in `test/jsontestsuite.test.ts` (see `N_KNOWN_LENIENT`). Examples -of accepted-but-non-RFC input include numbers with leading zeros and -unquoted object keys. Use an RFC-strict parser if byte-perfect RFC 8259 -rejection is required. +The native RSS 2/0.91/0.92 and RSS 1.0/0.90 shapes (`Rss2Feed`, +`Rss2Item`, `Rss1Feed`, `Rss1Item` …) are also exported; see +`src/feed.ts` for the full set. + + +## Format mapping + +When converting any RSS dialect to Atom, the plugin makes the following +best-effort mappings: + +| RSS source | Atom target | +|-------------------------------|----------------------------------------------------| +| `channel/title` | `feed.title` (`type: 'text'`) | +| `channel/description` | `feed.subtitle` (`type: 'text'`) | +| `channel/link` | `feed.id` and `feed.links[]` (`rel: 'alternate'`) | +| `channel/copyright` | `feed.rights` | +| `channel/lastBuildDate` | `feed.updated` | +| `channel/pubDate` | `feed.updated` (fallback) | +| `channel/managingEditor` | `feed.authors[0]` (parsed `email (Name)`) | +| `channel/generator` | `feed.generator.value` | +| `channel/image/url` | `feed.logo` | +| `item/guid` | `entry.id` | +| `item/link` (no `guid`) | `entry.id` (fallback) and `entry.links[]` | +| `item/description` | `entry.summary` (`type: 'html'`) | +| `item/pubDate` | `entry.published` and `entry.updated` | +| `item/author` | `entry.authors[0]` | +| `item/enclosure` | `entry.links[]` with `rel: 'enclosure'` | +| `item/comments` | `entry.links[]` with `rel: 'replies'` | +| `item/category` | `entry.categories[].term` (+ `scheme` from domain) | + +For RDF (RSS 1.0/0.90): + +| RDF source | Atom target | +|-------------------------------|----------------------------------------------------| +| `channel/@rdf:about` | `feed.id` | +| `channel/title` | `feed.title` | +| `channel/description` | `feed.subtitle` | +| `channel/link` | `feed.links[]` (`rel: 'alternate'`) | +| `image/url` | `feed.logo` | +| `item/@rdf:about` | `entry.id` | +| `item/title` | `entry.title` | +| `item/link` | `entry.links[]` (`rel: 'alternate'`) | + +For Atom 0.3 → Atom 1.0 the legacy element names are renamed: +`tagline → subtitle`, `modified → updated`, `issued → published`, +`copyright → rights`. ## Acknowledgments -Conformance testing uses third-party corpora under MIT License: - -- [nst/JSONTestSuite](https://github.com/nst/JSONTestSuite) by Nicolas - Seriot — vendored at `test/JSONTestSuite/` (the `test_parsing/` corpus). -- [microsoft/node-jsonc-parser](https://github.com/microsoft/node-jsonc-parser) — - parse-level test cases ported into `test/jsonc.test.ts`. +Conformance testing uses third-party corpora under permissive licenses +(see [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for full +attribution): -See [THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md) for details. +- [kurtmckee/feedparser](https://github.com/kurtmckee/feedparser) by + Kurt McKee and Mark Pilgrim — a focused subset of well-formed feed + samples is vendored at `test/feedparser-wellformed/`. ## License diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 3362e95..4f99cf9 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -3,48 +3,44 @@ This project incorporates material from the projects listed below. The original copyright notices and license texts are preserved as required. -## nst/JSONTestSuite +## kurtmckee/feedparser -Vendored at `test/JSONTestSuite/` for RFC 8259 conformance testing via -`test/jsontestsuite.test.ts`. Only the `test_parsing/` corpus, `LICENSE`, -and `README.md` from the upstream project are included; the upstream -`LICENSE` is preserved in place. +A focused subset of well-formed feed samples (`atom10`, `atom`, `rss`, +`rdf`) from `tests/wellformed/` of the upstream `kurtmckee/feedparser` +project is vendored at `test/feedparser-wellformed/`. The upstream +`LICENSE` is preserved in place at +`test/feedparser-wellformed/LICENSE`. -- Project: https://github.com/nst/JSONTestSuite -- License: MIT -- Copyright (c) 2016 Nicolas Seriot +- Project: https://github.com/kurtmckee/feedparser +- License: BSD 2-Clause "Simplified" License +- Copyright (C) 2010-2025 Kurt McKee +- Copyright (C) 2002-2008 Mark Pilgrim -## microsoft/node-jsonc-parser - -Parse-level test cases in `test/jsonc.test.ts` were ported from -`src/test/json.test.ts` of `microsoft/node-jsonc-parser`. - -- Project: https://github.com/microsoft/node-jsonc-parser -- License: MIT -- Copyright (c) Microsoft Corporation - ---- - -Both projects are distributed under the MIT License. Full license text: +Full upstream license text: ``` -MIT License - -Permission is hereby granted, free of charge, to any person obtaining a -copy of this software and associated documentation files (the "Software"), -to deal in the Software without restriction, including without limitation -the rights to use, copy, modify, merge, publish, distribute, sublicense, -and/or sell copies of the Software, and to permit persons to whom the -Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR -OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, -ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -OTHER DEALINGS IN THE SOFTWARE. +Copyright (C) 2010-2025 Kurt McKee +Copyright (C) 2002-2008 Mark Pilgrim +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. ``` diff --git a/embed-grammar.js b/embed-grammar.js deleted file mode 100644 index 1188a35..0000000 --- a/embed-grammar.js +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env node - -// Embed jsonc-grammar.jsonic into TypeScript and Go source files. -// Run via: npm run embed (or: node embed-grammar.js) - -const fs = require('fs') -const path = require('path') - -const GRAMMAR_FILE = path.join(__dirname, 'jsonc-grammar.jsonic') -const TS_FILE = path.join(__dirname, 'src', 'jsonc.ts') -const GO_FILE = path.join(__dirname, 'go', 'jsonc.go') - -const BEGIN = '// --- BEGIN EMBEDDED jsonc-grammar.jsonic ---' -const END = '// --- END EMBEDDED jsonc-grammar.jsonic ---' - -const grammar = fs.readFileSync(GRAMMAR_FILE, 'utf8') - -// --- TypeScript embedding --- -function embedTS() { - let src = fs.readFileSync(TS_FILE, 'utf8') - const startIdx = src.indexOf(BEGIN) - const endIdx = src.indexOf(END) - if (startIdx === -1 || endIdx === -1) { - console.error('TS markers not found in', TS_FILE) - process.exit(1) - } - - // Escape backticks and template expressions for a JS template literal. - const escaped = grammar - .replace(/\\/g, '\\\\') - .replace(/`/g, '\\`') - .replace(/\$\{/g, '\\${') - - const replacement = - BEGIN + - '\nconst grammarText = `\n' + - escaped + - '`\n' + - END - - src = src.substring(0, startIdx) + replacement + src.substring(endIdx + END.length) - fs.writeFileSync(TS_FILE, src) - console.log('Embedded grammar into', TS_FILE) -} - -// --- Go embedding --- -function embedGo() { - let src = fs.readFileSync(GO_FILE, 'utf8') - const startIdx = src.indexOf(BEGIN) - const endIdx = src.indexOf(END) - if (startIdx === -1 || endIdx === -1) { - console.error('Go markers not found in', GO_FILE) - process.exit(1) - } - - if (grammar.includes('`')) { - console.error('Grammar contains backticks, incompatible with Go raw strings') - process.exit(1) - } - - const replacement = - BEGIN + - '\nconst grammarText = `\n' + - grammar + - '`\n' + - END - - src = src.substring(0, startIdx) + replacement + src.substring(endIdx + END.length) - fs.writeFileSync(GO_FILE, src) - console.log('Embedded grammar into', GO_FILE) -} - -embedTS() -embedGo() diff --git a/go/go.mod b/go/go.mod deleted file mode 100644 index f58d839..0000000 --- a/go/go.mod +++ /dev/null @@ -1,5 +0,0 @@ -module github.com/jsonicjs/jsonc/go - -go 1.24.7 - -require github.com/jsonicjs/jsonic/go v0.1.22 diff --git a/go/go.sum b/go/go.sum deleted file mode 100644 index 5c34bfc..0000000 --- a/go/go.sum +++ /dev/null @@ -1,2 +0,0 @@ -github.com/jsonicjs/jsonic/go v0.1.22 h1:sam238fTyjDq0nby9TYS+aCCHprLl91ArQPWLCg2O0Y= -github.com/jsonicjs/jsonic/go v0.1.22/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg= diff --git a/go/jsonc.go b/go/jsonc.go deleted file mode 100644 index 3bc74e5..0000000 --- a/go/jsonc.go +++ /dev/null @@ -1,82 +0,0 @@ -/* Copyright (c) 2021-2025 Richard Rodger, MIT License */ - -package jsonc - -import ( - jsonic "github.com/jsonicjs/jsonic/go" -) - -const Version = "0.1.2" - -// --- BEGIN EMBEDDED jsonc-grammar.jsonic --- -const grammarText = ` -# JSONC Grammar Definition -# Parsed by a standard Jsonic instance and passed to jsonic.grammar() -# Extends standard JSON grammar with end-of-input value handling. - -{ - options: text: { lex: false } - options: number: { hex: false oct: false bin: false sep: null exclude: "@/^\\./" } - options: string: { chars: '"' multiChars: '' allowUnknown: false } - options: string: escape: { v: null } - options: map: { extend: false } - options: lex: { empty: false } - options: rule: { finish: false } - - rule: val: open: { - alts: [ - { s: '#ZZ' g: jsonc } - ] - inject: { append: true } - } - - rule: pair: close: { - alts: [ - { s: '#CA #CB' b: 1 g: comma } - ] - inject: {} - } - - rule: elem: close: { - alts: [ - { s: '#CA #CS' b: 1 g: comma } - ] - inject: {} - } -} -` -// --- END EMBEDDED jsonc-grammar.jsonic --- - -// Jsonc configures a jsonic instance for JSONC parsing. -func Jsonc(j *jsonic.Jsonic, pluginOpts map[string]any) error { - commentLex := true != toBool(pluginOpts["disallowComments"]) - ruleExclude := "comma" - if toBool(pluginOpts["allowTrailingComma"]) { - ruleExclude = "" - } - - // Apply grammar: static options, rules, and trailing comma alts. - if err := j.GrammarText(grammarText, &jsonic.GrammarSetting{ - Rule: &jsonic.GrammarSettingRule{ - Alt: &jsonic.GrammarSettingAlt{G: "jsonc"}, - }, - }); err != nil { - return err - } - - // Runtime options that depend on plugin arguments. - j.SetOptions(jsonic.Options{ - Comment: &jsonic.CommentOptions{Lex: &commentLex}, - Rule: &jsonic.RuleOptions{ - Include: "jsonc,json", - Exclude: ruleExclude, - }, - }) - - return nil -} - -func toBool(v any) bool { - b, _ := v.(bool) - return b -} diff --git a/go/jsonc_test.go b/go/jsonc_test.go deleted file mode 100644 index fd93e3f..0000000 --- a/go/jsonc_test.go +++ /dev/null @@ -1,634 +0,0 @@ -/* Copyright (c) 2021-2025 Richard Rodger, MIT License */ - -package jsonc - -import ( - "reflect" - "strings" - "testing" - - jsonic "github.com/jsonicjs/jsonic/go" -) - -func makeJsonc(opts ...map[string]any) *jsonic.Jsonic { - j := jsonic.Make() - if len(opts) > 0 { - j.Use(Jsonc, opts[0]) - } else { - j.Use(Jsonc) - } - return j -} - -func assert(t *testing.T, name string, got, want any) { - t.Helper() - if !reflect.DeepEqual(got, want) { - t.Errorf("%s:\n got: %#v\n want: %#v", name, got, want) - } -} - -func assertError(t *testing.T, name string, err error, contains string) { - t.Helper() - if err == nil { - t.Errorf("%s: expected error containing %q, got nil", name, contains) - return - } - if !strings.Contains(err.Error(), contains) { - t.Errorf("%s: expected error containing %q, got: %v", name, contains, err) - } -} - -var j = makeJsonc() - -func parse(src string) (any, error) { return j.Parse(src) } - -func TestHappy(t *testing.T) { - r, err := parse(`{"a":1}`) - if err != nil { - t.Fatal(err) - } - assert(t, "basic", r, map[string]any{"a": float64(1)}) -} - -func TestComments(t *testing.T) { - r, err := parse("// this is a comment") - if err != nil { - t.Fatal(err) - } - assert(t, "single-line", r, nil) - - r, err = parse("// this is a comment\n") - if err != nil { - t.Fatal(err) - } - assert(t, "single-line-newline", r, nil) - - r, err = parse("/* this is a comment*/") - if err != nil { - t.Fatal(err) - } - assert(t, "block", r, nil) - - r, err = parse("/* this is a \r\ncomment*/") - if err != nil { - t.Fatal(err) - } - assert(t, "block-crlf", r, nil) - - r, err = parse("/* this is a \ncomment*/") - if err != nil { - t.Fatal(err) - } - assert(t, "block-lf", r, nil) - - _, err = parse("/* this is a") - assertError(t, "unterminated-block", err, "unterminated_comment") - - _, err = parse("/* this is a \ncomment") - assertError(t, "unterminated-block-multiline", err, "unterminated_comment") - - _, err = parse("/ ttt") - assertError(t, "invalid-comment", err, "unexpected") -} - -func TestStrings(t *testing.T) { - r, err := parse(`"test"`) - if err != nil { - t.Fatal(err) - } - assert(t, "simple", r, "test") - - r, _ = parse(`"\""`) - assert(t, "escape-quote", r, `"`) - - r, _ = parse(`"\/"`) - assert(t, "escape-slash", r, "/") - - r, _ = parse(`"\b"`) - assert(t, "escape-backspace", r, "\b") - - r, _ = parse(`"\f"`) - assert(t, "escape-formfeed", r, "\f") - - r, _ = parse(`"\n"`) - assert(t, "escape-newline", r, "\n") - - r, _ = parse(`"\r"`) - assert(t, "escape-return", r, "\r") - - r, _ = parse(`"\t"`) - assert(t, "escape-tab", r, "\t") - - r, _ = parse(`"\u00DC"`) - assert(t, "unicode", r, "\u00DC") - - // Note: \v is accepted by the jsonic Go string matcher as a built-in escape. - // This is a minor deviation from strict JSONC spec which only allows - // \", \\, \/, \b, \f, \n, \r, \t, and \uXXXX. - - _, err = parse(`"test`) - assertError(t, "unterminated", err, "unterminated_string") -} - -func TestNumbers(t *testing.T) { - r, _ := parse("0") - assert(t, "zero", r, float64(0)) - - r, _ = parse("0.1") - assert(t, "decimal", r, 0.1) - - r, _ = parse("-0.1") - assert(t, "neg-decimal", r, -0.1) - - r, _ = parse("-1") - assert(t, "neg", r, float64(-1)) - - r, _ = parse("1") - assert(t, "one", r, float64(1)) - - r, _ = parse("123456789") - assert(t, "large", r, float64(123456789)) - - r, _ = parse("10") - assert(t, "ten", r, float64(10)) - - r, _ = parse("90") - assert(t, "ninety", r, float64(90)) - - r, _ = parse("90E+123") - assert(t, "sci-upper-plus", r, 90E+123) - - r, _ = parse("90e+123") - assert(t, "sci-lower-plus", r, 90e+123) - - r, _ = parse("90e-123") - assert(t, "sci-lower-minus", r, 90e-123) - - r, _ = parse("90E-123") - assert(t, "sci-upper-minus", r, 90E-123) - - r, _ = parse("90E123") - assert(t, "sci-upper", r, 90E123) - - r, _ = parse("90e123") - assert(t, "sci-lower", r, 90e123) - - _, err := parse("-") - if err == nil { - t.Error("expected error for bare minus") - } - - _, err = parse(".0") - if err == nil { - t.Error("expected error for leading dot number") - } -} - -func TestKeywords(t *testing.T) { - r, _ := parse("true") - assert(t, "true", r, true) - - r, _ = parse("false") - assert(t, "false", r, false) - - r, _ = parse("null") - assert(t, "null", r, nil) - - _, err := parse("True") - if err == nil { - t.Error("expected error for capitalized True") - } - - r, _ = parse("false//hello") - assert(t, "value-with-comment", r, false) -} - -func TestTrivia(t *testing.T) { - r, _ := parse(" ") - assert(t, "space", r, nil) - - r, _ = parse(" \t ") - assert(t, "tabs", r, nil) - - r, _ = parse(" \t \n \t ") - assert(t, "tabs-newlines", r, nil) - - r, _ = parse("\r\n") - assert(t, "crlf", r, nil) - - r, _ = parse("\r") - assert(t, "cr", r, nil) - - r, _ = parse("\n") - assert(t, "lf", r, nil) - - r, _ = parse("\n\r") - assert(t, "lfcr", r, nil) - - r, _ = parse("\n \n") - assert(t, "newlines-spaces", r, nil) -} - -func TestLiterals(t *testing.T) { - r, _ := parse("true") - assert(t, "true", r, true) - - r, _ = parse("false") - assert(t, "false", r, false) - - r, _ = parse("null") - assert(t, "null", r, nil) - - r, _ = parse(`"foo"`) - assert(t, "string", r, "foo") - - r, _ = parse(`"\"-\\-\/-\b-\f-\n-\r-\t"`) - assert(t, "escapes", r, "\"-\\-/-\b-\f-\n-\r-\t") - - r, _ = parse(`"\u00DC"`) - assert(t, "unicode", r, "\u00DC") - - r, _ = parse("9") - assert(t, "nine", r, float64(9)) - - r, _ = parse("-9") - assert(t, "neg-nine", r, float64(-9)) - - r, _ = parse("0.129") - assert(t, "decimal", r, 0.129) - - r, _ = parse("23e3") - assert(t, "sci", r, 23e3) - - r, _ = parse("1.2E+3") - assert(t, "sci-plus", r, 1.2E+3) - - r, _ = parse("1.2E-3") - assert(t, "sci-minus", r, 1.2E-3) - - r, _ = parse("1.2E-3 // comment") - assert(t, "num-comment", r, 1.2E-3) -} - -func TestObjects(t *testing.T) { - r, _ := parse("{}") - assert(t, "empty", r, map[string]any{}) - - r, _ = parse(`{ "foo": true }`) - assert(t, "one-field", r, map[string]any{"foo": true}) - - r, _ = parse(`{ "bar": 8, "xoo": "foo" }`) - assert(t, "two-fields", r, map[string]any{"bar": float64(8), "xoo": "foo"}) - - r, _ = parse(`{ "hello": [], "world": {} }`) - assert(t, "empty-nested", r, map[string]any{"hello": []any{}, "world": map[string]any{}}) - - r, _ = parse(`{ "a": false, "b": true, "c": [ 7.4 ] }`) - assert(t, "mixed", r, map[string]any{"a": false, "b": true, "c": []any{7.4}}) - - r, _ = parse(`{ "hello": { "again": { "inside": 5 }, "world": 1 }}`) - assert(t, "deep-nested", r, map[string]any{ - "hello": map[string]any{ - "again": map[string]any{"inside": float64(5)}, - "world": float64(1), - }, - }) - - r, _ = parse(`{ "foo": /*hello*/true }`) - assert(t, "comment-in-obj", r, map[string]any{"foo": true}) - - r, _ = parse(`{ "": true }`) - assert(t, "empty-key", r, map[string]any{"": true}) -} - -func TestArrays(t *testing.T) { - r, _ := parse("[]") - assert(t, "empty", r, []any{}) - - r, _ = parse("[ [], [ [] ]]") - assert(t, "nested-empty", r, []any{[]any{}, []any{[]any{}}}) - - r, _ = parse("[ 1, 2, 3 ]") - assert(t, "numbers", r, []any{float64(1), float64(2), float64(3)}) - - r, _ = parse(`[ { "a": null } ]`) - assert(t, "obj-in-array", r, []any{map[string]any{"a": nil}}) -} - -func TestObjectErrors(t *testing.T) { - _, err := parse("{,}") - if err == nil { - t.Error("expected error for leading comma in object") - } - - _, err = parse(`{ "foo": true, }`) - if err == nil { - t.Error("expected error for trailing comma in object (default)") - } - - _, err = parse(`{ "bar": 8 "xoo": "foo" }`) - if err == nil { - t.Error("expected error for missing comma in object") - } - - _, err = parse(`{ ,"bar": 8 }`) - if err == nil { - t.Error("expected error for leading comma") - } - - _, err = parse(`{ "bar": 8, "foo": }`) - if err == nil { - t.Error("expected error for missing value") - } - - _, err = parse(`{ 8, "foo": 9 }`) - if err == nil { - t.Error("expected error for number as key") - } -} - -func TestArrayErrors(t *testing.T) { - _, err := parse("[,]") - if err == nil { - t.Error("expected error for leading comma in array") - } - - _, err = parse("[ 1 2, 3 ]") - if err == nil { - t.Error("expected error for missing comma in array") - } - - _, err = parse("[ ,1, 2, 3 ]") - if err == nil { - t.Error("expected error for leading comma in array") - } - - _, err = parse("[ ,1, 2, 3, ]") - if err == nil { - t.Error("expected error for commas in array") - } -} - -func TestErrors(t *testing.T) { - _, err := parse("1,1") - if err == nil { - t.Error("expected error for extra content after value") - } - - _, err = parse("") - if err == nil { - t.Error("expected error for empty input") - } -} - -func TestDisallowComments(t *testing.T) { - nc := makeJsonc(map[string]any{"disallowComments": true}) - - r, err := nc.Parse(`[ 1, 2, null, "foo" ]`) - if err != nil { - t.Fatal(err) - } - assert(t, "array", r, []any{float64(1), float64(2), nil, "foo"}) - - r, err = nc.Parse(`{ "hello": [], "world": {} }`) - if err != nil { - t.Fatal(err) - } - assert(t, "object", r, map[string]any{"hello": []any{}, "world": map[string]any{}}) - - _, err = nc.Parse(`{ "foo": /*comment*/ true }`) - if err == nil { - t.Error("expected error for comment when comments are disallowed") - } -} - -func TestTrailingComma(t *testing.T) { - jc := makeJsonc(map[string]any{"allowTrailingComma": true}) - - r, err := jc.Parse(`{ "hello": [], }`) - if err != nil { - t.Fatal(err) - } - assert(t, "obj-trailing", r, map[string]any{"hello": []any{}}) - - r, err = jc.Parse(`{ "hello": [] }`) - if err != nil { - t.Fatal(err) - } - assert(t, "obj-no-trailing", r, map[string]any{"hello": []any{}}) - - r, err = jc.Parse(`{ "hello": [], "world": {}, }`) - if err != nil { - t.Fatal(err) - } - assert(t, "obj-multi-trailing", r, map[string]any{"hello": []any{}, "world": map[string]any{}}) - - r, err = jc.Parse(`[ 1, 2, ]`) - if err != nil { - t.Fatal(err) - } - assert(t, "arr-trailing", r, []any{float64(1), float64(2)}) - - r, err = jc.Parse(`[ 1, 2 ]`) - if err != nil { - t.Fatal(err) - } - assert(t, "arr-no-trailing", r, []any{float64(1), float64(2)}) - - // Default parser should reject trailing commas. - _, err = j.Parse(`{ "hello": [], }`) - if err == nil { - t.Error("expected error for trailing comma with default options") - } - - _, err = j.Parse(`[ 1, 2, ]`) - if err == nil { - t.Error("expected error for trailing comma in array with default options") - } -} - -func TestMisc(t *testing.T) { - r, _ := j.Parse(`{ "foo": "bar" }`) - assert(t, "simple-obj", r, map[string]any{"foo": "bar"}) - - r, _ = j.Parse(`{ "foo": {"bar": 1, "car": 2 } }`) - assert(t, "nested-obj", r, map[string]any{ - "foo": map[string]any{"bar": float64(1), "car": float64(2)}, - }) - - r, _ = j.Parse(`{ "foo": {"bar": 1, "car": 8 }, "goo": {} }`) - assert(t, "multi-nested", r, map[string]any{ - "foo": map[string]any{"bar": float64(1), "car": float64(8)}, - "goo": map[string]any{}, - }) - - _, err := j.Parse(`{ "dep": {"bar": 1, "car": `) - if err == nil { - t.Error("expected error for unterminated object") - } - - _, err = j.Parse(`{ "dep": {"bar": 1,, "car": `) - if err == nil { - t.Error("expected error for double comma") - } - - _, err = j.Parse(`{ "dep": {"bar": "na", "dar": "ma", "car": } }`) - if err == nil { - t.Error("expected error for missing value") - } - - r, _ = j.Parse(`["foo", null ]`) - assert(t, "arr-mixed", r, []any{"foo", nil}) - - _, err = j.Parse(`["foo", null, ]`) - if err == nil { - t.Error("expected error for trailing comma in array") - } - - _, err = j.Parse(`["foo", null,, ]`) - if err == nil { - t.Error("expected error for double comma in array") - } - - r, _ = j.Parse("true") - assert(t, "bare-true", r, true) - - r, _ = j.Parse("false") - assert(t, "bare-false", r, false) - - r, _ = j.Parse("null") - assert(t, "bare-null", r, nil) - - r, _ = j.Parse("23") - assert(t, "bare-num", r, float64(23)) - - r, _ = j.Parse("-1.93e-19") - assert(t, "sci-notation", r, -1.93e-19) - - r, _ = j.Parse(`"hello"`) - assert(t, "bare-string", r, "hello") - - r, _ = j.Parse("[]") - assert(t, "empty-arr", r, []any{}) - - r, _ = j.Parse("[ 1 ]") - assert(t, "single-arr", r, []any{float64(1)}) - - r, _ = j.Parse(`[ 1, "x"]`) - assert(t, "mixed-arr", r, []any{float64(1), "x"}) - - r, _ = j.Parse("[[]]") - assert(t, "nested-arr", r, []any{[]any{}}) - - r, _ = j.Parse("{ }") - assert(t, "empty-obj", r, map[string]any{}) - - r, _ = j.Parse(`{ "val": 1 }`) - assert(t, "val-obj", r, map[string]any{"val": float64(1)}) - - r, _ = j.Parse(`{"id": "$", "v": [ null, null] }`) - assert(t, "complex-obj", r, map[string]any{"id": "$", "v": []any{nil, nil}}) - - _, err = j.Parse(`{ "id": { "foo": { } } , }`) - if err == nil { - t.Error("expected error for trailing comma") - } - - r, _ = j.Parse(`{ "foo": { "goo": 3 } }`) - assert(t, "nested-num", r, map[string]any{"foo": map[string]any{"goo": float64(3)}}) - - r, _ = j.Parse("[\r\n0,\r\n1,\r\n2\r\n]") - assert(t, "crlf-arr", r, []any{float64(0), float64(1), float64(2)}) - - r, _ = j.Parse(`/* g */ { "foo": //f` + "\n" + `"bar" }`) - assert(t, "comments-mixed", r, map[string]any{"foo": "bar"}) - - r, _ = j.Parse("/* g\r\n */ { \"foo\": //f\n\"bar\" }") - assert(t, "comments-crlf", r, map[string]any{"foo": "bar"}) - - r, _ = j.Parse("/* g\n */ { \"foo\": //f\n\"bar\"\n}") - assert(t, "comments-lf", r, map[string]any{"foo": "bar"}) - - r, _ = j.Parse(`{ "key1": { "key11": [ "val111", "val112" ] }, "key2": [ { "key21": false, "key22": 221 }, null, [{}] ] }`) - assert(t, "complex", r, map[string]any{ - "key1": map[string]any{"key11": []any{"val111", "val112"}}, - "key2": []any{ - map[string]any{"key21": false, "key22": float64(221)}, - nil, - []any{map[string]any{}}, - }, - }) -} - -func TestUsePlugin(t *testing.T) { - j := makeJsonc() - result, err := j.Parse(`{"a": 1, "b": "hello"}`) - if err != nil { - t.Fatal(err) - } - m, ok := result.(map[string]any) - if !ok { - t.Fatalf("expected map, got %T", result) - } - assert(t, "plugin", m, map[string]any{"a": float64(1), "b": "hello"}) -} - -// TestAltGJsoncTag verifies the GrammarText setting {Rule:{Alt:{G:'jsonc'}}} -// tagged every alt installed by the jsonc plugin with 'jsonc'. -func TestAltGJsoncTag(t *testing.T) { - // Fresh instance with allowTrailingComma so pair/elem close alts survive - // the rule-exclude filter and can be inspected here. - jc := jsonic.Make() - if err := jc.Use(Jsonc, map[string]any{"allowTrailingComma": true}); err != nil { - t.Fatal(err) - } - - rsm := jc.RSM() - checks := []struct { - rule string - isOpen bool - tokSig string - }{ - {"val", true, "#ZZ"}, - {"pair", false, "#CA #CB"}, - {"elem", false, "#CA #CS"}, - } - - for _, c := range checks { - rs, ok := rsm[c.rule] - if !ok { - t.Errorf("rule %q missing", c.rule) - continue - } - alts := rs.Close - if c.isOpen { - alts = rs.Open - } - - found := false - for _, a := range alts { - if !strings.Contains(a.G, "jsonc") { - continue - } - // Match the alt introduced by this plugin by its group tag(s). - // We only need to confirm 'jsonc' is present on at least one alt - // per rule; more importantly, every alt tagged as coming from - // the plugin must carry 'jsonc'. - found = true - tags := strings.Split(a.G, ",") - has := false - for _, t := range tags { - if strings.TrimSpace(t) == "jsonc" { - has = true - break - } - } - if !has { - t.Errorf("rule %q alt missing 'jsonc' tag: g=%q", c.rule, a.G) - } - } - if !found { - t.Errorf("rule %q: no alt with 'jsonc' tag found", c.rule) - } - } -} diff --git a/jsonc-grammar.jsonic b/jsonc-grammar.jsonic deleted file mode 100644 index 092da2f..0000000 --- a/jsonc-grammar.jsonic +++ /dev/null @@ -1,34 +0,0 @@ -# JSONC Grammar Definition -# Parsed by a standard Jsonic instance and passed to jsonic.grammar() -# Extends standard JSON grammar with end-of-input value handling. - -{ - options: text: { lex: false } - options: number: { hex: false oct: false bin: false sep: null exclude: "@/^\\./" } - options: string: { chars: '"' multiChars: '' allowUnknown: false } - options: string: escape: { v: null } - options: map: { extend: false } - options: lex: { empty: false } - options: rule: { finish: false } - - rule: val: open: { - alts: [ - { s: '#ZZ' g: jsonc } - ] - inject: { append: true } - } - - rule: pair: close: { - alts: [ - { s: '#CA #CB' b: 1 g: comma } - ] - inject: {} - } - - rule: elem: close: { - alts: [ - { s: '#CA #CS' b: 1 g: comma } - ] - inject: {} - } -} diff --git a/package.json b/package.json index 47f2670..09f74d7 100644 --- a/package.json +++ b/package.json @@ -1,26 +1,27 @@ { - "name": "@jsonic/jsonc", - "version": "0.8.0", - "description": "This plugin allows the Jsonic JSON parser to support JSONC syntax.", + "name": "@jsonic/feed", + "version": "0.1.0", + "description": "Parses RSS (0.90, 0.91, 0.92, 1.0, 2.0) and Atom (0.3, 1.0) feeds into a typed structure, defaulting to a normalized Atom shape.", "author": "Richard Rodger (http://richardrodger.com)", "license": "MIT", - "main": "dist/jsonc.js", - "types": "dist/jsonc.d.ts", - "homepage": "https://github.com/jsonicjs/jsonc", - "repository": "github:jsonicjs/jsonc", + "main": "dist/feed.js", + "types": "dist/feed.d.ts", + "homepage": "https://github.com/jsonicjs/feed", + "repository": "github:jsonicjs/feed", "keywords": [ - "jsonc", - "json", - "comments", + "rss", + "atom", + "rdf", + "feed", "parser", - "jsonic" + "jsonic", + "xml" ], "scripts": { "test": "node --enable-source-maps --test \"dist-test/*.test.js\"", "test-some": "node --enable-source-maps --test-name-pattern=\"$npm_config_pattern\" --test \"dist-test/*.test.js\"", - "embed": "node embed-grammar.js", "watch": "tsc --build src test -w", - "build": "node embed-grammar.js && tsc --build src test", + "build": "tsc --build src test", "clean": "rm -rf dist dist-test node_modules yarn.lock package-lock.json", "reset": "npm run clean && npm i && npm run build && npm test", "repo-tag": "REPO_VERSION=`node -e \"console.log(require('./package').version)\"` && echo TAG: v$REPO_VERSION && git commit -a -m v$REPO_VERSION && git push && git tag v$REPO_VERSION && git push --tags;", @@ -28,10 +29,13 @@ "repo-publish-quick": "npm run build && npm run test && npm run repo-tag && npm publish --access public --registry https://registry.npmjs.org " }, "peerDependencies": { - "jsonic": ">=2" + "jsonic": "^2.28.0", + "@jsonic/xml": "^0.1.1" }, "devDependencies": { + "@jsonic/xml": "^0.1.1", "@types/node": "25.6.0", + "jsonic": "^2.28.0", "typescript": "6.0.3" }, "files": [ diff --git a/src/feed.ts b/src/feed.ts new file mode 100644 index 0000000..dba6783 --- /dev/null +++ b/src/feed.ts @@ -0,0 +1,981 @@ +/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */ + +// Plugin that parses RSS (0.90, 0.91, 0.92, 1.0, 2.0) and Atom (0.3, 1.0) +// feeds. Built on top of @jsonic/xml. By default all feed dialects are +// converted to a normalized Atom-shaped result; pass `{ format: 'native' }` +// to keep the source dialect's structure, or `{ format: 'raw' }` to get +// back the underlying XmlElement tree from @jsonic/xml. + +import { Jsonic, Plugin } from 'jsonic' +import { Xml } from '@jsonic/xml' +import type { XmlElement } from '@jsonic/xml' + + +// --- Public types --------------------------------------------------------- + +type FeedFormat = 'atom' | 'native' | 'raw' + +type FeedDialect = 'atom' | 'rss' | 'rdf' | 'unknown' + +type FeedVersion = + | 'atom10' + | 'atom03' + | 'rss20' + | 'rss092' + | 'rss091u' + | 'rss091n' + | 'rss10' + | 'rss090' + | 'unknown' + +type FeedOptions = { + // Output shape: + // 'atom' - normalized Atom-shaped object (the default) + // 'native' - dialect-specific structure (Atom*/Rss2*/Rss1*) + // 'raw' - the XmlElement tree from @jsonic/xml + format?: FeedFormat +} + +// Atom (RFC 4287) ---------------------------------------------------------- + +type AtomText = { + type: 'text' | 'html' | 'xhtml' + value: string +} + +type AtomPerson = { + name: string + uri?: string + email?: string +} + +type AtomLink = { + href: string + rel?: string + type?: string + hreflang?: string + title?: string + length?: number +} + +type AtomCategory = { + term: string + scheme?: string + label?: string +} + +type AtomGenerator = { + uri?: string + version?: string + value: string +} + +type AtomContent = { + type: string + src?: string + value?: string +} + +type AtomEntry = { + id?: string + title?: AtomText + updated?: string + published?: string + authors?: AtomPerson[] + contributors?: AtomPerson[] + categories?: AtomCategory[] + content?: AtomContent + links?: AtomLink[] + rights?: AtomText + summary?: AtomText + source?: Partial +} + +type AtomFeed = { + format: 'atom' + version: '1.0' | '0.3' | string + id?: string + title?: AtomText + updated?: string + authors?: AtomPerson[] + contributors?: AtomPerson[] + categories?: AtomCategory[] + generator?: AtomGenerator + icon?: string + logo?: string + rights?: AtomText + subtitle?: AtomText + links?: AtomLink[] + entries: AtomEntry[] +} + +// RSS 2.0 / 0.92 / 0.91 ---------------------------------------------------- + +type Rss2Category = { + domain?: string + value: string +} + +type Rss2Enclosure = { + url: string + length?: number + type?: string +} + +type Rss2Guid = { + isPermaLink?: boolean + value: string +} + +type Rss2Source = { + url?: string + value: string +} + +type Rss2Image = { + url: string + title: string + link: string + width?: number + height?: number + description?: string +} + +type Rss2Cloud = { + domain: string + port: number + path: string + registerProcedure: string + protocol: string +} + +type Rss2TextInput = { + title: string + description: string + name: string + link: string +} + +type Rss2Item = { + title?: string + link?: string + description?: string + author?: string + categories?: Rss2Category[] + comments?: string + enclosure?: Rss2Enclosure + guid?: Rss2Guid + pubDate?: string + source?: Rss2Source +} + +type Rss2Feed = { + format: 'rss' + version: '2.0' | '0.92' | '0.91' | string + title: string + link: string + description: string + language?: string + copyright?: string + managingEditor?: string + webMaster?: string + pubDate?: string + lastBuildDate?: string + categories?: Rss2Category[] + generator?: string + docs?: string + cloud?: Rss2Cloud + ttl?: number + image?: Rss2Image + textInput?: Rss2TextInput + skipHours?: number[] + skipDays?: string[] + items: Rss2Item[] +} + +// RSS 1.0 / 0.90 (RDF) ----------------------------------------------------- + +type Rss1Item = { + about?: string + title: string + link: string + description?: string +} + +type Rss1Image = { + about?: string + title: string + link: string + url: string +} + +type Rss1TextInput = { + about?: string + title: string + description: string + name: string + link: string +} + +type Rss1Feed = { + format: 'rdf' + version: '1.0' | '0.90' | string + about?: string + title: string + link: string + description?: string + image?: Rss1Image + textInput?: Rss1TextInput + items: Rss1Item[] +} + +type FeedResult = AtomFeed | Rss2Feed | Rss1Feed | XmlElement + + +// --- Namespaces ----------------------------------------------------------- + +const NS_ATOM_10 = 'http://www.w3.org/2005/Atom' +const NS_ATOM_03 = 'http://purl.org/atom/ns#' +const NS_RSS_10 = 'http://purl.org/rss/1.0/' +const NS_RSS_090 = 'http://my.netscape.com/rdf/simple/0.9/' +const NS_RDF = 'http://www.w3.org/1999/02/22-rdf-syntax-ns#' + + +// --- XmlElement helpers --------------------------------------------------- + +function isElement(node: unknown): node is XmlElement { + return ( + !!node && + typeof node === 'object' && + 'localName' in (node as object) && + 'children' in (node as object) + ) +} + +function elementChildren(el: XmlElement): XmlElement[] { + const out: XmlElement[] = [] + for (const c of el.children) if (isElement(c)) out.push(c) + return out +} + +function findChild( + el: XmlElement | undefined, + localName: string, + namespace?: string, +): XmlElement | undefined { + if (!el) return undefined + for (const c of el.children) { + if ( + isElement(c) && + c.localName === localName && + (namespace === undefined || c.namespace === namespace) + ) { + return c + } + } + return undefined +} + +function findChildren( + el: XmlElement | undefined, + localName: string, + namespace?: string, +): XmlElement[] { + const out: XmlElement[] = [] + if (!el) return out + for (const c of el.children) { + if ( + isElement(c) && + c.localName === localName && + (namespace === undefined || c.namespace === namespace) + ) { + out.push(c) + } + } + return out +} + +// Concatenate text node contents (ignores nested elements). +function textOf(el: XmlElement | undefined): string { + if (!el) return '' + let out = '' + for (const c of el.children) { + if (typeof c === 'string') out += c + } + return out.trim() +} + +// Serialize children (text + nested elements) back to a string. Used for +// xhtml/html content where the full body matters. +function innerXml(el: XmlElement | undefined): string { + if (!el) return '' + let out = '' + for (const c of el.children) { + if (typeof c === 'string') out += c + else out += serializeElement(c) + } + return out +} + +function serializeElement(el: XmlElement): string { + const attrs = Object.entries(el.attributes || {}) + .map(([k, v]) => ` ${k}="${escapeAttr(v)}"`) + .join('') + const inner = innerXml(el) + if (inner === '') return `<${el.name}${attrs}/>` + return `<${el.name}${attrs}>${inner}` +} + +function escapeAttr(v: string): string { + return String(v) + .replace(/&/g, '&') + .replace(/"/g, '"') + .replace(//g, '>') +} + + +// --- Format detection ----------------------------------------------------- + +function detect(root: XmlElement): { dialect: FeedDialect; version: FeedVersion } { + const name = root.localName + + if (name === 'feed') { + if (root.namespace === NS_ATOM_03) return { dialect: 'atom', version: 'atom03' } + return { dialect: 'atom', version: 'atom10' } + } + + if (name === 'rss') { + const v = (root.attributes && root.attributes.version) || '' + if (v === '2.0' || v === '2.0.1' || v === '2.0.2') { + return { dialect: 'rss', version: 'rss20' } + } + if (v === '0.92' || v === '0.93' || v === '0.94') { + return { dialect: 'rss', version: 'rss092' } + } + if (v === '0.91') { + // Distinguish Userland vs. Netscape variants by DOCTYPE; absent that, + // assume Userland (the dominant one in the wild). + return { dialect: 'rss', version: 'rss091u' } + } + return { dialect: 'rss', version: 'rss20' } + } + + if (name === 'RDF') { + // Look at the channel's namespace to pick RSS 1.0 vs 0.90. + const channel = findChild(root, 'channel') + if (channel?.namespace === NS_RSS_090) { + return { dialect: 'rdf', version: 'rss090' } + } + return { dialect: 'rdf', version: 'rss10' } + } + + return { dialect: 'unknown', version: 'unknown' } +} + + +// --- Atom (native) parser ------------------------------------------------- + +function parsePerson(el: XmlElement): AtomPerson { + return { + name: textOf(findChild(el, 'name')), + uri: textOf(findChild(el, 'uri')) || textOf(findChild(el, 'url')) || undefined, + email: textOf(findChild(el, 'email')) || undefined, + } +} + +function parseLink(el: XmlElement): AtomLink { + const a = el.attributes || {} + const link: AtomLink = { href: a.href || '' } + if (a.rel) link.rel = a.rel + if (a.type) link.type = a.type + if (a.hreflang) link.hreflang = a.hreflang + if (a.title) link.title = a.title + if (a.length) link.length = parseInt(a.length, 10) + return link +} + +function parseCategory(el: XmlElement): AtomCategory { + const a = el.attributes || {} + return { + term: a.term || textOf(el), + scheme: a.scheme, + label: a.label, + } +} + +function parseText(el: XmlElement | undefined): AtomText | undefined { + if (!el) return undefined + const a = el.attributes || {} + const type = (a.type as AtomText['type']) || 'text' + if (type === 'xhtml') { + // Take the inner body of the xhtml
, if present + const div = findChild(el, 'div') + return { type, value: innerXml(div || el) } + } + return { type, value: textOf(el) } +} + +function parseContent(el: XmlElement): AtomContent { + const a = el.attributes || {} + const type = a.type || 'text' + const out: AtomContent = { type } + if (a.src) out.src = a.src + if (type === 'xhtml') { + const div = findChild(el, 'div') + out.value = innerXml(div || el) + } else { + out.value = textOf(el) + } + return out +} + +function parseGenerator(el: XmlElement): AtomGenerator { + const a = el.attributes || {} + return { + uri: a.uri, + version: a.version, + value: textOf(el), + } +} + +function parseAtomEntry(el: XmlElement, atom03: boolean): AtomEntry { + const entry: AtomEntry = {} + + const id = findChild(el, 'id') + if (id) entry.id = textOf(id) + + const title = findChild(el, 'title') + if (title) entry.title = parseText(title) + + // Atom 1.0 uses 'updated' / 'published'; Atom 0.3 uses 'modified' / 'issued' + const updated = findChild(el, atom03 ? 'modified' : 'updated') + if (updated) entry.updated = textOf(updated) + const published = findChild(el, atom03 ? 'issued' : 'published') + if (published) entry.published = textOf(published) + + const authors = findChildren(el, 'author').map(parsePerson) + if (authors.length) entry.authors = authors + const contributors = findChildren(el, 'contributor').map(parsePerson) + if (contributors.length) entry.contributors = contributors + + const categories = findChildren(el, 'category').map(parseCategory) + if (categories.length) entry.categories = categories + + const links = findChildren(el, 'link').map(parseLink) + if (links.length) entry.links = links + + const content = findChild(el, 'content') + if (content) entry.content = parseContent(content) + + const rights = findChild(el, atom03 ? 'copyright' : 'rights') + if (rights) entry.rights = parseText(rights) + + const summary = findChild(el, atom03 ? 'tagline' : 'summary') + if (summary) entry.summary = parseText(summary) + + return entry +} + +function parseAtom(root: XmlElement, version: 'atom10' | 'atom03'): AtomFeed { + const atom03 = version === 'atom03' + const feed: AtomFeed = { + format: 'atom', + version: atom03 ? '0.3' : '1.0', + entries: [], + } + + const id = findChild(root, 'id') + if (id) feed.id = textOf(id) + + const title = findChild(root, 'title') + if (title) feed.title = parseText(title) + + const updated = findChild(root, atom03 ? 'modified' : 'updated') + if (updated) feed.updated = textOf(updated) + + const authors = findChildren(root, 'author').map(parsePerson) + if (authors.length) feed.authors = authors + + const contributors = findChildren(root, 'contributor').map(parsePerson) + if (contributors.length) feed.contributors = contributors + + const categories = findChildren(root, 'category').map(parseCategory) + if (categories.length) feed.categories = categories + + const links = findChildren(root, 'link').map(parseLink) + if (links.length) feed.links = links + + const generator = findChild(root, 'generator') + if (generator) feed.generator = parseGenerator(generator) + + const icon = findChild(root, 'icon') + if (icon) feed.icon = textOf(icon) + + const logo = findChild(root, 'logo') + if (logo) feed.logo = textOf(logo) + + const rights = findChild(root, atom03 ? 'copyright' : 'rights') + if (rights) feed.rights = parseText(rights) + + const subtitle = findChild(root, atom03 ? 'tagline' : 'subtitle') + if (subtitle) feed.subtitle = parseText(subtitle) + + feed.entries = findChildren(root, 'entry').map((e) => parseAtomEntry(e, atom03)) + + return feed +} + + +// --- RSS 2.x / 0.91 / 0.92 (native) parser -------------------------------- + +function parseRss2Image(el: XmlElement): Rss2Image { + const url = textOf(findChild(el, 'url')) + const title = textOf(findChild(el, 'title')) + const link = textOf(findChild(el, 'link')) + const out: Rss2Image = { url, title, link } + const w = textOf(findChild(el, 'width')) + if (w) out.width = parseInt(w, 10) + const h = textOf(findChild(el, 'height')) + if (h) out.height = parseInt(h, 10) + const d = textOf(findChild(el, 'description')) + if (d) out.description = d + return out +} + +function parseRss2Cloud(el: XmlElement): Rss2Cloud { + const a = el.attributes || {} + return { + domain: a.domain || '', + port: parseInt(a.port || '0', 10), + path: a.path || '', + registerProcedure: a.registerProcedure || '', + protocol: a.protocol || '', + } +} + +function parseRss2TextInput(el: XmlElement): Rss2TextInput { + return { + title: textOf(findChild(el, 'title')), + description: textOf(findChild(el, 'description')), + name: textOf(findChild(el, 'name')), + link: textOf(findChild(el, 'link')), + } +} + +function parseRss2Item(el: XmlElement): Rss2Item { + const item: Rss2Item = {} + + const title = findChild(el, 'title') + if (title) item.title = textOf(title) + + const link = findChild(el, 'link') + if (link) item.link = textOf(link) + + const desc = findChild(el, 'description') + if (desc) item.description = textOf(desc) + + const author = findChild(el, 'author') + if (author) item.author = textOf(author) + + const categories = findChildren(el, 'category').map((c) => ({ + domain: c.attributes?.domain, + value: textOf(c), + })) + if (categories.length) item.categories = categories + + const comments = findChild(el, 'comments') + if (comments) item.comments = textOf(comments) + + const enc = findChild(el, 'enclosure') + if (enc) { + const a = enc.attributes || {} + const out: Rss2Enclosure = { url: a.url || '' } + if (a.length) out.length = parseInt(a.length, 10) + if (a.type) out.type = a.type + item.enclosure = out + } + + const guid = findChild(el, 'guid') + if (guid) { + const a = guid.attributes || {} + const g: Rss2Guid = { value: textOf(guid) } + if ('isPermaLink' in a) g.isPermaLink = a.isPermaLink !== 'false' + item.guid = g + } + + const pubDate = findChild(el, 'pubDate') + if (pubDate) item.pubDate = textOf(pubDate) + + const src = findChild(el, 'source') + if (src) { + item.source = { + url: src.attributes?.url, + value: textOf(src), + } + } + + return item +} + +function parseRss2(root: XmlElement, version: FeedVersion): Rss2Feed { + const channel = findChild(root, 'channel') || root + const v: Rss2Feed['version'] = + version === 'rss092' ? '0.92' : + version === 'rss091u' || version === 'rss091n' ? '0.91' : '2.0' + + const feed: Rss2Feed = { + format: 'rss', + version: v, + title: textOf(findChild(channel, 'title')), + link: textOf(findChild(channel, 'link')), + description: textOf(findChild(channel, 'description')), + items: [], + } + + const language = findChild(channel, 'language') + if (language) feed.language = textOf(language) + const copyright = findChild(channel, 'copyright') + if (copyright) feed.copyright = textOf(copyright) + const managingEditor = findChild(channel, 'managingEditor') + if (managingEditor) feed.managingEditor = textOf(managingEditor) + const webMaster = findChild(channel, 'webMaster') + if (webMaster) feed.webMaster = textOf(webMaster) + const pubDate = findChild(channel, 'pubDate') + if (pubDate) feed.pubDate = textOf(pubDate) + const lastBuildDate = findChild(channel, 'lastBuildDate') + if (lastBuildDate) feed.lastBuildDate = textOf(lastBuildDate) + + const categories = findChildren(channel, 'category').map((c) => ({ + domain: c.attributes?.domain, + value: textOf(c), + })) + if (categories.length) feed.categories = categories + + const generator = findChild(channel, 'generator') + if (generator) feed.generator = textOf(generator) + + const docs = findChild(channel, 'docs') + if (docs) feed.docs = textOf(docs) + + const cloud = findChild(channel, 'cloud') + if (cloud) feed.cloud = parseRss2Cloud(cloud) + + const ttl = findChild(channel, 'ttl') + if (ttl) feed.ttl = parseInt(textOf(ttl), 10) + + const image = findChild(channel, 'image') + if (image) feed.image = parseRss2Image(image) + + const textInput = findChild(channel, 'textInput') || findChild(channel, 'textinput') + if (textInput) feed.textInput = parseRss2TextInput(textInput) + + const skipHours = findChild(channel, 'skipHours') + if (skipHours) { + feed.skipHours = findChildren(skipHours, 'hour').map((h) => parseInt(textOf(h), 10)) + } + const skipDays = findChild(channel, 'skipDays') + if (skipDays) { + feed.skipDays = findChildren(skipDays, 'day').map(textOf) + } + + // Items can sit on the channel (RSS 0.92/2.0) or, very rarely, on the rss + // root in some malformed feeds. + const items = findChildren(channel, 'item') + feed.items = items.map(parseRss2Item) + + return feed +} + + +// --- RSS 1.0 / 0.90 (native) parser --------------------------------------- + +function parseRss1Image(el: XmlElement): Rss1Image { + return { + about: el.attributes?.['rdf:about'], + title: textOf(findChild(el, 'title')), + link: textOf(findChild(el, 'link')), + url: textOf(findChild(el, 'url')), + } +} + +function parseRss1TextInput(el: XmlElement): Rss1TextInput { + return { + about: el.attributes?.['rdf:about'], + title: textOf(findChild(el, 'title')), + description: textOf(findChild(el, 'description')), + name: textOf(findChild(el, 'name')), + link: textOf(findChild(el, 'link')), + } +} + +function parseRss1Item(el: XmlElement): Rss1Item { + const item: Rss1Item = { + title: textOf(findChild(el, 'title')), + link: textOf(findChild(el, 'link')), + } + const about = el.attributes?.['rdf:about'] + if (about) item.about = about + const desc = findChild(el, 'description') + if (desc) item.description = textOf(desc) + return item +} + +function parseRss1(root: XmlElement, version: FeedVersion): Rss1Feed { + const channel = findChild(root, 'channel') + const items = findChildren(root, 'item') + + const feed: Rss1Feed = { + format: 'rdf', + version: version === 'rss090' ? '0.90' : '1.0', + title: textOf(findChild(channel, 'title')), + link: textOf(findChild(channel, 'link')), + items: items.map(parseRss1Item), + } + + const about = channel?.attributes?.['rdf:about'] + if (about) feed.about = about + + const desc = findChild(channel, 'description') + if (desc) feed.description = textOf(desc) + + const image = findChild(root, 'image') + if (image) feed.image = parseRss1Image(image) + + const textInput = findChild(root, 'textinput') || findChild(root, 'textInput') + if (textInput) feed.textInput = parseRss1TextInput(textInput) + + return feed +} + + +// --- Native -> Atom conversions ------------------------------------------- + +function rss2ToAtom(rss: Rss2Feed): AtomFeed { + const out: AtomFeed = { + format: 'atom', + version: '1.0', + entries: [], + } + + if (rss.title) out.title = { type: 'text', value: rss.title } + if (rss.description) out.subtitle = { type: 'text', value: rss.description } + if (rss.copyright) out.rights = { type: 'text', value: rss.copyright } + + // Use the RSS link as the channel id when no other identity is available; + // Atom requires an id but RSS doesn't have a direct equivalent, so this + // is a best-effort mapping. + if (rss.link) out.id = rss.link + + // Updated: prefer lastBuildDate, fall back to pubDate. + if (rss.lastBuildDate) out.updated = rss.lastBuildDate + else if (rss.pubDate) out.updated = rss.pubDate + + if (rss.generator) { + out.generator = { value: rss.generator } + } + + if (rss.image?.url) out.logo = rss.image.url + + const links: AtomLink[] = [] + if (rss.link) links.push({ href: rss.link, rel: 'alternate' }) + if (links.length) out.links = links + + if (rss.categories?.length) { + out.categories = rss.categories.map((c) => ({ + term: c.value, + scheme: c.domain, + })) + } + + // managingEditor / webMaster look like "email (Name)" or "email"; preserve + // the email and name where possible. + if (rss.managingEditor || rss.webMaster) { + const persons: AtomPerson[] = [] + const me = rss.managingEditor || rss.webMaster + if (me) persons.push(parseRssPerson(me)) + out.authors = persons + } + + out.entries = rss.items.map(rss2ItemToAtomEntry) + + return out +} + +function parseRssPerson(s: string): AtomPerson { + // RSS authors look like "you@example.com (Your Name)" or just an email. + const m = s.match(/^\s*([^\s()]+@\S+)\s*(?:\(([^)]+)\))?\s*$/) + if (m) { + return { name: m[2] || m[1], email: m[1] } + } + return { name: s.trim() } +} + +function rss2ItemToAtomEntry(item: Rss2Item): AtomEntry { + const entry: AtomEntry = {} + + if (item.title) entry.title = { type: 'text', value: item.title } + if (item.description) entry.summary = { type: 'html', value: item.description } + if (item.pubDate) { + entry.published = item.pubDate + entry.updated = item.pubDate + } + + // guid is the natural id; otherwise fall back to link. + if (item.guid) entry.id = item.guid.value + else if (item.link) entry.id = item.link + + const links: AtomLink[] = [] + if (item.link) links.push({ href: item.link, rel: 'alternate' }) + if (item.enclosure?.url) { + const link: AtomLink = { href: item.enclosure.url, rel: 'enclosure' } + if (item.enclosure.type) link.type = item.enclosure.type + if (item.enclosure.length !== undefined) link.length = item.enclosure.length + links.push(link) + } + if (item.comments) { + links.push({ href: item.comments, rel: 'replies', type: 'text/html' }) + } + if (links.length) entry.links = links + + if (item.author) entry.authors = [parseRssPerson(item.author)] + + if (item.categories?.length) { + entry.categories = item.categories.map((c) => ({ + term: c.value, + scheme: c.domain, + })) + } + + if (item.source) { + const src: Partial = { format: 'atom', version: '1.0' } + if (item.source.value) src.title = { type: 'text', value: item.source.value } + if (item.source.url) src.links = [{ href: item.source.url, rel: 'self' }] + entry.source = src + } + + return entry +} + +function rss1ToAtom(rss: Rss1Feed): AtomFeed { + const out: AtomFeed = { + format: 'atom', + version: '1.0', + entries: [], + } + + if (rss.title) out.title = { type: 'text', value: rss.title } + if (rss.description) out.subtitle = { type: 'text', value: rss.description } + if (rss.about) out.id = rss.about + else if (rss.link) out.id = rss.link + if (rss.link) out.links = [{ href: rss.link, rel: 'alternate' }] + if (rss.image?.url) out.logo = rss.image.url + + out.entries = rss.items.map((it) => { + const e: AtomEntry = {} + if (it.title) e.title = { type: 'text', value: it.title } + if (it.description) e.summary = { type: 'text', value: it.description } + e.id = it.about || it.link + if (it.link) e.links = [{ href: it.link, rel: 'alternate' }] + return e + }) + + return out +} + + +// --- Top-level convert ---------------------------------------------------- + +function convert(root: XmlElement, opts: Required): FeedResult { + if (opts.format === 'raw') return root + + const { dialect, version } = detect(root) + + if (dialect === 'unknown') { + throw new Error( + `feed: unrecognized root element "${root.localName}"; expected one of feed, rss, RDF`, + ) + } + + // Native parse first. + let native: AtomFeed | Rss2Feed | Rss1Feed + if (dialect === 'atom') { + native = parseAtom(root, version === 'atom03' ? 'atom03' : 'atom10') + } else if (dialect === 'rss') { + native = parseRss2(root, version) + } else { + native = parseRss1(root, version) + } + + if (opts.format === 'native') return native + + // Atom (default): convert to Atom shape. + if (native.format === 'atom') return native + if (native.format === 'rss') return rss2ToAtom(native) + return rss1ToAtom(native) +} + + +// --- Public functional entry point ---------------------------------------- + +function parseFeed(src: string, options?: FeedOptions): FeedResult { + const j = Jsonic.make().use(Xml) + const root = j(src) + if (!isElement(root)) { + throw new Error('feed: input did not parse to an XML element') + } + return convert(root, withDefaults(options)) +} + +function withDefaults(o?: FeedOptions): Required { + return { format: o?.format ?? 'atom' } +} + + +// --- jsonic Plugin -------------------------------------------------------- + +const Feed: Plugin = function Feed(jsonic, options) { + jsonic.use(Xml) + const opts = withDefaults(options as FeedOptions | undefined) + + // Attach a `feed(src)` method that runs xml parse + feed convert. + ;(jsonic as any).feed = function (src: string): FeedResult { + const root = jsonic(src) + if (!isElement(root)) { + throw new Error('feed: input did not parse to an XML element') + } + return convert(root, opts) + } +} + + +export { Feed, parseFeed, detect } + +export type { + FeedFormat, + FeedDialect, + FeedVersion, + FeedOptions, + FeedResult, + AtomFeed, + AtomEntry, + AtomText, + AtomPerson, + AtomLink, + AtomCategory, + AtomGenerator, + AtomContent, + Rss2Feed, + Rss2Item, + Rss2Category, + Rss2Enclosure, + Rss2Guid, + Rss2Source, + Rss2Image, + Rss2Cloud, + Rss2TextInput, + Rss1Feed, + Rss1Item, + Rss1Image, + Rss1TextInput, +} diff --git a/src/jsonc.ts b/src/jsonc.ts deleted file mode 100644 index 00d0cb8..0000000 --- a/src/jsonc.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2021-2025 Richard Rodger, MIT License */ - -// Import Jsonic types used by plugin. -import { Jsonic } from 'jsonic' - -type JsoncOptions = { - allowTrailingComma?: boolean - disallowComments?: boolean -} - -// --- BEGIN EMBEDDED jsonc-grammar.jsonic --- -const grammarText = ` -# JSONC Grammar Definition -# Parsed by a standard Jsonic instance and passed to jsonic.grammar() -# Extends standard JSON grammar with end-of-input value handling. - -{ - options: text: { lex: false } - options: number: { hex: false oct: false bin: false sep: null exclude: "@/^\\\\./" } - options: string: { chars: '"' multiChars: '' allowUnknown: false } - options: string: escape: { v: null } - options: map: { extend: false } - options: lex: { empty: false } - options: rule: { finish: false } - - rule: val: open: { - alts: [ - { s: '#ZZ' g: jsonc } - ] - inject: { append: true } - } - - rule: pair: close: { - alts: [ - { s: '#CA #CB' b: 1 g: comma } - ] - inject: {} - } - - rule: elem: close: { - alts: [ - { s: '#CA #CS' b: 1 g: comma } - ] - inject: {} - } -} -` -// --- END EMBEDDED jsonc-grammar.jsonic --- - -function Jsonc(jsonic: Jsonic, options: JsoncOptions) { - const comment_lex = true !== options.disallowComments - const rule_exclude = options.allowTrailingComma ? '' : 'comma' - - // Apply grammar: static options and val ZZ rule alt. - jsonic.grammar(Jsonic.make()(grammarText), { rule: { alt: { g: 'jsonc' } } }) - - // Runtime options that depend on plugin arguments. - jsonic.options({ - comment: { - lex: comment_lex, - }, - rule: { - include: 'jsonc,json', - exclude: rule_exclude, - }, - }) -} - -export { Jsonc } - -export type { JsoncOptions } diff --git a/test/JSONTestSuite/LICENSE b/test/JSONTestSuite/LICENSE deleted file mode 100644 index c4b3621..0000000 --- a/test/JSONTestSuite/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2016 Nicolas Seriot - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/test/JSONTestSuite/README.md b/test/JSONTestSuite/README.md deleted file mode 100644 index 775ccfd..0000000 --- a/test/JSONTestSuite/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# JSON Parsing Test Suite -A comprehensive test suite for RFC 8259 compliant JSON parsers - -This repository was created as an appendix to the article [Parsing JSON is a Minefield 💣](http://seriot.ch/parsing_json.php). - -**/parsers/** - -This directory contains several parsers and tiny wrappers to turn the parsers into JSON validators, by returning a specific value. - -- `0` the parser did accept the content -- `1` the parser did reject the content -- `>1` the process did crash -- `timeout` happens after 5 seconds - -**/test\_parsing/** - -The name of these files tell if their contents should be accepted or rejected. - -- `y_` content must be accepted by parsers -- `n_` content must be rejected by parsers -- `i_` parsers are free to accept or reject content - -**/test\_transform/** - -These files contain weird structures and characters that parsers may understand differently, eg: - -- huge numbers -- dictionaries with similar keys -- NULL characters -- escaped invalid strings - -These files were used to produce `results/transform.html`. - -**/run_tests.py** - -Run all parsers with all files: - - $ python3 run_tests.py - -Run all parsers with a specific file: - - $ python3 run_tests.py file.json - -Run specific parsers with all files: - - $ echo '["Python 2.7.10", "Python 3.5.2"]' > python_only.json - $ python3 run_tests.py --filter=python_only.json - -The script writes logs in `results/logs.txt`. - -The script then reads `logs.txt` and generates `results/parsing.html`. - -**/results/** - -JSON Parsing Tests diff --git a/test/JSONTestSuite/test_parsing/i_number_double_huge_neg_exp.json b/test/JSONTestSuite/test_parsing/i_number_double_huge_neg_exp.json deleted file mode 100644 index ae4c7b7..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_double_huge_neg_exp.json +++ /dev/null @@ -1 +0,0 @@ -[123.456e-789] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_huge_exp.json b/test/JSONTestSuite/test_parsing/i_number_huge_exp.json deleted file mode 100644 index 9b5efa2..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_huge_exp.json +++ /dev/null @@ -1 +0,0 @@ -[0.4e00669999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999969999999006] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_neg_int_huge_exp.json b/test/JSONTestSuite/test_parsing/i_number_neg_int_huge_exp.json deleted file mode 100755 index 3abd58a..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_neg_int_huge_exp.json +++ /dev/null @@ -1 +0,0 @@ -[-1e+9999] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_pos_double_huge_exp.json b/test/JSONTestSuite/test_parsing/i_number_pos_double_huge_exp.json deleted file mode 100755 index e10a7eb..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_pos_double_huge_exp.json +++ /dev/null @@ -1 +0,0 @@ -[1.5e+9999] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_real_neg_overflow.json b/test/JSONTestSuite/test_parsing/i_number_real_neg_overflow.json deleted file mode 100644 index 3d628a9..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_real_neg_overflow.json +++ /dev/null @@ -1 +0,0 @@ -[-123123e100000] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_real_pos_overflow.json b/test/JSONTestSuite/test_parsing/i_number_real_pos_overflow.json deleted file mode 100644 index 54d7d3d..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_real_pos_overflow.json +++ /dev/null @@ -1 +0,0 @@ -[123123e100000] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_real_underflow.json b/test/JSONTestSuite/test_parsing/i_number_real_underflow.json deleted file mode 100644 index c5236eb..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_real_underflow.json +++ /dev/null @@ -1 +0,0 @@ -[123e-10000000] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_too_big_neg_int.json b/test/JSONTestSuite/test_parsing/i_number_too_big_neg_int.json deleted file mode 100644 index dfa3846..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_too_big_neg_int.json +++ /dev/null @@ -1 +0,0 @@ -[-123123123123123123123123123123] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_too_big_pos_int.json b/test/JSONTestSuite/test_parsing/i_number_too_big_pos_int.json deleted file mode 100644 index 338a8c3..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_too_big_pos_int.json +++ /dev/null @@ -1 +0,0 @@ -[100000000000000000000] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_number_very_big_negative_int.json b/test/JSONTestSuite/test_parsing/i_number_very_big_negative_int.json deleted file mode 100755 index e2d9738..0000000 --- a/test/JSONTestSuite/test_parsing/i_number_very_big_negative_int.json +++ /dev/null @@ -1 +0,0 @@ -[-237462374673276894279832749832423479823246327846] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_object_key_lone_2nd_surrogate.json b/test/JSONTestSuite/test_parsing/i_object_key_lone_2nd_surrogate.json deleted file mode 100644 index 5be7eba..0000000 --- a/test/JSONTestSuite/test_parsing/i_object_key_lone_2nd_surrogate.json +++ /dev/null @@ -1 +0,0 @@ -{"\uDFAA":0} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_1st_surrogate_but_2nd_missing.json b/test/JSONTestSuite/test_parsing/i_string_1st_surrogate_but_2nd_missing.json deleted file mode 100644 index 3b9e37c..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_1st_surrogate_but_2nd_missing.json +++ /dev/null @@ -1 +0,0 @@ -["\uDADA"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json b/test/JSONTestSuite/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json deleted file mode 100644 index 4875928..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_1st_valid_surrogate_2nd_invalid.json +++ /dev/null @@ -1 +0,0 @@ -["\uD888\u1234"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_UTF-16LE_with_BOM.json b/test/JSONTestSuite/test_parsing/i_string_UTF-16LE_with_BOM.json deleted file mode 100644 index 2a79c0629a49133d8f715bddbef19cfb3ef025bd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12 ScmezWFPcG#;Uy5qG5`P~Km+3d diff --git a/test/JSONTestSuite/test_parsing/i_string_UTF-8_invalid_sequence.json b/test/JSONTestSuite/test_parsing/i_string_UTF-8_invalid_sequence.json deleted file mode 100755 index e2a968a..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_UTF-8_invalid_sequence.json +++ /dev/null @@ -1 +0,0 @@ -["日ш"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_UTF8_surrogate_U+D800.json b/test/JSONTestSuite/test_parsing/i_string_UTF8_surrogate_U+D800.json deleted file mode 100644 index 916bff9..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_UTF8_surrogate_U+D800.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json b/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json deleted file mode 100755 index 3cb11d2..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_and_escape_valid.json +++ /dev/null @@ -1 +0,0 @@ -["\uD800\n"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_pair.json b/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_pair.json deleted file mode 100755 index 38ec23b..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogate_pair.json +++ /dev/null @@ -1 +0,0 @@ -["\uDd1ea"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogates_escape_valid.json b/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogates_escape_valid.json deleted file mode 100755 index c9cd6f6..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_incomplete_surrogates_escape_valid.json +++ /dev/null @@ -1 +0,0 @@ -["\uD800\uD800\n"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_invalid_lonely_surrogate.json b/test/JSONTestSuite/test_parsing/i_string_invalid_lonely_surrogate.json deleted file mode 100755 index 3abbd8d..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_invalid_lonely_surrogate.json +++ /dev/null @@ -1 +0,0 @@ -["\ud800"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_invalid_surrogate.json b/test/JSONTestSuite/test_parsing/i_string_invalid_surrogate.json deleted file mode 100755 index ffddc04..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_invalid_surrogate.json +++ /dev/null @@ -1 +0,0 @@ -["\ud800abc"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_invalid_utf-8.json b/test/JSONTestSuite/test_parsing/i_string_invalid_utf-8.json deleted file mode 100644 index 8e45a7e..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_invalid_utf-8.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_inverted_surrogates_U+1D11E.json b/test/JSONTestSuite/test_parsing/i_string_inverted_surrogates_U+1D11E.json deleted file mode 100755 index 0d5456c..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_inverted_surrogates_U+1D11E.json +++ /dev/null @@ -1 +0,0 @@ -["\uDd1e\uD834"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_iso_latin_1.json b/test/JSONTestSuite/test_parsing/i_string_iso_latin_1.json deleted file mode 100644 index 9389c98..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_iso_latin_1.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_lone_second_surrogate.json b/test/JSONTestSuite/test_parsing/i_string_lone_second_surrogate.json deleted file mode 100644 index 1dbd397..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_lone_second_surrogate.json +++ /dev/null @@ -1 +0,0 @@ -["\uDFAA"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_lone_utf8_continuation_byte.json b/test/JSONTestSuite/test_parsing/i_string_lone_utf8_continuation_byte.json deleted file mode 100644 index 729337c..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_lone_utf8_continuation_byte.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_not_in_unicode_range.json b/test/JSONTestSuite/test_parsing/i_string_not_in_unicode_range.json deleted file mode 100644 index df90a29..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_not_in_unicode_range.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_2_bytes.json b/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_2_bytes.json deleted file mode 100644 index c8cee5e..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_2_bytes.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes.json b/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes.json deleted file mode 100755 index 9a91da7..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes_null.json b/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes_null.json deleted file mode 100755 index d24fffd..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_overlong_sequence_6_bytes_null.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_truncated-utf-8.json b/test/JSONTestSuite/test_parsing/i_string_truncated-utf-8.json deleted file mode 100644 index 63c7777..0000000 --- a/test/JSONTestSuite/test_parsing/i_string_truncated-utf-8.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_string_utf16BE_no_BOM.json b/test/JSONTestSuite/test_parsing/i_string_utf16BE_no_BOM.json deleted file mode 100644 index 57e5392ff6309134268c7e3ec2a9289b99ff7148..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10 PcmZRGW>8{y3B<7g33~zN diff --git a/test/JSONTestSuite/test_parsing/i_string_utf16LE_no_BOM.json b/test/JSONTestSuite/test_parsing/i_string_utf16LE_no_BOM.json deleted file mode 100644 index c49c1b25d8e5819591993d4d45e4649a46c1b3e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10 Pcma!MP-1uq#IXzj3t$1} diff --git a/test/JSONTestSuite/test_parsing/i_structure_500_nested_arrays.json b/test/JSONTestSuite/test_parsing/i_structure_500_nested_arrays.json deleted file mode 100644 index 7118405..0000000 --- a/test/JSONTestSuite/test_parsing/i_structure_500_nested_arrays.json +++ /dev/null @@ -1 +0,0 @@ -[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/i_structure_UTF-8_BOM_empty_object.json b/test/JSONTestSuite/test_parsing/i_structure_UTF-8_BOM_empty_object.json deleted file mode 100755 index 22fdca1..0000000 --- a/test/JSONTestSuite/test_parsing/i_structure_UTF-8_BOM_empty_object.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_1_true_without_comma.json b/test/JSONTestSuite/test_parsing/n_array_1_true_without_comma.json deleted file mode 100644 index c14e3f6..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_1_true_without_comma.json +++ /dev/null @@ -1 +0,0 @@ -[1 true] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_a_invalid_utf8.json b/test/JSONTestSuite/test_parsing/n_array_a_invalid_utf8.json deleted file mode 100644 index 38a86e2..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_a_invalid_utf8.json +++ /dev/null @@ -1 +0,0 @@ -[a] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_colon_instead_of_comma.json b/test/JSONTestSuite/test_parsing/n_array_colon_instead_of_comma.json deleted file mode 100644 index 0d02ad4..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_colon_instead_of_comma.json +++ /dev/null @@ -1 +0,0 @@ -["": 1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_comma_after_close.json b/test/JSONTestSuite/test_parsing/n_array_comma_after_close.json deleted file mode 100644 index 2ccba8d..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_comma_after_close.json +++ /dev/null @@ -1 +0,0 @@ -[""], \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_comma_and_number.json b/test/JSONTestSuite/test_parsing/n_array_comma_and_number.json deleted file mode 100755 index d2c84e3..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_comma_and_number.json +++ /dev/null @@ -1 +0,0 @@ -[,1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_double_comma.json b/test/JSONTestSuite/test_parsing/n_array_double_comma.json deleted file mode 100755 index 0431712..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_double_comma.json +++ /dev/null @@ -1 +0,0 @@ -[1,,2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_double_extra_comma.json b/test/JSONTestSuite/test_parsing/n_array_double_extra_comma.json deleted file mode 100644 index 3f01d31..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_double_extra_comma.json +++ /dev/null @@ -1 +0,0 @@ -["x",,] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_extra_close.json b/test/JSONTestSuite/test_parsing/n_array_extra_close.json deleted file mode 100644 index c12f9fa..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_extra_close.json +++ /dev/null @@ -1 +0,0 @@ -["x"]] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_extra_comma.json b/test/JSONTestSuite/test_parsing/n_array_extra_comma.json deleted file mode 100644 index 5f8ce18..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_extra_comma.json +++ /dev/null @@ -1 +0,0 @@ -["",] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_incomplete.json b/test/JSONTestSuite/test_parsing/n_array_incomplete.json deleted file mode 100644 index cc65b0b..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_incomplete.json +++ /dev/null @@ -1 +0,0 @@ -["x" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_incomplete_invalid_value.json b/test/JSONTestSuite/test_parsing/n_array_incomplete_invalid_value.json deleted file mode 100644 index c21a8f6..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_incomplete_invalid_value.json +++ /dev/null @@ -1 +0,0 @@ -[x \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_inner_array_no_comma.json b/test/JSONTestSuite/test_parsing/n_array_inner_array_no_comma.json deleted file mode 100644 index c70b716..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_inner_array_no_comma.json +++ /dev/null @@ -1 +0,0 @@ -[3[4]] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_invalid_utf8.json b/test/JSONTestSuite/test_parsing/n_array_invalid_utf8.json deleted file mode 100644 index 6099d34..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_invalid_utf8.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_items_separated_by_semicolon.json b/test/JSONTestSuite/test_parsing/n_array_items_separated_by_semicolon.json deleted file mode 100755 index d4bd731..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_items_separated_by_semicolon.json +++ /dev/null @@ -1 +0,0 @@ -[1:2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_just_comma.json b/test/JSONTestSuite/test_parsing/n_array_just_comma.json deleted file mode 100755 index 9d7077c..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_just_comma.json +++ /dev/null @@ -1 +0,0 @@ -[,] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_just_minus.json b/test/JSONTestSuite/test_parsing/n_array_just_minus.json deleted file mode 100755 index 29501c6..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_just_minus.json +++ /dev/null @@ -1 +0,0 @@ -[-] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_missing_value.json b/test/JSONTestSuite/test_parsing/n_array_missing_value.json deleted file mode 100644 index 3a6ba86..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_missing_value.json +++ /dev/null @@ -1 +0,0 @@ -[ , ""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_newlines_unclosed.json b/test/JSONTestSuite/test_parsing/n_array_newlines_unclosed.json deleted file mode 100644 index 6466800..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_newlines_unclosed.json +++ /dev/null @@ -1,3 +0,0 @@ -["a", -4 -,1, \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_number_and_comma.json b/test/JSONTestSuite/test_parsing/n_array_number_and_comma.json deleted file mode 100755 index 13f6f1d..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_number_and_comma.json +++ /dev/null @@ -1 +0,0 @@ -[1,] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_number_and_several_commas.json b/test/JSONTestSuite/test_parsing/n_array_number_and_several_commas.json deleted file mode 100755 index 0ac408c..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_number_and_several_commas.json +++ /dev/null @@ -1 +0,0 @@ -[1,,] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_spaces_vertical_tab_formfeed.json b/test/JSONTestSuite/test_parsing/n_array_spaces_vertical_tab_formfeed.json deleted file mode 100755 index 6cd7cf5..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_spaces_vertical_tab_formfeed.json +++ /dev/null @@ -1 +0,0 @@ -[" a"\f] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_star_inside.json b/test/JSONTestSuite/test_parsing/n_array_star_inside.json deleted file mode 100755 index 5a51946..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_star_inside.json +++ /dev/null @@ -1 +0,0 @@ -[*] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_unclosed.json b/test/JSONTestSuite/test_parsing/n_array_unclosed.json deleted file mode 100644 index 0607330..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_unclosed.json +++ /dev/null @@ -1 +0,0 @@ -["" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_unclosed_trailing_comma.json b/test/JSONTestSuite/test_parsing/n_array_unclosed_trailing_comma.json deleted file mode 100644 index 6604698..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_unclosed_trailing_comma.json +++ /dev/null @@ -1 +0,0 @@ -[1, \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_unclosed_with_new_lines.json b/test/JSONTestSuite/test_parsing/n_array_unclosed_with_new_lines.json deleted file mode 100644 index 4f61de3..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_unclosed_with_new_lines.json +++ /dev/null @@ -1,3 +0,0 @@ -[1, -1 -,1 \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_array_unclosed_with_object_inside.json b/test/JSONTestSuite/test_parsing/n_array_unclosed_with_object_inside.json deleted file mode 100644 index 043a87e..0000000 --- a/test/JSONTestSuite/test_parsing/n_array_unclosed_with_object_inside.json +++ /dev/null @@ -1 +0,0 @@ -[{} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_incomplete_false.json b/test/JSONTestSuite/test_parsing/n_incomplete_false.json deleted file mode 100644 index eb18c6a..0000000 --- a/test/JSONTestSuite/test_parsing/n_incomplete_false.json +++ /dev/null @@ -1 +0,0 @@ -[fals] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_incomplete_null.json b/test/JSONTestSuite/test_parsing/n_incomplete_null.json deleted file mode 100644 index c18ef53..0000000 --- a/test/JSONTestSuite/test_parsing/n_incomplete_null.json +++ /dev/null @@ -1 +0,0 @@ -[nul] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_incomplete_true.json b/test/JSONTestSuite/test_parsing/n_incomplete_true.json deleted file mode 100644 index f451ac6..0000000 --- a/test/JSONTestSuite/test_parsing/n_incomplete_true.json +++ /dev/null @@ -1 +0,0 @@ -[tru] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_multidigit_number_then_00.json b/test/JSONTestSuite/test_parsing/n_multidigit_number_then_00.json deleted file mode 100644 index c22507b864f7f089c91c1eb85b1b15cc63b943a6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4 LcmXpsGG+h(0mJ~8 diff --git a/test/JSONTestSuite/test_parsing/n_number_++.json b/test/JSONTestSuite/test_parsing/n_number_++.json deleted file mode 100644 index bdb62aa..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_++.json +++ /dev/null @@ -1 +0,0 @@ -[++1234] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_+1.json b/test/JSONTestSuite/test_parsing/n_number_+1.json deleted file mode 100755 index 3cbe58c..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_+1.json +++ /dev/null @@ -1 +0,0 @@ -[+1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_+Inf.json b/test/JSONTestSuite/test_parsing/n_number_+Inf.json deleted file mode 100755 index 871ae14..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_+Inf.json +++ /dev/null @@ -1 +0,0 @@ -[+Inf] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_-01.json b/test/JSONTestSuite/test_parsing/n_number_-01.json deleted file mode 100755 index 0df32ba..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_-01.json +++ /dev/null @@ -1 +0,0 @@ -[-01] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_-1.0..json b/test/JSONTestSuite/test_parsing/n_number_-1.0..json deleted file mode 100755 index 7cf55a8..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_-1.0..json +++ /dev/null @@ -1 +0,0 @@ -[-1.0.] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_-2..json b/test/JSONTestSuite/test_parsing/n_number_-2..json deleted file mode 100755 index 9be8436..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_-2..json +++ /dev/null @@ -1 +0,0 @@ -[-2.] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_-NaN.json b/test/JSONTestSuite/test_parsing/n_number_-NaN.json deleted file mode 100755 index f61615d..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_-NaN.json +++ /dev/null @@ -1 +0,0 @@ -[-NaN] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_.-1.json b/test/JSONTestSuite/test_parsing/n_number_.-1.json deleted file mode 100644 index 1c9f2dd..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_.-1.json +++ /dev/null @@ -1 +0,0 @@ -[.-1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_.2e-3.json b/test/JSONTestSuite/test_parsing/n_number_.2e-3.json deleted file mode 100755 index c6c976f..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_.2e-3.json +++ /dev/null @@ -1 +0,0 @@ -[.2e-3] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0.1.2.json b/test/JSONTestSuite/test_parsing/n_number_0.1.2.json deleted file mode 100755 index c83a256..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0.1.2.json +++ /dev/null @@ -1 +0,0 @@ -[0.1.2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0.3e+.json b/test/JSONTestSuite/test_parsing/n_number_0.3e+.json deleted file mode 100644 index a55a1bf..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0.3e+.json +++ /dev/null @@ -1 +0,0 @@ -[0.3e+] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0.3e.json b/test/JSONTestSuite/test_parsing/n_number_0.3e.json deleted file mode 100644 index 3dd5df4..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0.3e.json +++ /dev/null @@ -1 +0,0 @@ -[0.3e] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0.e1.json b/test/JSONTestSuite/test_parsing/n_number_0.e1.json deleted file mode 100644 index c92c71c..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0.e1.json +++ /dev/null @@ -1 +0,0 @@ -[0.e1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0_capital_E+.json b/test/JSONTestSuite/test_parsing/n_number_0_capital_E+.json deleted file mode 100644 index 3ba2c7d..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0_capital_E+.json +++ /dev/null @@ -1 +0,0 @@ -[0E+] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0_capital_E.json b/test/JSONTestSuite/test_parsing/n_number_0_capital_E.json deleted file mode 100755 index 5301840..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0_capital_E.json +++ /dev/null @@ -1 +0,0 @@ -[0E] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0e+.json b/test/JSONTestSuite/test_parsing/n_number_0e+.json deleted file mode 100644 index 8ab0bc4..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0e+.json +++ /dev/null @@ -1 +0,0 @@ -[0e+] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_0e.json b/test/JSONTestSuite/test_parsing/n_number_0e.json deleted file mode 100644 index 47ec421..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_0e.json +++ /dev/null @@ -1 +0,0 @@ -[0e] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_1.0e+.json b/test/JSONTestSuite/test_parsing/n_number_1.0e+.json deleted file mode 100755 index cd84b9f..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_1.0e+.json +++ /dev/null @@ -1 +0,0 @@ -[1.0e+] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_1.0e-.json b/test/JSONTestSuite/test_parsing/n_number_1.0e-.json deleted file mode 100755 index 4eb7afa..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_1.0e-.json +++ /dev/null @@ -1 +0,0 @@ -[1.0e-] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_1.0e.json b/test/JSONTestSuite/test_parsing/n_number_1.0e.json deleted file mode 100755 index 21753f4..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_1.0e.json +++ /dev/null @@ -1 +0,0 @@ -[1.0e] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_1_000.json b/test/JSONTestSuite/test_parsing/n_number_1_000.json deleted file mode 100755 index 7b18b66..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_1_000.json +++ /dev/null @@ -1 +0,0 @@ -[1 000.0] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_1eE2.json b/test/JSONTestSuite/test_parsing/n_number_1eE2.json deleted file mode 100755 index 4318a34..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_1eE2.json +++ /dev/null @@ -1 +0,0 @@ -[1eE2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_2.e+3.json b/test/JSONTestSuite/test_parsing/n_number_2.e+3.json deleted file mode 100755 index 4442f39..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_2.e+3.json +++ /dev/null @@ -1 +0,0 @@ -[2.e+3] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_2.e-3.json b/test/JSONTestSuite/test_parsing/n_number_2.e-3.json deleted file mode 100755 index a65060e..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_2.e-3.json +++ /dev/null @@ -1 +0,0 @@ -[2.e-3] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_2.e3.json b/test/JSONTestSuite/test_parsing/n_number_2.e3.json deleted file mode 100755 index 66f7cf7..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_2.e3.json +++ /dev/null @@ -1 +0,0 @@ -[2.e3] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_9.e+.json b/test/JSONTestSuite/test_parsing/n_number_9.e+.json deleted file mode 100644 index 732a7b1..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_9.e+.json +++ /dev/null @@ -1 +0,0 @@ -[9.e+] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_Inf.json b/test/JSONTestSuite/test_parsing/n_number_Inf.json deleted file mode 100755 index c40c734..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_Inf.json +++ /dev/null @@ -1 +0,0 @@ -[Inf] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_NaN.json b/test/JSONTestSuite/test_parsing/n_number_NaN.json deleted file mode 100755 index 4992317..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_NaN.json +++ /dev/null @@ -1 +0,0 @@ -[NaN] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_U+FF11_fullwidth_digit_one.json b/test/JSONTestSuite/test_parsing/n_number_U+FF11_fullwidth_digit_one.json deleted file mode 100644 index b14587e..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_U+FF11_fullwidth_digit_one.json +++ /dev/null @@ -1 +0,0 @@ -[1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_expression.json b/test/JSONTestSuite/test_parsing/n_number_expression.json deleted file mode 100644 index 76fdbc8..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_expression.json +++ /dev/null @@ -1 +0,0 @@ -[1+2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_hex_1_digit.json b/test/JSONTestSuite/test_parsing/n_number_hex_1_digit.json deleted file mode 100644 index 3b21488..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_hex_1_digit.json +++ /dev/null @@ -1 +0,0 @@ -[0x1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_hex_2_digits.json b/test/JSONTestSuite/test_parsing/n_number_hex_2_digits.json deleted file mode 100644 index 83e516a..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_hex_2_digits.json +++ /dev/null @@ -1 +0,0 @@ -[0x42] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_infinity.json b/test/JSONTestSuite/test_parsing/n_number_infinity.json deleted file mode 100755 index 8c2baf7..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_infinity.json +++ /dev/null @@ -1 +0,0 @@ -[Infinity] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_invalid+-.json b/test/JSONTestSuite/test_parsing/n_number_invalid+-.json deleted file mode 100644 index 1cce602..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_invalid+-.json +++ /dev/null @@ -1 +0,0 @@ -[0e+-1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_invalid-negative-real.json b/test/JSONTestSuite/test_parsing/n_number_invalid-negative-real.json deleted file mode 100644 index 5fc3c1e..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_invalid-negative-real.json +++ /dev/null @@ -1 +0,0 @@ -[-123.123foo] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-bigger-int.json b/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-bigger-int.json deleted file mode 100644 index 3b97e58..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-bigger-int.json +++ /dev/null @@ -1 +0,0 @@ -[123] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-exponent.json b/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-exponent.json deleted file mode 100644 index ea35d72..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-exponent.json +++ /dev/null @@ -1 +0,0 @@ -[1e1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-int.json b/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-int.json deleted file mode 100644 index 371226e..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_invalid-utf-8-in-int.json +++ /dev/null @@ -1 +0,0 @@ -[0] diff --git a/test/JSONTestSuite/test_parsing/n_number_minus_infinity.json b/test/JSONTestSuite/test_parsing/n_number_minus_infinity.json deleted file mode 100755 index cf4133d..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_minus_infinity.json +++ /dev/null @@ -1 +0,0 @@ -[-Infinity] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_minus_sign_with_trailing_garbage.json b/test/JSONTestSuite/test_parsing/n_number_minus_sign_with_trailing_garbage.json deleted file mode 100644 index a6d8e78..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_minus_sign_with_trailing_garbage.json +++ /dev/null @@ -1 +0,0 @@ -[-foo] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_minus_space_1.json b/test/JSONTestSuite/test_parsing/n_number_minus_space_1.json deleted file mode 100644 index 9a5ebed..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_minus_space_1.json +++ /dev/null @@ -1 +0,0 @@ -[- 1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_neg_int_starting_with_zero.json b/test/JSONTestSuite/test_parsing/n_number_neg_int_starting_with_zero.json deleted file mode 100644 index 67af096..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_neg_int_starting_with_zero.json +++ /dev/null @@ -1 +0,0 @@ -[-012] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_neg_real_without_int_part.json b/test/JSONTestSuite/test_parsing/n_number_neg_real_without_int_part.json deleted file mode 100755 index 1f2a434..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_neg_real_without_int_part.json +++ /dev/null @@ -1 +0,0 @@ -[-.123] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_neg_with_garbage_at_end.json b/test/JSONTestSuite/test_parsing/n_number_neg_with_garbage_at_end.json deleted file mode 100644 index 2aa7311..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_neg_with_garbage_at_end.json +++ /dev/null @@ -1 +0,0 @@ -[-1x] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_real_garbage_after_e.json b/test/JSONTestSuite/test_parsing/n_number_real_garbage_after_e.json deleted file mode 100644 index 9213dfc..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_real_garbage_after_e.json +++ /dev/null @@ -1 +0,0 @@ -[1ea] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_real_with_invalid_utf8_after_e.json b/test/JSONTestSuite/test_parsing/n_number_real_with_invalid_utf8_after_e.json deleted file mode 100644 index 1e52ef9..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_real_with_invalid_utf8_after_e.json +++ /dev/null @@ -1 +0,0 @@ -[1e] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_real_without_fractional_part.json b/test/JSONTestSuite/test_parsing/n_number_real_without_fractional_part.json deleted file mode 100755 index 1de287c..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_real_without_fractional_part.json +++ /dev/null @@ -1 +0,0 @@ -[1.] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_starting_with_dot.json b/test/JSONTestSuite/test_parsing/n_number_starting_with_dot.json deleted file mode 100755 index f682dbd..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_starting_with_dot.json +++ /dev/null @@ -1 +0,0 @@ -[.123] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_with_alpha.json b/test/JSONTestSuite/test_parsing/n_number_with_alpha.json deleted file mode 100644 index 1e42d81..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_with_alpha.json +++ /dev/null @@ -1 +0,0 @@ -[1.2a-3] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_with_alpha_char.json b/test/JSONTestSuite/test_parsing/n_number_with_alpha_char.json deleted file mode 100644 index b79dacc..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_with_alpha_char.json +++ /dev/null @@ -1 +0,0 @@ -[1.8011670033376514H-308] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_number_with_leading_zero.json b/test/JSONTestSuite/test_parsing/n_number_with_leading_zero.json deleted file mode 100755 index 7106da1..0000000 --- a/test/JSONTestSuite/test_parsing/n_number_with_leading_zero.json +++ /dev/null @@ -1 +0,0 @@ -[012] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_bad_value.json b/test/JSONTestSuite/test_parsing/n_object_bad_value.json deleted file mode 100644 index a03a8c0..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_bad_value.json +++ /dev/null @@ -1 +0,0 @@ -["x", truth] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_bracket_key.json b/test/JSONTestSuite/test_parsing/n_object_bracket_key.json deleted file mode 100644 index cc443b4..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_bracket_key.json +++ /dev/null @@ -1 +0,0 @@ -{[: "x"} diff --git a/test/JSONTestSuite/test_parsing/n_object_comma_instead_of_colon.json b/test/JSONTestSuite/test_parsing/n_object_comma_instead_of_colon.json deleted file mode 100644 index 8d56377..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_comma_instead_of_colon.json +++ /dev/null @@ -1 +0,0 @@ -{"x", null} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_double_colon.json b/test/JSONTestSuite/test_parsing/n_object_double_colon.json deleted file mode 100644 index 80e8c7b..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_double_colon.json +++ /dev/null @@ -1 +0,0 @@ -{"x"::"b"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_emoji.json b/test/JSONTestSuite/test_parsing/n_object_emoji.json deleted file mode 100644 index cb4078e..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_emoji.json +++ /dev/null @@ -1 +0,0 @@ -{🇨🇭} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_garbage_at_end.json b/test/JSONTestSuite/test_parsing/n_object_garbage_at_end.json deleted file mode 100644 index 80c42cb..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_garbage_at_end.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"a" 123} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_key_with_single_quotes.json b/test/JSONTestSuite/test_parsing/n_object_key_with_single_quotes.json deleted file mode 100755 index 77c3275..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_key_with_single_quotes.json +++ /dev/null @@ -1 +0,0 @@ -{key: 'value'} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json b/test/JSONTestSuite/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json deleted file mode 100644 index aa2cb63..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_lone_continuation_byte_in_key_and_trailing_comma.json +++ /dev/null @@ -1 +0,0 @@ -{"":"0",} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_missing_colon.json b/test/JSONTestSuite/test_parsing/n_object_missing_colon.json deleted file mode 100644 index b98eff6..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_missing_colon.json +++ /dev/null @@ -1 +0,0 @@ -{"a" b} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_missing_key.json b/test/JSONTestSuite/test_parsing/n_object_missing_key.json deleted file mode 100755 index b4fb0f5..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_missing_key.json +++ /dev/null @@ -1 +0,0 @@ -{:"b"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_missing_semicolon.json b/test/JSONTestSuite/test_parsing/n_object_missing_semicolon.json deleted file mode 100755 index e345138..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_missing_semicolon.json +++ /dev/null @@ -1 +0,0 @@ -{"a" "b"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_missing_value.json b/test/JSONTestSuite/test_parsing/n_object_missing_value.json deleted file mode 100644 index 3ef538a..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_missing_value.json +++ /dev/null @@ -1 +0,0 @@ -{"a": \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_no-colon.json b/test/JSONTestSuite/test_parsing/n_object_no-colon.json deleted file mode 100644 index f3797b3..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_no-colon.json +++ /dev/null @@ -1 +0,0 @@ -{"a" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_non_string_key.json b/test/JSONTestSuite/test_parsing/n_object_non_string_key.json deleted file mode 100755 index b9945b3..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_non_string_key.json +++ /dev/null @@ -1 +0,0 @@ -{1:1} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_non_string_key_but_huge_number_instead.json b/test/JSONTestSuite/test_parsing/n_object_non_string_key_but_huge_number_instead.json deleted file mode 100755 index b37fa86..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_non_string_key_but_huge_number_instead.json +++ /dev/null @@ -1 +0,0 @@ -{9999E9999:1} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_repeated_null_null.json b/test/JSONTestSuite/test_parsing/n_object_repeated_null_null.json deleted file mode 100755 index f7d2959..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_repeated_null_null.json +++ /dev/null @@ -1 +0,0 @@ -{null:null,null:null} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_several_trailing_commas.json b/test/JSONTestSuite/test_parsing/n_object_several_trailing_commas.json deleted file mode 100755 index 3c9afe8..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_several_trailing_commas.json +++ /dev/null @@ -1 +0,0 @@ -{"id":0,,,,,} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_single_quote.json b/test/JSONTestSuite/test_parsing/n_object_single_quote.json deleted file mode 100644 index e5cdf97..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_single_quote.json +++ /dev/null @@ -1 +0,0 @@ -{'a':0} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_trailing_comma.json b/test/JSONTestSuite/test_parsing/n_object_trailing_comma.json deleted file mode 100755 index a4b0250..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_trailing_comma.json +++ /dev/null @@ -1 +0,0 @@ -{"id":0,} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_trailing_comment.json b/test/JSONTestSuite/test_parsing/n_object_trailing_comment.json deleted file mode 100644 index a372c65..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_trailing_comment.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b"}/**/ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_trailing_comment_open.json b/test/JSONTestSuite/test_parsing/n_object_trailing_comment_open.json deleted file mode 100644 index d557f41..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_trailing_comment_open.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b"}/**// \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open.json b/test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open.json deleted file mode 100644 index e335136..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b"}// \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open_incomplete.json b/test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open_incomplete.json deleted file mode 100644 index d892e49..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_trailing_comment_slash_open_incomplete.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b"}/ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_two_commas_in_a_row.json b/test/JSONTestSuite/test_parsing/n_object_two_commas_in_a_row.json deleted file mode 100755 index 7c639ae..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_two_commas_in_a_row.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b",,"c":"d"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_unquoted_key.json b/test/JSONTestSuite/test_parsing/n_object_unquoted_key.json deleted file mode 100644 index 8ba1372..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_unquoted_key.json +++ /dev/null @@ -1 +0,0 @@ -{a: "b"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_unterminated-value.json b/test/JSONTestSuite/test_parsing/n_object_unterminated-value.json deleted file mode 100644 index 7fe699a..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_unterminated-value.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"a \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_with_single_string.json b/test/JSONTestSuite/test_parsing/n_object_with_single_string.json deleted file mode 100644 index d63f7fb..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_with_single_string.json +++ /dev/null @@ -1 +0,0 @@ -{ "foo" : "bar", "a" } \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_object_with_trailing_garbage.json b/test/JSONTestSuite/test_parsing/n_object_with_trailing_garbage.json deleted file mode 100644 index 787c8f0..0000000 --- a/test/JSONTestSuite/test_parsing/n_object_with_trailing_garbage.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b"}# \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_single_space.json b/test/JSONTestSuite/test_parsing/n_single_space.json deleted file mode 100755 index 0519ecb..0000000 --- a/test/JSONTestSuite/test_parsing/n_single_space.json +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape.json b/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape.json deleted file mode 100644 index acec66d..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape.json +++ /dev/null @@ -1 +0,0 @@ -["\uD800\"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u.json b/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u.json deleted file mode 100644 index e834b05..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u.json +++ /dev/null @@ -1 +0,0 @@ -["\uD800\u"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1.json b/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1.json deleted file mode 100644 index a04cd34..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1.json +++ /dev/null @@ -1 +0,0 @@ -["\uD800\u1"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1x.json b/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1x.json deleted file mode 100644 index bfbd234..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_1_surrogate_then_escape_u1x.json +++ /dev/null @@ -1 +0,0 @@ -["\uD800\u1x"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_accentuated_char_no_quotes.json b/test/JSONTestSuite/test_parsing/n_string_accentuated_char_no_quotes.json deleted file mode 100644 index fd68956..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_accentuated_char_no_quotes.json +++ /dev/null @@ -1 +0,0 @@ -[é] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_backslash_00.json b/test/JSONTestSuite/test_parsing/n_string_backslash_00.json deleted file mode 100644 index b5bf267b5d4ee922d20cec1543b66d1530ff76cf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6 Ncma!6ieXTS1pox&0a*Y5 diff --git a/test/JSONTestSuite/test_parsing/n_string_escape_x.json b/test/JSONTestSuite/test_parsing/n_string_escape_x.json deleted file mode 100644 index fae2919..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_escape_x.json +++ /dev/null @@ -1 +0,0 @@ -["\x00"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_escaped_backslash_bad.json b/test/JSONTestSuite/test_parsing/n_string_escaped_backslash_bad.json deleted file mode 100755 index 016fcb4..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_escaped_backslash_bad.json +++ /dev/null @@ -1 +0,0 @@ -["\\\"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_escaped_ctrl_char_tab.json b/test/JSONTestSuite/test_parsing/n_string_escaped_ctrl_char_tab.json deleted file mode 100644 index f35ea38..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_escaped_ctrl_char_tab.json +++ /dev/null @@ -1 +0,0 @@ -["\ "] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_escaped_emoji.json b/test/JSONTestSuite/test_parsing/n_string_escaped_emoji.json deleted file mode 100644 index a277754..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_escaped_emoji.json +++ /dev/null @@ -1 +0,0 @@ -["\🌀"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_incomplete_escape.json b/test/JSONTestSuite/test_parsing/n_string_incomplete_escape.json deleted file mode 100755 index 3415c33..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_incomplete_escape.json +++ /dev/null @@ -1 +0,0 @@ -["\"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_incomplete_escaped_character.json b/test/JSONTestSuite/test_parsing/n_string_incomplete_escaped_character.json deleted file mode 100755 index 0f2197e..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_incomplete_escaped_character.json +++ /dev/null @@ -1 +0,0 @@ -["\u00A"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate.json b/test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate.json deleted file mode 100755 index 75504a6..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate.json +++ /dev/null @@ -1 +0,0 @@ -["\uD834\uDd"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate_escape_invalid.json b/test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate_escape_invalid.json deleted file mode 100755 index bd96560..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_incomplete_surrogate_escape_invalid.json +++ /dev/null @@ -1 +0,0 @@ -["\uD800\uD800\x"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_invalid-utf-8-in-escape.json b/test/JSONTestSuite/test_parsing/n_string_invalid-utf-8-in-escape.json deleted file mode 100644 index 0c43006..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_invalid-utf-8-in-escape.json +++ /dev/null @@ -1 +0,0 @@ -["\u"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_invalid_backslash_esc.json b/test/JSONTestSuite/test_parsing/n_string_invalid_backslash_esc.json deleted file mode 100755 index d1eb609..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_invalid_backslash_esc.json +++ /dev/null @@ -1 +0,0 @@ -["\a"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_invalid_unicode_escape.json b/test/JSONTestSuite/test_parsing/n_string_invalid_unicode_escape.json deleted file mode 100644 index 7608cb6..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_invalid_unicode_escape.json +++ /dev/null @@ -1 +0,0 @@ -["\uqqqq"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_invalid_utf8_after_escape.json b/test/JSONTestSuite/test_parsing/n_string_invalid_utf8_after_escape.json deleted file mode 100644 index 2f757a2..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_invalid_utf8_after_escape.json +++ /dev/null @@ -1 +0,0 @@ -["\"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_leading_uescaped_thinspace.json b/test/JSONTestSuite/test_parsing/n_string_leading_uescaped_thinspace.json deleted file mode 100755 index 7b297c6..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_leading_uescaped_thinspace.json +++ /dev/null @@ -1 +0,0 @@ -[\u0020"asd"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_no_quotes_with_bad_escape.json b/test/JSONTestSuite/test_parsing/n_string_no_quotes_with_bad_escape.json deleted file mode 100644 index 01bc70a..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_no_quotes_with_bad_escape.json +++ /dev/null @@ -1 +0,0 @@ -[\n] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_single_doublequote.json b/test/JSONTestSuite/test_parsing/n_string_single_doublequote.json deleted file mode 100755 index 9d68933..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_single_doublequote.json +++ /dev/null @@ -1 +0,0 @@ -" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_single_quote.json b/test/JSONTestSuite/test_parsing/n_string_single_quote.json deleted file mode 100644 index caff239..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_single_quote.json +++ /dev/null @@ -1 +0,0 @@ -['single quote'] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_single_string_no_double_quotes.json b/test/JSONTestSuite/test_parsing/n_string_single_string_no_double_quotes.json deleted file mode 100755 index f2ba8f8..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_single_string_no_double_quotes.json +++ /dev/null @@ -1 +0,0 @@ -abc \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_start_escape_unclosed.json b/test/JSONTestSuite/test_parsing/n_string_start_escape_unclosed.json deleted file mode 100644 index db62a46..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_start_escape_unclosed.json +++ /dev/null @@ -1 +0,0 @@ -["\ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_unescaped_ctrl_char.json b/test/JSONTestSuite/test_parsing/n_string_unescaped_ctrl_char.json deleted file mode 100755 index 9f21348071d3d736bdd469f159cea674c09237af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 7 Ocma!6N@Pe>iUj}$`2oKG diff --git a/test/JSONTestSuite/test_parsing/n_string_unescaped_newline.json b/test/JSONTestSuite/test_parsing/n_string_unescaped_newline.json deleted file mode 100644 index 700d360..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_unescaped_newline.json +++ /dev/null @@ -1,2 +0,0 @@ -["new -line"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_unescaped_tab.json b/test/JSONTestSuite/test_parsing/n_string_unescaped_tab.json deleted file mode 100644 index 160264a..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_unescaped_tab.json +++ /dev/null @@ -1 +0,0 @@ -[" "] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_unicode_CapitalU.json b/test/JSONTestSuite/test_parsing/n_string_unicode_CapitalU.json deleted file mode 100644 index 17332bb..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_unicode_CapitalU.json +++ /dev/null @@ -1 +0,0 @@ -"\UA66D" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_string_with_trailing_garbage.json b/test/JSONTestSuite/test_parsing/n_string_with_trailing_garbage.json deleted file mode 100644 index efe3bd2..0000000 --- a/test/JSONTestSuite/test_parsing/n_string_with_trailing_garbage.json +++ /dev/null @@ -1 +0,0 @@ -""x \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_100000_opening_arrays.json b/test/JSONTestSuite/test_parsing/n_structure_100000_opening_arrays.json deleted file mode 100644 index a4823ee..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_100000_opening_arrays.json +++ /dev/null @@ -1 +0,0 @@ -[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_U+2060_word_joined.json b/test/JSONTestSuite/test_parsing/n_structure_U+2060_word_joined.json deleted file mode 100644 index 81156a6..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_U+2060_word_joined.json +++ /dev/null @@ -1 +0,0 @@ -[⁠] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_UTF8_BOM_no_data.json b/test/JSONTestSuite/test_parsing/n_structure_UTF8_BOM_no_data.json deleted file mode 100755 index 5f28270..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_UTF8_BOM_no_data.json +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_angle_bracket_..json b/test/JSONTestSuite/test_parsing/n_structure_angle_bracket_..json deleted file mode 100755 index a56fef0..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_angle_bracket_..json +++ /dev/null @@ -1 +0,0 @@ -<.> \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_angle_bracket_null.json b/test/JSONTestSuite/test_parsing/n_structure_angle_bracket_null.json deleted file mode 100755 index 617f262..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_angle_bracket_null.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_array_trailing_garbage.json b/test/JSONTestSuite/test_parsing/n_structure_array_trailing_garbage.json deleted file mode 100644 index 5a745e6..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_array_trailing_garbage.json +++ /dev/null @@ -1 +0,0 @@ -[1]x \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_array_with_extra_array_close.json b/test/JSONTestSuite/test_parsing/n_structure_array_with_extra_array_close.json deleted file mode 100755 index 6cfb139..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_array_with_extra_array_close.json +++ /dev/null @@ -1 +0,0 @@ -[1]] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_array_with_unclosed_string.json b/test/JSONTestSuite/test_parsing/n_structure_array_with_unclosed_string.json deleted file mode 100755 index ba6b178..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_array_with_unclosed_string.json +++ /dev/null @@ -1 +0,0 @@ -["asd] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_ascii-unicode-identifier.json b/test/JSONTestSuite/test_parsing/n_structure_ascii-unicode-identifier.json deleted file mode 100644 index ef2ab62..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_ascii-unicode-identifier.json +++ /dev/null @@ -1 +0,0 @@ -aå \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_capitalized_True.json b/test/JSONTestSuite/test_parsing/n_structure_capitalized_True.json deleted file mode 100755 index 7cd8846..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_capitalized_True.json +++ /dev/null @@ -1 +0,0 @@ -[True] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_close_unopened_array.json b/test/JSONTestSuite/test_parsing/n_structure_close_unopened_array.json deleted file mode 100755 index d2af0c6..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_close_unopened_array.json +++ /dev/null @@ -1 +0,0 @@ -1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_comma_instead_of_closing_brace.json b/test/JSONTestSuite/test_parsing/n_structure_comma_instead_of_closing_brace.json deleted file mode 100644 index ac61b82..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_comma_instead_of_closing_brace.json +++ /dev/null @@ -1 +0,0 @@ -{"x": true, \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_double_array.json b/test/JSONTestSuite/test_parsing/n_structure_double_array.json deleted file mode 100755 index 058d162..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_double_array.json +++ /dev/null @@ -1 +0,0 @@ -[][] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_end_array.json b/test/JSONTestSuite/test_parsing/n_structure_end_array.json deleted file mode 100644 index 54caf60..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_end_array.json +++ /dev/null @@ -1 +0,0 @@ -] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_incomplete_UTF8_BOM.json b/test/JSONTestSuite/test_parsing/n_structure_incomplete_UTF8_BOM.json deleted file mode 100755 index bfcdd51..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_incomplete_UTF8_BOM.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_lone-invalid-utf-8.json b/test/JSONTestSuite/test_parsing/n_structure_lone-invalid-utf-8.json deleted file mode 100644 index 8b1296c..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_lone-invalid-utf-8.json +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_lone-open-bracket.json b/test/JSONTestSuite/test_parsing/n_structure_lone-open-bracket.json deleted file mode 100644 index 8e2f0be..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_lone-open-bracket.json +++ /dev/null @@ -1 +0,0 @@ -[ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_no_data.json b/test/JSONTestSuite/test_parsing/n_structure_no_data.json deleted file mode 100644 index e69de29..0000000 diff --git a/test/JSONTestSuite/test_parsing/n_structure_null-byte-outside-string.json b/test/JSONTestSuite/test_parsing/n_structure_null-byte-outside-string.json deleted file mode 100644 index 326db14422a756e9bd39221edf37b844cb8471c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3 Kcma!Mhy?%vaR9jh diff --git a/test/JSONTestSuite/test_parsing/n_structure_number_with_trailing_garbage.json b/test/JSONTestSuite/test_parsing/n_structure_number_with_trailing_garbage.json deleted file mode 100644 index 0746539..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_number_with_trailing_garbage.json +++ /dev/null @@ -1 +0,0 @@ -2@ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_object_followed_by_closing_object.json b/test/JSONTestSuite/test_parsing/n_structure_object_followed_by_closing_object.json deleted file mode 100644 index aa9ebae..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_object_followed_by_closing_object.json +++ /dev/null @@ -1 +0,0 @@ -{}} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_object_unclosed_no_value.json b/test/JSONTestSuite/test_parsing/n_structure_object_unclosed_no_value.json deleted file mode 100644 index 17d0451..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_object_unclosed_no_value.json +++ /dev/null @@ -1 +0,0 @@ -{"": \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_object_with_comment.json b/test/JSONTestSuite/test_parsing/n_structure_object_with_comment.json deleted file mode 100644 index ed1b569..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_object_with_comment.json +++ /dev/null @@ -1 +0,0 @@ -{"a":/*comment*/"b"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_object_with_trailing_garbage.json b/test/JSONTestSuite/test_parsing/n_structure_object_with_trailing_garbage.json deleted file mode 100644 index 9ca2336..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_object_with_trailing_garbage.json +++ /dev/null @@ -1 +0,0 @@ -{"a": true} "x" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_array_apostrophe.json b/test/JSONTestSuite/test_parsing/n_structure_open_array_apostrophe.json deleted file mode 100644 index 8bebe3a..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_array_apostrophe.json +++ /dev/null @@ -1 +0,0 @@ -[' \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_array_comma.json b/test/JSONTestSuite/test_parsing/n_structure_open_array_comma.json deleted file mode 100644 index 6295fdc..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_array_comma.json +++ /dev/null @@ -1 +0,0 @@ -[, \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_array_object.json b/test/JSONTestSuite/test_parsing/n_structure_open_array_object.json deleted file mode 100644 index e870445..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_array_object.json +++ /dev/null @@ -1 +0,0 @@ -[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"":[{"": diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_array_open_object.json b/test/JSONTestSuite/test_parsing/n_structure_open_array_open_object.json deleted file mode 100644 index 7a63c8c..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_array_open_object.json +++ /dev/null @@ -1 +0,0 @@ -[{ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_array_open_string.json b/test/JSONTestSuite/test_parsing/n_structure_open_array_open_string.json deleted file mode 100644 index 9822a6b..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_array_open_string.json +++ /dev/null @@ -1 +0,0 @@ -["a \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_array_string.json b/test/JSONTestSuite/test_parsing/n_structure_open_array_string.json deleted file mode 100644 index 42a6193..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_array_string.json +++ /dev/null @@ -1 +0,0 @@ -["a" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_object.json b/test/JSONTestSuite/test_parsing/n_structure_open_object.json deleted file mode 100644 index 81750b9..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_object.json +++ /dev/null @@ -1 +0,0 @@ -{ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_object_close_array.json b/test/JSONTestSuite/test_parsing/n_structure_open_object_close_array.json deleted file mode 100755 index eebc700..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_object_close_array.json +++ /dev/null @@ -1 +0,0 @@ -{] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_object_comma.json b/test/JSONTestSuite/test_parsing/n_structure_open_object_comma.json deleted file mode 100644 index 47bc910..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_object_comma.json +++ /dev/null @@ -1 +0,0 @@ -{, \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_object_open_array.json b/test/JSONTestSuite/test_parsing/n_structure_open_object_open_array.json deleted file mode 100644 index 381ede5..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_object_open_array.json +++ /dev/null @@ -1 +0,0 @@ -{[ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_object_open_string.json b/test/JSONTestSuite/test_parsing/n_structure_open_object_open_string.json deleted file mode 100644 index 328c30c..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_object_open_string.json +++ /dev/null @@ -1 +0,0 @@ -{"a \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_object_string_with_apostrophes.json b/test/JSONTestSuite/test_parsing/n_structure_open_object_string_with_apostrophes.json deleted file mode 100644 index 9dba170..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_object_string_with_apostrophes.json +++ /dev/null @@ -1 +0,0 @@ -{'a' \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_open_open.json b/test/JSONTestSuite/test_parsing/n_structure_open_open.json deleted file mode 100644 index 841fd5f..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_open_open.json +++ /dev/null @@ -1 +0,0 @@ -["\{["\{["\{["\{ \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_single_eacute.json b/test/JSONTestSuite/test_parsing/n_structure_single_eacute.json deleted file mode 100644 index 92a39f3..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_single_eacute.json +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_single_star.json b/test/JSONTestSuite/test_parsing/n_structure_single_star.json deleted file mode 100755 index f59ec20..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_single_star.json +++ /dev/null @@ -1 +0,0 @@ -* \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_trailing_#.json b/test/JSONTestSuite/test_parsing/n_structure_trailing_#.json deleted file mode 100644 index 8986110..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_trailing_#.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b"}#{} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_uescaped_LF_before_string.json b/test/JSONTestSuite/test_parsing/n_structure_uescaped_LF_before_string.json deleted file mode 100755 index df2f0f2..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_uescaped_LF_before_string.json +++ /dev/null @@ -1 +0,0 @@ -[\u000A""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array.json b/test/JSONTestSuite/test_parsing/n_structure_unclosed_array.json deleted file mode 100755 index 1120951..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array.json +++ /dev/null @@ -1 +0,0 @@ -[1 \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_partial_null.json b/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_partial_null.json deleted file mode 100644 index 0d59176..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_partial_null.json +++ /dev/null @@ -1 +0,0 @@ -[ false, nul \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_false.json b/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_false.json deleted file mode 100644 index a2ff850..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_false.json +++ /dev/null @@ -1 +0,0 @@ -[ true, fals \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_true.json b/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_true.json deleted file mode 100644 index 3149e8f..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_unclosed_array_unfinished_true.json +++ /dev/null @@ -1 +0,0 @@ -[ false, tru \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_unclosed_object.json b/test/JSONTestSuite/test_parsing/n_structure_unclosed_object.json deleted file mode 100755 index 694d69d..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_unclosed_object.json +++ /dev/null @@ -1 +0,0 @@ -{"asd":"asd" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_unicode-identifier.json b/test/JSONTestSuite/test_parsing/n_structure_unicode-identifier.json deleted file mode 100644 index 7284aea..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_unicode-identifier.json +++ /dev/null @@ -1 +0,0 @@ -å \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_whitespace_U+2060_word_joiner.json b/test/JSONTestSuite/test_parsing/n_structure_whitespace_U+2060_word_joiner.json deleted file mode 100755 index 81156a6..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_whitespace_U+2060_word_joiner.json +++ /dev/null @@ -1 +0,0 @@ -[⁠] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/n_structure_whitespace_formfeed.json b/test/JSONTestSuite/test_parsing/n_structure_whitespace_formfeed.json deleted file mode 100755 index a9ea535..0000000 --- a/test/JSONTestSuite/test_parsing/n_structure_whitespace_formfeed.json +++ /dev/null @@ -1 +0,0 @@ -[ ] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_arraysWithSpaces.json b/test/JSONTestSuite/test_parsing/y_array_arraysWithSpaces.json deleted file mode 100755 index 5822907..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_arraysWithSpaces.json +++ /dev/null @@ -1 +0,0 @@ -[[] ] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_empty-string.json b/test/JSONTestSuite/test_parsing/y_array_empty-string.json deleted file mode 100644 index 93b6be2..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_empty-string.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_empty.json b/test/JSONTestSuite/test_parsing/y_array_empty.json deleted file mode 100755 index 0637a08..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_empty.json +++ /dev/null @@ -1 +0,0 @@ -[] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_ending_with_newline.json b/test/JSONTestSuite/test_parsing/y_array_ending_with_newline.json deleted file mode 100755 index eac5f7b..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_ending_with_newline.json +++ /dev/null @@ -1 +0,0 @@ -["a"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_false.json b/test/JSONTestSuite/test_parsing/y_array_false.json deleted file mode 100644 index 67b2f07..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_false.json +++ /dev/null @@ -1 +0,0 @@ -[false] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_heterogeneous.json b/test/JSONTestSuite/test_parsing/y_array_heterogeneous.json deleted file mode 100755 index d3c1e26..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_heterogeneous.json +++ /dev/null @@ -1 +0,0 @@ -[null, 1, "1", {}] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_null.json b/test/JSONTestSuite/test_parsing/y_array_null.json deleted file mode 100644 index 500db4a..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_null.json +++ /dev/null @@ -1 +0,0 @@ -[null] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_with_1_and_newline.json b/test/JSONTestSuite/test_parsing/y_array_with_1_and_newline.json deleted file mode 100644 index 9948255..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_with_1_and_newline.json +++ /dev/null @@ -1,2 +0,0 @@ -[1 -] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_with_leading_space.json b/test/JSONTestSuite/test_parsing/y_array_with_leading_space.json deleted file mode 100755 index 18bfe64..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_with_leading_space.json +++ /dev/null @@ -1 +0,0 @@ - [1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_with_several_null.json b/test/JSONTestSuite/test_parsing/y_array_with_several_null.json deleted file mode 100755 index 99f6c5d..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_with_several_null.json +++ /dev/null @@ -1 +0,0 @@ -[1,null,null,null,2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_array_with_trailing_space.json b/test/JSONTestSuite/test_parsing/y_array_with_trailing_space.json deleted file mode 100755 index de9e7a9..0000000 --- a/test/JSONTestSuite/test_parsing/y_array_with_trailing_space.json +++ /dev/null @@ -1 +0,0 @@ -[2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number.json b/test/JSONTestSuite/test_parsing/y_number.json deleted file mode 100644 index e5f5cc3..0000000 --- a/test/JSONTestSuite/test_parsing/y_number.json +++ /dev/null @@ -1 +0,0 @@ -[123e65] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_0e+1.json b/test/JSONTestSuite/test_parsing/y_number_0e+1.json deleted file mode 100755 index d1d3967..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_0e+1.json +++ /dev/null @@ -1 +0,0 @@ -[0e+1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_0e1.json b/test/JSONTestSuite/test_parsing/y_number_0e1.json deleted file mode 100755 index 3283a79..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_0e1.json +++ /dev/null @@ -1 +0,0 @@ -[0e1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_after_space.json b/test/JSONTestSuite/test_parsing/y_number_after_space.json deleted file mode 100644 index 623570d..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_after_space.json +++ /dev/null @@ -1 +0,0 @@ -[ 4] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_double_close_to_zero.json b/test/JSONTestSuite/test_parsing/y_number_double_close_to_zero.json deleted file mode 100755 index 96555ff..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_double_close_to_zero.json +++ /dev/null @@ -1 +0,0 @@ -[-0.000000000000000000000000000000000000000000000000000000000000000000000000000001] diff --git a/test/JSONTestSuite/test_parsing/y_number_int_with_exp.json b/test/JSONTestSuite/test_parsing/y_number_int_with_exp.json deleted file mode 100755 index a4ca9e7..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_int_with_exp.json +++ /dev/null @@ -1 +0,0 @@ -[20e1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_minus_zero.json b/test/JSONTestSuite/test_parsing/y_number_minus_zero.json deleted file mode 100755 index 37af131..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_minus_zero.json +++ /dev/null @@ -1 +0,0 @@ -[-0] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_negative_int.json b/test/JSONTestSuite/test_parsing/y_number_negative_int.json deleted file mode 100644 index 8e30f8b..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_negative_int.json +++ /dev/null @@ -1 +0,0 @@ -[-123] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_negative_one.json b/test/JSONTestSuite/test_parsing/y_number_negative_one.json deleted file mode 100644 index 99d21a2..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_negative_one.json +++ /dev/null @@ -1 +0,0 @@ -[-1] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_negative_zero.json b/test/JSONTestSuite/test_parsing/y_number_negative_zero.json deleted file mode 100644 index 37af131..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_negative_zero.json +++ /dev/null @@ -1 +0,0 @@ -[-0] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_real_capital_e.json b/test/JSONTestSuite/test_parsing/y_number_real_capital_e.json deleted file mode 100644 index 6edbdfc..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_real_capital_e.json +++ /dev/null @@ -1 +0,0 @@ -[1E22] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_real_capital_e_neg_exp.json b/test/JSONTestSuite/test_parsing/y_number_real_capital_e_neg_exp.json deleted file mode 100644 index 0a01bd3..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_real_capital_e_neg_exp.json +++ /dev/null @@ -1 +0,0 @@ -[1E-2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.json b/test/JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.json deleted file mode 100644 index 5a8fc09..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_real_capital_e_pos_exp.json +++ /dev/null @@ -1 +0,0 @@ -[1E+2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_real_exponent.json b/test/JSONTestSuite/test_parsing/y_number_real_exponent.json deleted file mode 100644 index da2522d..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_real_exponent.json +++ /dev/null @@ -1 +0,0 @@ -[123e45] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_real_fraction_exponent.json b/test/JSONTestSuite/test_parsing/y_number_real_fraction_exponent.json deleted file mode 100644 index 3944a7a..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_real_fraction_exponent.json +++ /dev/null @@ -1 +0,0 @@ -[123.456e78] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_real_neg_exp.json b/test/JSONTestSuite/test_parsing/y_number_real_neg_exp.json deleted file mode 100644 index ca40d3c..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_real_neg_exp.json +++ /dev/null @@ -1 +0,0 @@ -[1e-2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_real_pos_exponent.json b/test/JSONTestSuite/test_parsing/y_number_real_pos_exponent.json deleted file mode 100644 index 343601d..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_real_pos_exponent.json +++ /dev/null @@ -1 +0,0 @@ -[1e+2] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_simple_int.json b/test/JSONTestSuite/test_parsing/y_number_simple_int.json deleted file mode 100644 index e47f69a..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_simple_int.json +++ /dev/null @@ -1 +0,0 @@ -[123] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_number_simple_real.json b/test/JSONTestSuite/test_parsing/y_number_simple_real.json deleted file mode 100644 index b02878e..0000000 --- a/test/JSONTestSuite/test_parsing/y_number_simple_real.json +++ /dev/null @@ -1 +0,0 @@ -[123.456789] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object.json b/test/JSONTestSuite/test_parsing/y_object.json deleted file mode 100755 index 78262ed..0000000 --- a/test/JSONTestSuite/test_parsing/y_object.json +++ /dev/null @@ -1 +0,0 @@ -{"asd":"sdf", "dfg":"fgh"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_basic.json b/test/JSONTestSuite/test_parsing/y_object_basic.json deleted file mode 100755 index 646bbe7..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_basic.json +++ /dev/null @@ -1 +0,0 @@ -{"asd":"sdf"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_duplicated_key.json b/test/JSONTestSuite/test_parsing/y_object_duplicated_key.json deleted file mode 100755 index bbc2e1c..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_duplicated_key.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b","a":"c"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_duplicated_key_and_value.json b/test/JSONTestSuite/test_parsing/y_object_duplicated_key_and_value.json deleted file mode 100755 index 211581c..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_duplicated_key_and_value.json +++ /dev/null @@ -1 +0,0 @@ -{"a":"b","a":"b"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_empty.json b/test/JSONTestSuite/test_parsing/y_object_empty.json deleted file mode 100644 index 9e26dfe..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_empty.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_empty_key.json b/test/JSONTestSuite/test_parsing/y_object_empty_key.json deleted file mode 100755 index c0013d3..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_empty_key.json +++ /dev/null @@ -1 +0,0 @@ -{"":0} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_escaped_null_in_key.json b/test/JSONTestSuite/test_parsing/y_object_escaped_null_in_key.json deleted file mode 100644 index 593f0f6..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_escaped_null_in_key.json +++ /dev/null @@ -1 +0,0 @@ -{"foo\u0000bar": 42} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_extreme_numbers.json b/test/JSONTestSuite/test_parsing/y_object_extreme_numbers.json deleted file mode 100644 index a0d3531..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_extreme_numbers.json +++ /dev/null @@ -1 +0,0 @@ -{ "min": -1.0e+28, "max": 1.0e+28 } \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_long_strings.json b/test/JSONTestSuite/test_parsing/y_object_long_strings.json deleted file mode 100644 index bdc4a08..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_long_strings.json +++ /dev/null @@ -1 +0,0 @@ -{"x":[{"id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}], "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_simple.json b/test/JSONTestSuite/test_parsing/y_object_simple.json deleted file mode 100644 index dacac91..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_simple.json +++ /dev/null @@ -1 +0,0 @@ -{"a":[]} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_object_string_unicode.json b/test/JSONTestSuite/test_parsing/y_object_string_unicode.json deleted file mode 100644 index 8effdb2..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_string_unicode.json +++ /dev/null @@ -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 --git a/test/JSONTestSuite/test_parsing/y_object_with_newlines.json b/test/JSONTestSuite/test_parsing/y_object_with_newlines.json deleted file mode 100644 index 246ec6b..0000000 --- a/test/JSONTestSuite/test_parsing/y_object_with_newlines.json +++ /dev/null @@ -1,3 +0,0 @@ -{ -"a": "b" -} \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json b/test/JSONTestSuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json deleted file mode 100755 index 9967dde..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_1_2_3_bytes_UTF-8_sequences.json +++ /dev/null @@ -1 +0,0 @@ -["\u0060\u012a\u12AB"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pair.json b/test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pair.json deleted file mode 100755 index 996875c..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pair.json +++ /dev/null @@ -1 +0,0 @@ -["\uD801\udc37"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pairs.json b/test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pairs.json deleted file mode 100755 index 3401021..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_accepted_surrogate_pairs.json +++ /dev/null @@ -1 +0,0 @@ -["\ud83d\ude39\ud83d\udc8d"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_allowed_escapes.json b/test/JSONTestSuite/test_parsing/y_string_allowed_escapes.json deleted file mode 100644 index 7f49553..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_allowed_escapes.json +++ /dev/null @@ -1 +0,0 @@ -["\"\\\/\b\f\n\r\t"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_backslash_and_u_escaped_zero.json b/test/JSONTestSuite/test_parsing/y_string_backslash_and_u_escaped_zero.json deleted file mode 100755 index d4439ed..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_backslash_and_u_escaped_zero.json +++ /dev/null @@ -1 +0,0 @@ -["\\u0000"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_backslash_doublequotes.json b/test/JSONTestSuite/test_parsing/y_string_backslash_doublequotes.json deleted file mode 100644 index ae03243..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_backslash_doublequotes.json +++ /dev/null @@ -1 +0,0 @@ -["\""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_comments.json b/test/JSONTestSuite/test_parsing/y_string_comments.json deleted file mode 100644 index 2260c20..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_comments.json +++ /dev/null @@ -1 +0,0 @@ -["a/*b*/c/*d//e"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_double_escape_a.json b/test/JSONTestSuite/test_parsing/y_string_double_escape_a.json deleted file mode 100644 index 6715d6f..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_double_escape_a.json +++ /dev/null @@ -1 +0,0 @@ -["\\a"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_double_escape_n.json b/test/JSONTestSuite/test_parsing/y_string_double_escape_n.json deleted file mode 100644 index 44ca56c..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_double_escape_n.json +++ /dev/null @@ -1 +0,0 @@ -["\\n"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_escaped_control_character.json b/test/JSONTestSuite/test_parsing/y_string_escaped_control_character.json deleted file mode 100644 index 5b014a9..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_escaped_control_character.json +++ /dev/null @@ -1 +0,0 @@ -["\u0012"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_escaped_noncharacter.json b/test/JSONTestSuite/test_parsing/y_string_escaped_noncharacter.json deleted file mode 100755 index 2ff52e2..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_escaped_noncharacter.json +++ /dev/null @@ -1 +0,0 @@ -["\uFFFF"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_in_array.json b/test/JSONTestSuite/test_parsing/y_string_in_array.json deleted file mode 100755 index 21d7ae4..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_in_array.json +++ /dev/null @@ -1 +0,0 @@ -["asd"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_in_array_with_leading_space.json b/test/JSONTestSuite/test_parsing/y_string_in_array_with_leading_space.json deleted file mode 100755 index 9e1887c..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_in_array_with_leading_space.json +++ /dev/null @@ -1 +0,0 @@ -[ "asd"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_last_surrogates_1_and_2.json b/test/JSONTestSuite/test_parsing/y_string_last_surrogates_1_and_2.json deleted file mode 100644 index 3919cef..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_last_surrogates_1_and_2.json +++ /dev/null @@ -1 +0,0 @@ -["\uDBFF\uDFFF"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_nbsp_uescaped.json b/test/JSONTestSuite/test_parsing/y_string_nbsp_uescaped.json deleted file mode 100644 index 2085ab1..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_nbsp_uescaped.json +++ /dev/null @@ -1 +0,0 @@ -["new\u00A0line"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json b/test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json deleted file mode 100755 index 059e4d9..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+10FFFF.json +++ /dev/null @@ -1 +0,0 @@ -["􏿿"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json b/test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json deleted file mode 100755 index 4c913bd..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_nonCharacterInUTF-8_U+FFFF.json +++ /dev/null @@ -1 +0,0 @@ -["￿"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_null_escape.json b/test/JSONTestSuite/test_parsing/y_string_null_escape.json deleted file mode 100644 index c1ad844..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_null_escape.json +++ /dev/null @@ -1 +0,0 @@ -["\u0000"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_one-byte-utf-8.json b/test/JSONTestSuite/test_parsing/y_string_one-byte-utf-8.json deleted file mode 100644 index 1571859..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_one-byte-utf-8.json +++ /dev/null @@ -1 +0,0 @@ -["\u002c"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_pi.json b/test/JSONTestSuite/test_parsing/y_string_pi.json deleted file mode 100644 index 9df11ae..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_pi.json +++ /dev/null @@ -1 +0,0 @@ -["π"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json b/test/JSONTestSuite/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json deleted file mode 100755 index 10a33a1..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_reservedCharacterInUTF-8_U+1BFFF.json +++ /dev/null @@ -1 +0,0 @@ -["𛿿"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_simple_ascii.json b/test/JSONTestSuite/test_parsing/y_string_simple_ascii.json deleted file mode 100644 index 8cadf7d..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_simple_ascii.json +++ /dev/null @@ -1 +0,0 @@ -["asd "] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_space.json b/test/JSONTestSuite/test_parsing/y_string_space.json deleted file mode 100644 index efd782c..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_space.json +++ /dev/null @@ -1 +0,0 @@ -" " \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json b/test/JSONTestSuite/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json deleted file mode 100755 index 7620b66..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_surrogates_U+1D11E_MUSICAL_SYMBOL_G_CLEF.json +++ /dev/null @@ -1 +0,0 @@ -["\uD834\uDd1e"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_three-byte-utf-8.json b/test/JSONTestSuite/test_parsing/y_string_three-byte-utf-8.json deleted file mode 100644 index 108f1d6..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_three-byte-utf-8.json +++ /dev/null @@ -1 +0,0 @@ -["\u0821"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_two-byte-utf-8.json b/test/JSONTestSuite/test_parsing/y_string_two-byte-utf-8.json deleted file mode 100644 index 461503c..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_two-byte-utf-8.json +++ /dev/null @@ -1 +0,0 @@ -["\u0123"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_u+2028_line_sep.json b/test/JSONTestSuite/test_parsing/y_string_u+2028_line_sep.json deleted file mode 100755 index 897b602..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_u+2028_line_sep.json +++ /dev/null @@ -1 +0,0 @@ -["
"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_u+2029_par_sep.json b/test/JSONTestSuite/test_parsing/y_string_u+2029_par_sep.json deleted file mode 100755 index 8cd998c..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_u+2029_par_sep.json +++ /dev/null @@ -1 +0,0 @@ -["
"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_uEscape.json b/test/JSONTestSuite/test_parsing/y_string_uEscape.json deleted file mode 100755 index f7b41a0..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_uEscape.json +++ /dev/null @@ -1 +0,0 @@ -["\u0061\u30af\u30EA\u30b9"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_uescaped_newline.json b/test/JSONTestSuite/test_parsing/y_string_uescaped_newline.json deleted file mode 100644 index 3a5a220..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_uescaped_newline.json +++ /dev/null @@ -1 +0,0 @@ -["new\u000Aline"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unescaped_char_delete.json b/test/JSONTestSuite/test_parsing/y_string_unescaped_char_delete.json deleted file mode 100755 index 7d064f4..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unescaped_char_delete.json +++ /dev/null @@ -1 +0,0 @@ -[""] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode.json b/test/JSONTestSuite/test_parsing/y_string_unicode.json deleted file mode 100644 index 3598095..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode.json +++ /dev/null @@ -1 +0,0 @@ -["\uA66D"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicodeEscapedBackslash.json b/test/JSONTestSuite/test_parsing/y_string_unicodeEscapedBackslash.json deleted file mode 100755 index 0bb3b51..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicodeEscapedBackslash.json +++ /dev/null @@ -1 +0,0 @@ -["\u005C"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_2.json b/test/JSONTestSuite/test_parsing/y_string_unicode_2.json deleted file mode 100644 index a7dcb97..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_2.json +++ /dev/null @@ -1 +0,0 @@ -["⍂㈴⍂"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_U+10FFFE_nonchar.json b/test/JSONTestSuite/test_parsing/y_string_unicode_U+10FFFE_nonchar.json deleted file mode 100644 index 9a8370b..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_U+10FFFE_nonchar.json +++ /dev/null @@ -1 +0,0 @@ -["\uDBFF\uDFFE"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_U+1FFFE_nonchar.json b/test/JSONTestSuite/test_parsing/y_string_unicode_U+1FFFE_nonchar.json deleted file mode 100644 index c51f8ae..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_U+1FFFE_nonchar.json +++ /dev/null @@ -1 +0,0 @@ -["\uD83F\uDFFE"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json b/test/JSONTestSuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json deleted file mode 100644 index 626d5f8..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_U+200B_ZERO_WIDTH_SPACE.json +++ /dev/null @@ -1 +0,0 @@ -["\u200B"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json b/test/JSONTestSuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json deleted file mode 100644 index 1e23972..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_U+2064_invisible_plus.json +++ /dev/null @@ -1 +0,0 @@ -["\u2064"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_U+FDD0_nonchar.json b/test/JSONTestSuite/test_parsing/y_string_unicode_U+FDD0_nonchar.json deleted file mode 100644 index 18ef151..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_U+FDD0_nonchar.json +++ /dev/null @@ -1 +0,0 @@ -["\uFDD0"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_U+FFFE_nonchar.json b/test/JSONTestSuite/test_parsing/y_string_unicode_U+FFFE_nonchar.json deleted file mode 100644 index 13d261f..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_U+FFFE_nonchar.json +++ /dev/null @@ -1 +0,0 @@ -["\uFFFE"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_unicode_escaped_double_quote.json b/test/JSONTestSuite/test_parsing/y_string_unicode_escaped_double_quote.json deleted file mode 100755 index 4e62578..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_unicode_escaped_double_quote.json +++ /dev/null @@ -1 +0,0 @@ -["\u0022"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_utf8.json b/test/JSONTestSuite/test_parsing/y_string_utf8.json deleted file mode 100644 index 4087843..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_utf8.json +++ /dev/null @@ -1 +0,0 @@ -["€𝄞"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_string_with_del_character.json b/test/JSONTestSuite/test_parsing/y_string_with_del_character.json deleted file mode 100755 index 8bd2490..0000000 --- a/test/JSONTestSuite/test_parsing/y_string_with_del_character.json +++ /dev/null @@ -1 +0,0 @@ -["aa"] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_lonely_false.json b/test/JSONTestSuite/test_parsing/y_structure_lonely_false.json deleted file mode 100644 index 02e4a84..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_lonely_false.json +++ /dev/null @@ -1 +0,0 @@ -false \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_lonely_int.json b/test/JSONTestSuite/test_parsing/y_structure_lonely_int.json deleted file mode 100755 index f70d7bb..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_lonely_int.json +++ /dev/null @@ -1 +0,0 @@ -42 \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_lonely_negative_real.json b/test/JSONTestSuite/test_parsing/y_structure_lonely_negative_real.json deleted file mode 100755 index b5135a2..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_lonely_negative_real.json +++ /dev/null @@ -1 +0,0 @@ --0.1 \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_lonely_null.json b/test/JSONTestSuite/test_parsing/y_structure_lonely_null.json deleted file mode 100644 index ec747fa..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_lonely_null.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_lonely_string.json b/test/JSONTestSuite/test_parsing/y_structure_lonely_string.json deleted file mode 100755 index b6e982c..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_lonely_string.json +++ /dev/null @@ -1 +0,0 @@ -"asd" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_lonely_true.json b/test/JSONTestSuite/test_parsing/y_structure_lonely_true.json deleted file mode 100755 index f32a580..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_lonely_true.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_string_empty.json b/test/JSONTestSuite/test_parsing/y_structure_string_empty.json deleted file mode 100644 index 3cc762b..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_string_empty.json +++ /dev/null @@ -1 +0,0 @@ -"" \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_trailing_newline.json b/test/JSONTestSuite/test_parsing/y_structure_trailing_newline.json deleted file mode 100644 index 0c3426d..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_trailing_newline.json +++ /dev/null @@ -1 +0,0 @@ -["a"] diff --git a/test/JSONTestSuite/test_parsing/y_structure_true_in_array.json b/test/JSONTestSuite/test_parsing/y_structure_true_in_array.json deleted file mode 100644 index de601e3..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_true_in_array.json +++ /dev/null @@ -1 +0,0 @@ -[true] \ No newline at end of file diff --git a/test/JSONTestSuite/test_parsing/y_structure_whitespace_array.json b/test/JSONTestSuite/test_parsing/y_structure_whitespace_array.json deleted file mode 100644 index 2bedf7f..0000000 --- a/test/JSONTestSuite/test_parsing/y_structure_whitespace_array.json +++ /dev/null @@ -1 +0,0 @@ - [] \ No newline at end of file diff --git a/test/feed.test.ts b/test/feed.test.ts new file mode 100644 index 0000000..0a00a12 --- /dev/null +++ b/test/feed.test.ts @@ -0,0 +1,429 @@ +/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */ + +import { test, describe } from 'node:test' +import assert from 'node:assert' + +import { Jsonic } from 'jsonic' +import { Feed, parseFeed, detect } from '../dist/feed.js' +import type { + AtomFeed, + Rss1Feed, + Rss2Feed, +} from '../dist/feed.js' + + +// Sample feeds. The Atom 1.0 sample is the canonical example from RFC 4287 +// section 1.1. The RSS 2.0 / 0.91 / RDF samples are minimal hand-written +// fixtures that exercise the elements each parser cares about. + +const ATOM_10 = ` + + Example Feed + A subtitle. + + + 2003-12-13T18:30:02Z + + John Doe + johndoe@example.com + + urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 + (c) 2003 John Doe + Example Toolkit + + + Atom-Powered Robots Run Amok + + + urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a + 2003-12-13T18:30:02Z + 2003-12-13T08:29:29-04:00 + Some text. + <p>hi</p> + + +` + +const ATOM_03 = ` + + Example 0.3 Feed + An older feed + + 2003-12-13T18:30:02Z + Jane + tag:example.org,2003:1 + + Old Entry + + tag:example.org,2003:2 + 2003-12-13T08:29:29-04:00 + 2003-12-13T18:30:02Z + +` + +const RSS_20 = ` + + + RSS 2 Sample + http://example.com/ + RSS 2.0 description + en-us + Wed, 13 Dec 2003 18:30:02 GMT + Wed, 13 Dec 2003 19:30:02 GMT + editor@example.com (Edna Editor) + my generator + News + 60 + + http://example.com/logo.png + Logo + http://example.com/ + 96 + 32 + + 023 + Sunday + + RSS Item 1 + http://example.com/1 + Item one body + j@example.com (Jane Doe) + cats + birds + http://example.com/1#comments + + item-1-guid + Wed, 13 Dec 2003 18:30:02 GMT + Source name + + + RSS Item 2 + http://example.com/2 + + +` + +const RSS_091 = ` + + + RSS 0.91 + http://example.com/ + An old feed + en-us + + Item + http://example.com/i1 + Body + + +` + +const RSS_092 = ` + + + RSS 0.92 + http://example.com/ + 0.92 feed + + Item + + + +` + +const RSS_10 = ` + + + RSS 1.0 Example + http://example.org/ + An RDF-based feed + + + + + + + + Item One + http://example.org/items/1 + Item one + +` + +const RSS_090 = ` + + + RSS 0.90 + http://example.org/ + old + + + Item + http://example.org/1 + +` + + +describe('feed - format detection', () => { + test('detect atom 1.0', () => { + const root = Jsonic.make().use(require('@jsonic/xml').Xml)(ATOM_10) + assert.deepEqual(detect(root), { dialect: 'atom', version: 'atom10' }) + }) + + test('detect atom 0.3', () => { + const root = Jsonic.make().use(require('@jsonic/xml').Xml)(ATOM_03) + assert.deepEqual(detect(root), { dialect: 'atom', version: 'atom03' }) + }) + + test('detect rss 2.0', () => { + const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_20) + assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss20' }) + }) + + test('detect rss 0.92', () => { + const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_092) + assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss092' }) + }) + + test('detect rss 0.91', () => { + const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_091) + assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss091u' }) + }) + + test('detect rss 1.0 (rdf)', () => { + const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_10) + assert.deepEqual(detect(root), { dialect: 'rdf', version: 'rss10' }) + }) + + test('detect rss 0.90 (rdf)', () => { + const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_090) + assert.deepEqual(detect(root), { dialect: 'rdf', version: 'rss090' }) + }) +}) + + +describe('feed - default Atom output', () => { + test('atom 1.0 round-trips through Atom output', () => { + const f = parseFeed(ATOM_10) as AtomFeed + assert.equal(f.format, 'atom') + assert.equal(f.version, '1.0') + assert.equal(f.id, 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6') + assert.deepEqual(f.title, { type: 'text', value: 'Example Feed' }) + assert.deepEqual(f.subtitle, { type: 'text', value: 'A subtitle.' }) + assert.equal(f.updated, '2003-12-13T18:30:02Z') + assert.equal(f.authors?.[0].name, 'John Doe') + assert.equal(f.authors?.[0].email, 'johndoe@example.com') + assert.deepEqual(f.rights, { type: 'text', value: '(c) 2003 John Doe' }) + assert.equal(f.generator?.value, 'Example Toolkit') + assert.equal(f.generator?.version, '1.2') + assert.equal(f.categories?.[0].term, 'news') + assert.equal(f.links?.length, 2) + assert.equal(f.links?.[0].rel, 'self') + + const e = f.entries[0] + assert.equal(e.id, 'urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a') + assert.deepEqual(e.title, { type: 'text', value: 'Atom-Powered Robots Run Amok' }) + assert.equal(e.updated, '2003-12-13T18:30:02Z') + assert.equal(e.published, '2003-12-13T08:29:29-04:00') + assert.deepEqual(e.summary, { type: 'text', value: 'Some text.' }) + assert.equal(e.content?.type, 'html') + assert.equal(e.content?.value, '

hi

') + assert.equal(e.categories?.[0].term, 'robots') + assert.equal(e.categories?.[0].label, 'Robots') + + const enclosure = e.links?.find((l) => l.rel === 'enclosure') + assert.equal(enclosure?.href, 'http://example.org/audio.mp3') + assert.equal(enclosure?.type, 'audio/mpeg') + assert.equal(enclosure?.length, 1337) + }) + + test('atom 0.3 maps tagline -> subtitle and modified -> updated', () => { + const f = parseFeed(ATOM_03) as AtomFeed + assert.equal(f.format, 'atom') + assert.equal(f.version, '0.3') + assert.deepEqual(f.subtitle, { type: 'text', value: 'An older feed' }) + assert.equal(f.updated, '2003-12-13T18:30:02Z') + const e = f.entries[0] + assert.equal(e.published, '2003-12-13T08:29:29-04:00') + assert.equal(e.updated, '2003-12-13T18:30:02Z') + }) + + test('rss 2.0 converts to Atom shape', () => { + const f = parseFeed(RSS_20) as AtomFeed + assert.equal(f.format, 'atom') + assert.deepEqual(f.title, { type: 'text', value: 'RSS 2 Sample' }) + assert.deepEqual(f.subtitle, { type: 'text', value: 'RSS 2.0 description' }) + assert.equal(f.id, 'http://example.com/') + // updated falls back from lastBuildDate + assert.equal(f.updated, 'Wed, 13 Dec 2003 19:30:02 GMT') + assert.equal(f.generator?.value, 'my generator') + assert.equal(f.logo, 'http://example.com/logo.png') + assert.equal(f.authors?.[0].email, 'editor@example.com') + assert.equal(f.authors?.[0].name, 'Edna Editor') + assert.equal(f.categories?.[0].term, 'News') + assert.equal(f.categories?.[0].scheme, 'cats') + + const e0 = f.entries[0] + assert.deepEqual(e0.title, { type: 'text', value: 'RSS Item 1' }) + assert.deepEqual(e0.summary, { type: 'html', value: 'Item one body' }) + assert.equal(e0.id, 'item-1-guid') // guid wins + assert.equal(e0.updated, 'Wed, 13 Dec 2003 18:30:02 GMT') + assert.equal(e0.published, 'Wed, 13 Dec 2003 18:30:02 GMT') + assert.equal(e0.authors?.[0].email, 'j@example.com') + assert.equal(e0.authors?.[0].name, 'Jane Doe') + assert.equal(e0.categories?.length, 2) + + const altLink = e0.links?.find((l) => l.rel === 'alternate') + assert.equal(altLink?.href, 'http://example.com/1') + const encLink = e0.links?.find((l) => l.rel === 'enclosure') + assert.equal(encLink?.href, 'http://example.com/1.mp3') + assert.equal(encLink?.length, 12345) + assert.equal(encLink?.type, 'audio/mpeg') + const reply = e0.links?.find((l) => l.rel === 'replies') + assert.equal(reply?.href, 'http://example.com/1#comments') + + // entry without guid falls back to link as id + const e1 = f.entries[1] + assert.equal(e1.id, 'http://example.com/2') + }) + + test('rss 0.92 / 0.91 convert to Atom', () => { + const f91 = parseFeed(RSS_091) as AtomFeed + assert.equal(f91.format, 'atom') + assert.deepEqual(f91.title, { type: 'text', value: 'RSS 0.91' }) + assert.equal(f91.entries.length, 1) + + const f92 = parseFeed(RSS_092) as AtomFeed + assert.equal(f92.format, 'atom') + assert.deepEqual(f92.title, { type: 'text', value: 'RSS 0.92' }) + assert.equal(f92.entries[0].links?.[0].rel, 'enclosure') + }) + + test('rss 1.0 (rdf) converts to Atom', () => { + const f = parseFeed(RSS_10) as AtomFeed + assert.equal(f.format, 'atom') + assert.deepEqual(f.title, { type: 'text', value: 'RSS 1.0 Example' }) + assert.deepEqual(f.subtitle, { type: 'text', value: 'An RDF-based feed' }) + assert.equal(f.id, 'http://example.org/index.rdf') + assert.equal(f.entries.length, 1) + const e = f.entries[0] + assert.deepEqual(e.title, { type: 'text', value: 'Item One' }) + assert.deepEqual(e.summary, { type: 'text', value: 'Item one' }) + assert.equal(e.id, 'http://example.org/items/1') + }) + + test('rss 0.90 (rdf) converts to Atom', () => { + const f = parseFeed(RSS_090) as AtomFeed + assert.equal(f.format, 'atom') + assert.deepEqual(f.title, { type: 'text', value: 'RSS 0.90' }) + assert.equal(f.entries.length, 1) + assert.deepEqual(f.entries[0].title, { type: 'text', value: 'Item' }) + }) +}) + + +describe('feed - native output', () => { + test('rss 2.0 native shape', () => { + const f = parseFeed(RSS_20, { format: 'native' }) as Rss2Feed + assert.equal(f.format, 'rss') + assert.equal(f.version, '2.0') + assert.equal(f.title, 'RSS 2 Sample') + assert.equal(f.link, 'http://example.com/') + assert.equal(f.description, 'RSS 2.0 description') + assert.equal(f.language, 'en-us') + assert.equal(f.ttl, 60) + assert.equal(f.image?.url, 'http://example.com/logo.png') + assert.equal(f.image?.width, 96) + assert.deepEqual(f.skipHours, [0, 23]) + assert.deepEqual(f.skipDays, ['Sunday']) + assert.equal(f.items.length, 2) + const i0 = f.items[0] + assert.equal(i0.title, 'RSS Item 1') + assert.equal(i0.author, 'j@example.com (Jane Doe)') + assert.equal(i0.guid?.value, 'item-1-guid') + assert.equal(i0.guid?.isPermaLink, false) + assert.equal(i0.enclosure?.url, 'http://example.com/1.mp3') + assert.equal(i0.enclosure?.length, 12345) + assert.equal(i0.categories?.length, 2) + assert.equal(i0.categories?.[1].domain, 'd2') + assert.equal(i0.source?.url, 'http://example.com/source.xml') + assert.equal(i0.source?.value, 'Source name') + }) + + test('atom 1.0 native shape (already atom)', () => { + const f = parseFeed(ATOM_10, { format: 'native' }) as AtomFeed + assert.equal(f.format, 'atom') + assert.equal(f.version, '1.0') + assert.equal(f.entries.length, 1) + }) + + test('rss 1.0 native (rdf) shape', () => { + const f = parseFeed(RSS_10, { format: 'native' }) as Rss1Feed + assert.equal(f.format, 'rdf') + assert.equal(f.version, '1.0') + assert.equal(f.about, 'http://example.org/index.rdf') + assert.equal(f.title, 'RSS 1.0 Example') + assert.equal(f.items.length, 1) + assert.equal(f.items[0].about, 'http://example.org/items/1') + }) +}) + + +describe('feed - raw output', () => { + test('returns the underlying XmlElement tree', () => { + const root: any = parseFeed(ATOM_10, { format: 'raw' }) + assert.equal(root.localName, 'feed') + assert.equal(root.namespace, 'http://www.w3.org/2005/Atom') + assert.ok(Array.isArray(root.children)) + }) +}) + + +describe('feed - Plugin form', () => { + test('jsonic.feed(src) returns Atom by default', () => { + const j: any = Jsonic.make().use(Feed) + const f = j.feed(RSS_20) as AtomFeed + assert.equal(f.format, 'atom') + assert.equal(f.entries.length, 2) + }) + + test('jsonic.feed(src) honors plugin options', () => { + const j: any = Jsonic.make().use(Feed, { format: 'native' }) + const f = j.feed(RSS_20) as Rss2Feed + assert.equal(f.format, 'rss') + assert.equal(f.version, '2.0') + }) +}) + + +describe('feed - errors', () => { + test('unrecognized root element throws', () => { + assert.throws(() => parseFeed(''), /unrecognized root/) + }) + + test('non-XML input throws', () => { + assert.throws(() => parseFeed(''), /XML element|jsonic|unexpected/i) + }) +}) + + +describe('feed - xhtml content', () => { + test('xhtml content extracts inner div body', () => { + const src = ` + + <div xmlns="http://www.w3.org/1999/xhtml">Hi <em>there</em></div> +

body here

+
+
` + const f = parseFeed(src) as AtomFeed + const e = f.entries[0] + assert.equal(e.title?.type, 'xhtml') + assert.match(e.title?.value || '', /Hi there<\/em>/) + assert.equal(e.content?.type, 'xhtml') + assert.match(e.content?.value || '', /body here<\/b><\/p>/) + }) +}) diff --git a/test/feedparser-wellformed/LICENSE b/test/feedparser-wellformed/LICENSE new file mode 100644 index 0000000..bbcdec6 --- /dev/null +++ b/test/feedparser-wellformed/LICENSE @@ -0,0 +1,65 @@ +feedparser and its unit tests are released under the following license: + +----- begin license block ----- + +Copyright (C) 2010-2025 Kurt McKee +Copyright (C) 2002-2008 Mark Pilgrim +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +----- end license block ----- + + + + + +The feedparser documentation (everything in the docs/ directory) is +released under the following license: + +----- begin license block ----- + +Copyright (C) 2010-2025 Kurt McKee +Copyright (C) 2004-2008 Mark Pilgrim. All rights reserved. + +Redistribution and use in source (Sphinx ReST) and "compiled" forms (HTML, PDF, +PostScript, RTF and so forth) with or without modification, are permitted +provided that the following conditions are met: + +* Redistributions of source code (Sphinx ReST) must retain the above copyright + notice, this list of conditions and the following disclaimer. +* Redistributions in compiled form (converted to HTML, PDF, PostScript, RTF and + other formats) must reproduce the above copyright notice, this list of + conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + +THIS DOCUMENTATION IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 'AS IS' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS DOCUMENTATION, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/test/feedparser-wellformed/atom/atom_namespace_1.xml b/test/feedparser-wellformed/atom/atom_namespace_1.xml new file mode 100644 index 0000000..da19b1a --- /dev/null +++ b/test/feedparser-wellformed/atom/atom_namespace_1.xml @@ -0,0 +1,7 @@ + + + Example Atom + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom/entry_author_email.xml b/test/feedparser-wellformed/atom/entry_author_email.xml new file mode 100644 index 0000000..b5ae46f --- /dev/null +++ b/test/feedparser-wellformed/atom/entry_author_email.xml @@ -0,0 +1,13 @@ + + + + + Example author + me@example.com + http://example.com/ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom/entry_author_name.xml b/test/feedparser-wellformed/atom/entry_author_name.xml new file mode 100644 index 0000000..52be7d7 --- /dev/null +++ b/test/feedparser-wellformed/atom/entry_author_name.xml @@ -0,0 +1,13 @@ + + + + + Example author + me@example.com + http://example.com/ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom/entry_content_value.xml b/test/feedparser-wellformed/atom/entry_content_value.xml new file mode 100644 index 0000000..8f56ef9 --- /dev/null +++ b/test/feedparser-wellformed/atom/entry_content_value.xml @@ -0,0 +1,9 @@ + + + + Example Atom + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom/entry_id.xml b/test/feedparser-wellformed/atom/entry_id.xml new file mode 100644 index 0000000..5fdf2f0 --- /dev/null +++ b/test/feedparser-wellformed/atom/entry_id.xml @@ -0,0 +1,9 @@ + + + + http://example.com/ + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom/entry_issued.xml b/test/feedparser-wellformed/atom/entry_issued.xml new file mode 100644 index 0000000..5a3d6f2 --- /dev/null +++ b/test/feedparser-wellformed/atom/entry_issued.xml @@ -0,0 +1,9 @@ + + + +Thu, 01 Jan 2004 19:48:21 GMT + + diff --git a/test/feedparser-wellformed/atom/entry_modified.xml b/test/feedparser-wellformed/atom/entry_modified.xml new file mode 100644 index 0000000..a768fcc --- /dev/null +++ b/test/feedparser-wellformed/atom/entry_modified.xml @@ -0,0 +1,9 @@ + + + +Thu, 01 Jan 2004 19:48:21 GMT + + diff --git a/test/feedparser-wellformed/atom/entry_title.xml b/test/feedparser-wellformed/atom/entry_title.xml new file mode 100644 index 0000000..330afcf --- /dev/null +++ b/test/feedparser-wellformed/atom/entry_title.xml @@ -0,0 +1,9 @@ + + + + Example Atom + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/atom10_namespace.xml b/test/feedparser-wellformed/atom10/atom10_namespace.xml new file mode 100644 index 0000000..8c4601e --- /dev/null +++ b/test/feedparser-wellformed/atom10/atom10_namespace.xml @@ -0,0 +1,7 @@ + + + Example Atom + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/atom10_version.xml b/test/feedparser-wellformed/atom10/atom10_version.xml new file mode 100644 index 0000000..cfa2fca --- /dev/null +++ b/test/feedparser-wellformed/atom10/atom10_version.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_author_email.xml b/test/feedparser-wellformed/atom10/entry_author_email.xml new file mode 100644 index 0000000..842e6bf --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_author_email.xml @@ -0,0 +1,13 @@ + + + + + Example author + me@example.com + http://example.com/ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_author_name.xml b/test/feedparser-wellformed/atom10/entry_author_name.xml new file mode 100644 index 0000000..5c6f826 --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_author_name.xml @@ -0,0 +1,13 @@ + + + + + Example author + me@example.com + http://example.com/ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_author_uri.xml b/test/feedparser-wellformed/atom10/entry_author_uri.xml new file mode 100644 index 0000000..d124364 --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_author_uri.xml @@ -0,0 +1,13 @@ + + + + + Example author + me@example.com + http://example.com/ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_content_type.xml b/test/feedparser-wellformed/atom10/entry_content_type.xml new file mode 100644 index 0000000..3a77455 --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_content_type.xml @@ -0,0 +1,9 @@ + + + + Example Atom + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_content_value.xml b/test/feedparser-wellformed/atom10/entry_content_value.xml new file mode 100644 index 0000000..c13dfc2 --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_content_value.xml @@ -0,0 +1,9 @@ + + + + Example Atom + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_id.xml b/test/feedparser-wellformed/atom10/entry_id.xml new file mode 100644 index 0000000..1319611 --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_id.xml @@ -0,0 +1,9 @@ + + + + http://example.com/ + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_link_href.xml b/test/feedparser-wellformed/atom10/entry_link_href.xml new file mode 100644 index 0000000..1b3f2bc --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_link_href.xml @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_summary.xml b/test/feedparser-wellformed/atom10/entry_summary.xml new file mode 100644 index 0000000..6b1b6ce --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_summary.xml @@ -0,0 +1,9 @@ + + + + Example Atom + + \ No newline at end of file diff --git a/test/feedparser-wellformed/atom10/entry_title.xml b/test/feedparser-wellformed/atom10/entry_title.xml new file mode 100644 index 0000000..0dd858a --- /dev/null +++ b/test/feedparser-wellformed/atom10/entry_title.xml @@ -0,0 +1,9 @@ + + + + Example Atom + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rdf_channel_description.xml b/test/feedparser-wellformed/rdf/rdf_channel_description.xml new file mode 100644 index 0000000..ade239f --- /dev/null +++ b/test/feedparser-wellformed/rdf/rdf_channel_description.xml @@ -0,0 +1,9 @@ + + + + Example description + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rdf_channel_link.xml b/test/feedparser-wellformed/rdf/rdf_channel_link.xml new file mode 100644 index 0000000..272710e --- /dev/null +++ b/test/feedparser-wellformed/rdf/rdf_channel_link.xml @@ -0,0 +1,9 @@ + + + + http://example.com/ + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rdf_channel_title.xml b/test/feedparser-wellformed/rdf/rdf_channel_title.xml new file mode 100644 index 0000000..1b06859 --- /dev/null +++ b/test/feedparser-wellformed/rdf/rdf_channel_title.xml @@ -0,0 +1,9 @@ + + + + Example feed + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rdf_item_description.xml b/test/feedparser-wellformed/rdf/rdf_item_description.xml new file mode 100644 index 0000000..915a15c --- /dev/null +++ b/test/feedparser-wellformed/rdf/rdf_item_description.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + Example description + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rdf_item_link.xml b/test/feedparser-wellformed/rdf/rdf_item_link.xml new file mode 100644 index 0000000..ca65567 --- /dev/null +++ b/test/feedparser-wellformed/rdf/rdf_item_link.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + http://example.com/1 + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rdf_item_rdf_about.xml b/test/feedparser-wellformed/rdf/rdf_item_rdf_about.xml new file mode 100644 index 0000000..9f37310 --- /dev/null +++ b/test/feedparser-wellformed/rdf/rdf_item_rdf_about.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rdf_item_title.xml b/test/feedparser-wellformed/rdf/rdf_item_title.xml new file mode 100644 index 0000000..4d7c8c7 --- /dev/null +++ b/test/feedparser-wellformed/rdf/rdf_item_title.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + Example title + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rss090_channel_title.xml b/test/feedparser-wellformed/rdf/rss090_channel_title.xml new file mode 100644 index 0000000..6e60d94 --- /dev/null +++ b/test/feedparser-wellformed/rdf/rss090_channel_title.xml @@ -0,0 +1,12 @@ + + + +Example title + + +Item title + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rss090_item_title.xml b/test/feedparser-wellformed/rdf/rss090_item_title.xml new file mode 100644 index 0000000..201026b --- /dev/null +++ b/test/feedparser-wellformed/rdf/rss090_item_title.xml @@ -0,0 +1,12 @@ + + + +Example title + + +Item title + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rdf/rss_version_10.xml b/test/feedparser-wellformed/rdf/rss_version_10.xml new file mode 100644 index 0000000..5f8f7ae --- /dev/null +++ b/test/feedparser-wellformed/rdf/rss_version_10.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/channel_copyright.xml b/test/feedparser-wellformed/rss/channel_copyright.xml new file mode 100644 index 0000000..db059a4 --- /dev/null +++ b/test/feedparser-wellformed/rss/channel_copyright.xml @@ -0,0 +1,9 @@ + + + +Example copyright + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/channel_description.xml b/test/feedparser-wellformed/rss/channel_description.xml new file mode 100644 index 0000000..4d604a6 --- /dev/null +++ b/test/feedparser-wellformed/rss/channel_description.xml @@ -0,0 +1,9 @@ + + + +Example description + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/channel_generator.xml b/test/feedparser-wellformed/rss/channel_generator.xml new file mode 100644 index 0000000..cb77440 --- /dev/null +++ b/test/feedparser-wellformed/rss/channel_generator.xml @@ -0,0 +1,9 @@ + + + +Example generator + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/channel_image_url.xml b/test/feedparser-wellformed/rss/channel_image_url.xml new file mode 100644 index 0000000..763cf39 --- /dev/null +++ b/test/feedparser-wellformed/rss/channel_image_url.xml @@ -0,0 +1,16 @@ + + + + +Sample image +http://example.org/url +http://example.org/link +80 +15 +Available in Netscape RSS 0.91 + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/channel_link.xml b/test/feedparser-wellformed/rss/channel_link.xml new file mode 100644 index 0000000..5ec81fb --- /dev/null +++ b/test/feedparser-wellformed/rss/channel_link.xml @@ -0,0 +1,9 @@ + + + +http://example.com/ + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/channel_pubDate.xml b/test/feedparser-wellformed/rss/channel_pubDate.xml new file mode 100644 index 0000000..bfdad70 --- /dev/null +++ b/test/feedparser-wellformed/rss/channel_pubDate.xml @@ -0,0 +1,9 @@ + + + +Thu, 01 Jan 2004 19:48:21 GMT + + diff --git a/test/feedparser-wellformed/rss/channel_title.xml b/test/feedparser-wellformed/rss/channel_title.xml new file mode 100644 index 0000000..b2b07fa --- /dev/null +++ b/test/feedparser-wellformed/rss/channel_title.xml @@ -0,0 +1,9 @@ + + + +Example feed + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/item_author.xml b/test/feedparser-wellformed/rss/item_author.xml new file mode 100644 index 0000000..e5567b1 --- /dev/null +++ b/test/feedparser-wellformed/rss/item_author.xml @@ -0,0 +1,11 @@ + + + + +Example editor + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/item_category.xml b/test/feedparser-wellformed/rss/item_category.xml new file mode 100644 index 0000000..d251d4d --- /dev/null +++ b/test/feedparser-wellformed/rss/item_category.xml @@ -0,0 +1,11 @@ + + + + +Example category + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/item_description.xml b/test/feedparser-wellformed/rss/item_description.xml new file mode 100644 index 0000000..3072cc3 --- /dev/null +++ b/test/feedparser-wellformed/rss/item_description.xml @@ -0,0 +1,11 @@ + + + + +Example description + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/item_enclosure_url.xml b/test/feedparser-wellformed/rss/item_enclosure_url.xml new file mode 100644 index 0000000..b800c79 --- /dev/null +++ b/test/feedparser-wellformed/rss/item_enclosure_url.xml @@ -0,0 +1,12 @@ + + + + + +http://example.com/ + + + diff --git a/test/feedparser-wellformed/rss/item_guid.xml b/test/feedparser-wellformed/rss/item_guid.xml new file mode 100644 index 0000000..8f7e26c --- /dev/null +++ b/test/feedparser-wellformed/rss/item_guid.xml @@ -0,0 +1,11 @@ + + + + +http://guid.example.com/ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/item_link.xml b/test/feedparser-wellformed/rss/item_link.xml new file mode 100644 index 0000000..e6151a7 --- /dev/null +++ b/test/feedparser-wellformed/rss/item_link.xml @@ -0,0 +1,11 @@ + + + + +http://example.com/ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/item_pubDate.xml b/test/feedparser-wellformed/rss/item_pubDate.xml new file mode 100644 index 0000000..b863fd8 --- /dev/null +++ b/test/feedparser-wellformed/rss/item_pubDate.xml @@ -0,0 +1,11 @@ + + + + +Thu, 01 Jan 2004 19:48:21 GMT + + + diff --git a/test/feedparser-wellformed/rss/item_title.xml b/test/feedparser-wellformed/rss/item_title.xml new file mode 100644 index 0000000..be3da8a --- /dev/null +++ b/test/feedparser-wellformed/rss/item_title.xml @@ -0,0 +1,11 @@ + + + + +Item 1 title + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/rss_version_091_netscape.xml b/test/feedparser-wellformed/rss/rss_version_091_netscape.xml new file mode 100644 index 0000000..9bf937d --- /dev/null +++ b/test/feedparser-wellformed/rss/rss_version_091_netscape.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/rss_version_091_userland.xml b/test/feedparser-wellformed/rss/rss_version_091_userland.xml new file mode 100644 index 0000000..c073c9f --- /dev/null +++ b/test/feedparser-wellformed/rss/rss_version_091_userland.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/rss_version_092.xml b/test/feedparser-wellformed/rss/rss_version_092.xml new file mode 100644 index 0000000..aebd4b6 --- /dev/null +++ b/test/feedparser-wellformed/rss/rss_version_092.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/test/feedparser-wellformed/rss/rss_version_20.xml b/test/feedparser-wellformed/rss/rss_version_20.xml new file mode 100644 index 0000000..1fd047b --- /dev/null +++ b/test/feedparser-wellformed/rss/rss_version_20.xml @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/test/feedparser.test.ts b/test/feedparser.test.ts new file mode 100644 index 0000000..3ae9056 --- /dev/null +++ b/test/feedparser.test.ts @@ -0,0 +1,288 @@ +/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */ + +// Uses well-formed feed samples vendored from kurtmckee/feedparser +// (Copyright (C) 2010-2025 Kurt McKee, 2002-2008 Mark Pilgrim, BSD 2-Clause) +// at test/feedparser-wellformed/. The upstream LICENSE is preserved alongside; +// see THIRD_PARTY_NOTICES.md. + +import { test, describe } from 'node:test' +import assert from 'node:assert' +import { readdirSync, readFileSync, existsSync } from 'node:fs' +import { join } from 'node:path' + +import { parseFeed, detect } from '../dist/feed.js' +import type { + AtomFeed, + FeedDialect, + FeedVersion, +} from '../dist/feed.js' +import { Jsonic } from 'jsonic' +import { Xml } from '@jsonic/xml' + +const SUITE_DIR = join(__dirname, '..', 'test', 'feedparser-wellformed') + +// Read all .xml files in a subdirectory. +function loadDir(name: string): { file: string; src: string }[] { + const dir = join(SUITE_DIR, name) + if (!existsSync(dir)) return [] + return readdirSync(dir) + .filter((f) => f.endsWith('.xml')) + .sort() + .map((f) => ({ file: f, src: readFileSync(join(dir, f), 'utf8') })) +} + +const ATOM10 = loadDir('atom10') +const ATOM = loadDir('atom') +const RSS = loadDir('rss') +const RDF = loadDir('rdf') + + +// Each upstream test file has a top-of-file +// preamble. We don't try to interpret arbitrary feedparser expectations here +// (their accessor model and ours differ substantially); we use the Description +// line as a label and assert on dialect+version detection plus a small set of +// hand-translated value checks below. +function description(src: string): string { + const m = src.match(/Description:\s*(.+)/) + return m ? m[1].trim() : '?' +} + + +describe('feedparser-wellformed - dialect / version detection', () => { + if (!existsSync(SUITE_DIR)) { + test('suite unavailable', () => { + console.warn(`feedparser-wellformed not vendored at ${SUITE_DIR}; skipping.`) + }) + return + } + + function check( + files: { file: string; src: string }[], + expect: { dialect: FeedDialect; version: FeedVersion | FeedVersion[] }, + label: string, + ) { + test(label, () => { + const fails: string[] = [] + for (const { file, src } of files) { + const root = Jsonic.make().use(Xml)(src) + const got = detect(root) + const versionsOk = Array.isArray(expect.version) + ? expect.version.includes(got.version) + : got.version === expect.version + if (got.dialect !== expect.dialect || !versionsOk) { + fails.push(` ${file}: got ${got.dialect}/${got.version}`) + } + } + assert.deepEqual(fails, [], `${label} mismatches:\n${fails.join('\n')}`) + }) + } + + check(ATOM10, { dialect: 'atom', version: 'atom10' }, 'atom10/* -> atom/atom10') + check(ATOM, { dialect: 'atom', version: 'atom03' }, 'atom/* -> atom/atom03') + check( + RSS, + { dialect: 'rss', version: ['rss20', 'rss092', 'rss091u', 'rss091n'] }, + 'rss/* -> rss/(any 0.91/0.92/2.0)', + ) + check( + RDF, + { dialect: 'rdf', version: ['rss10', 'rss090'] }, + 'rdf/* -> rdf/(rss10 or rss090)', + ) +}) + + +describe('feedparser-wellformed - parse without error', () => { + if (!existsSync(SUITE_DIR)) return + + test('all atom10 files parse to a feed', () => { + const fails: { file: string; err: string }[] = [] + for (const { file, src } of ATOM10) { + try { + const f = parseFeed(src) as AtomFeed + if (f.format !== 'atom') { + fails.push({ file, err: `format=${f.format}` }) + } + } catch (e: any) { + fails.push({ file, err: e?.message || String(e) }) + } + } + assert.deepEqual(fails, [], `atom10 failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) + }) + + test('all atom (0.3) files parse to a feed', () => { + const fails: { file: string; err: string }[] = [] + for (const { file, src } of ATOM) { + try { + const f = parseFeed(src) as AtomFeed + if (f.format !== 'atom') { + fails.push({ file, err: `format=${f.format}` }) + } + } catch (e: any) { + fails.push({ file, err: e?.message || String(e) }) + } + } + assert.deepEqual(fails, [], `atom failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) + }) + + test('all rss files parse to a feed', () => { + const fails: { file: string; err: string }[] = [] + for (const { file, src } of RSS) { + try { + const f = parseFeed(src) as AtomFeed + if (f.format !== 'atom') { + fails.push({ file, err: `format=${f.format}` }) + } + } catch (e: any) { + fails.push({ file, err: e?.message || String(e) }) + } + } + assert.deepEqual(fails, [], `rss failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) + }) + + test('all rdf files parse to a feed', () => { + const fails: { file: string; err: string }[] = [] + for (const { file, src } of RDF) { + try { + const f = parseFeed(src) as AtomFeed + if (f.format !== 'atom') { + fails.push({ file, err: `format=${f.format}` }) + } + } catch (e: any) { + fails.push({ file, err: e?.message || String(e) }) + } + } + assert.deepEqual(fails, [], `rdf failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) + }) +}) + + +// Targeted value checks against vendored corpus files. We match feedparser's +// own Description/Expect comments (translated to our shape). +describe('feedparser-wellformed - targeted value checks', () => { + if (!existsSync(SUITE_DIR)) return + + function findFile(set: { file: string; src: string }[], name: string) { + return set.find((x) => x.file === name)?.src + } + + test('atom10/entry_title -> entries[0].title.value == "Example Atom"', () => { + const src = findFile(ATOM10, 'entry_title.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.entries[0].title?.value, 'Example Atom') + }) + + test('atom10/entry_author_email -> entries[0].authors[0].email', () => { + const src = findFile(ATOM10, 'entry_author_email.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.entries[0].authors?.[0].email, 'me@example.com') + }) + + test('atom10/entry_author_name -> entries[0].authors[0].name', () => { + const src = findFile(ATOM10, 'entry_author_name.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.entries[0].authors?.[0].name, 'Example author') + }) + + test('atom10/entry_id -> entries[0].id', () => { + const src = findFile(ATOM10, 'entry_id.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.ok(f.entries[0].id, 'id present') + }) + + test('atom10/entry_link_href -> entries[0].links[0].href', () => { + const src = findFile(ATOM10, 'entry_link_href.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.ok(f.entries[0].links?.[0].href, 'href present') + }) + + test('atom/entry_title -> entries[0].title.value', () => { + const src = findFile(ATOM, 'entry_title.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.ok(f.entries[0].title?.value, 'title present') + }) + + test('atom/entry_issued -> entries[0].published', () => { + const src = findFile(ATOM, 'entry_issued.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.ok(f.entries[0].published, 'published present') + }) + + test('atom/entry_modified -> entries[0].updated', () => { + const src = findFile(ATOM, 'entry_modified.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.ok(f.entries[0].updated, 'updated present') + }) + + test('rss/channel_title -> title.value == "Example feed"', () => { + const src = findFile(RSS, 'channel_title.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.title?.value, 'Example feed') + }) + + test('rss/item_title -> entries[0].title.value', () => { + const src = findFile(RSS, 'item_title.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.entries[0].title?.value, 'Item 1 title') + }) + + test('rss/item_link -> entries[0].links[0].href', () => { + const src = findFile(RSS, 'item_link.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.ok(f.entries[0].links?.[0].href, 'href present') + }) + + test('rss/item_guid -> entries[0].id', () => { + const src = findFile(RSS, 'item_guid.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.ok(f.entries[0].id, 'id present') + }) + + test('rss/item_enclosure_url -> entries[0].links has rel=enclosure', () => { + const src = findFile(RSS, 'item_enclosure_url.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + const enc = f.entries[0].links?.find((l) => l.rel === 'enclosure') + assert.ok(enc, 'enclosure link present') + }) + + test('rdf/rdf_channel_title -> title.value == "Example feed"', () => { + const src = findFile(RDF, 'rdf_channel_title.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.title?.value, 'Example feed') + }) + + test('rdf/rdf_item_title -> entries[0].title.value == "Example title"', () => { + const src = findFile(RDF, 'rdf_item_title.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.entries[0].title?.value, 'Example title') + }) + + test('rdf/rss090_channel_title -> title.value == "Example title"', () => { + const src = findFile(RDF, 'rss090_channel_title.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.title?.value, 'Example title') + }) + + test('rdf/rdf_item_rdf_about -> entries[0].id is the rdf:about URI', () => { + const src = findFile(RDF, 'rdf_item_rdf_about.xml') + assert.ok(src, 'fixture present') + const f = parseFeed(src!) as AtomFeed + assert.equal(f.entries[0].id, 'http://example.org/1') + }) +}) diff --git a/test/jsonc.test.ts b/test/jsonc.test.ts deleted file mode 100644 index b99ce58..0000000 --- a/test/jsonc.test.ts +++ /dev/null @@ -1,265 +0,0 @@ -/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */ - -// Parse-level test cases in this file were ported from -// microsoft/node-jsonc-parser (src/test/json.test.ts), Copyright (c) -// Microsoft Corporation, MIT License. See THIRD_PARTY_NOTICES.md. - -import { test, describe } from 'node:test' -import assert from 'node:assert' - -import { Jsonic } from 'jsonic' -import { Jsonc } from '../dist/jsonc.js' - - -const j = Jsonic.make().use(Jsonc) - - -describe('jsonc', () => { - - test('happy', () => { - assert.deepEqual(j('{"a":1}'), { a: 1 }) - }) - - - test('comments', () => { - assert.deepEqual(j('// this is a comment'), undefined) - assert.deepEqual(j('// this is a comment\n'), undefined) - assert.deepEqual(j('/* this is a comment*/'), undefined) - assert.deepEqual(j('/* this is a \r\ncomment*/'), undefined) - assert.deepEqual(j('/* this is a \ncomment*/'), undefined) - assert.throws(() => j('/* this is a'), /unterminated_comment/) - assert.throws(() => j('/* this is a \ncomment'), /unterminated_comment/) - assert.throws(() => j('/ ttt'), /unexpected/) - }) - - - test('strings', () => { - assert.deepEqual(j('"test"'), 'test') - assert.deepEqual(j('"\\""'), '"') - assert.deepEqual(j('"\\/"'), '/') - assert.deepEqual(j('"\\b"'), '\b') - assert.deepEqual(j('"\\f"'), '\f') - assert.deepEqual(j('"\\n"'), '\n') - assert.deepEqual(j('"\\r"'), '\r') - assert.deepEqual(j('"\\t"'), '\t') - assert.deepEqual(j('"\u88ff"'), '\u88ff') - assert.deepEqual(j('"\u200B\u2028"'), '\u200B\u2028') - assert.throws(() => j('"\\v"'), /unexpected/) - assert.throws(() => j('"test'), /unterminated_string/) - assert.throws(() => j('"test\n"'), /unprintable/) - assert.throws(() => j('"\t"'), /unprintable/) - assert.throws(() => j('"\t "'), /unprintable/) - assert.throws(() => j('"\0 "'), /unprintable/) - }) - - - test('numbers', () => { - assert.deepEqual(j('0'), 0) - assert.deepEqual(j('0.1'), 0.1) - assert.deepEqual(j('-0.1'), -0.1) - assert.deepEqual(j('-1'), -1) - assert.deepEqual(j('1'), 1) - assert.deepEqual(j('123456789'), 123456789) - assert.deepEqual(j('10'), 10) - assert.deepEqual(j('90'), 90) - assert.deepEqual(j('90E+123'), 90E+123) - assert.deepEqual(j('90e+123'), 90e+123) - assert.deepEqual(j('90e-123'), 90e-123) - assert.deepEqual(j('90E-123'), 90E-123) - assert.deepEqual(j('90E123'), 90E123) - assert.deepEqual(j('90e123'), 90e123) - assert.deepEqual(j('01'), 1) - assert.deepEqual(j('-01'), -1) - assert.throws(() => j('-'), /unexpected/) - assert.throws(() => j('.0'), /unexpected/) - }) - - - test('keywords', () => { - assert.deepEqual(j('true'), true) - assert.deepEqual(j('false'), false) - assert.deepEqual(j('null'), null) - - assert.throws(() => j('nulllll'), /unexpected/) - assert.throws(() => j('True'), /unexpected/) - assert.throws(() => j('foo-bar'), /unexpected/) - assert.throws(() => j('foo bar'), /unexpected/) - - assert.deepEqual(j('false//hello'), false) - }) - - - test('trivia', () => { - assert.deepEqual(j(' '), undefined) - assert.deepEqual(j(' \t '), undefined) - assert.deepEqual(j(' \t \n \t '), undefined) - assert.deepEqual(j('\r\n'), undefined) - assert.deepEqual(j('\r'), undefined) - assert.deepEqual(j('\n'), undefined) - assert.deepEqual(j('\n\r'), undefined) - assert.deepEqual(j('\n \n'), undefined) - }) - - - test('literals', () => { - assert.deepEqual(j('true'), true) - assert.deepEqual(j('false'), false) - assert.deepEqual(j('null'), null) - assert.deepEqual(j('"foo"'), 'foo') - assert.deepEqual(j('"\\"-\\\\-\\/-\\b-\\f-\\n-\\r-\\t"'), '"-\\-/-\b-\f-\n-\r-\t') - assert.deepEqual(j('"\\u00DC"'), '\u00DC') - assert.deepEqual(j('9'), 9) - assert.deepEqual(j('-9'), -9) - assert.deepEqual(j('0.129'), 0.129) - assert.deepEqual(j('23e3'), 23e3) - assert.deepEqual(j('1.2E+3'), 1.2E+3) - assert.deepEqual(j('1.2E-3'), 1.2E-3) - assert.deepEqual(j('1.2E-3 // comment'), 1.2E-3) - }) - - - test('objects', () => { - assert.deepEqual(j('{}'), {}) - assert.deepEqual(j('{ "foo": true }'), { foo: true }) - assert.deepEqual(j('{ "bar": 8, "xoo": "foo" }'), { bar: 8, xoo: 'foo' }) - assert.deepEqual(j('{ "hello": [], "world": {} }'), { hello: [], world: {} }) - assert.deepEqual(j('{ "a": false, "b": true, "c": [ 7.4 ] }'), { a: false, b: true, c: [7.4] }) - assert.deepEqual(j('{ "lineComment": "//", "blockComment": ["/*", "*/"], "brackets": [ ["{", "}"], ["[", "]"], ["(", ")"] ] }'), - { lineComment: '//', blockComment: ['/*', '*/'], brackets: [['{', '}'], ['[', ']'], ['(', ')']] }) - assert.deepEqual(j('{ "hello": [], "world": {} }'), { hello: [], world: {} }) - assert.deepEqual(j('{ "hello": { "again": { "inside": 5 }, "world": 1 }}'), { hello: { again: { inside: 5 }, world: 1 } }) - assert.deepEqual(j('{ "foo": /*hello*/true }'), { foo: true }) - assert.deepEqual(j('{ "": true }'), { '': true }) - }) - - - test('arrays', () => { - assert.deepEqual(j('[]'), []) - assert.deepEqual(j('[ [], [ [] ]]'), [[], [[]]]) - assert.deepEqual(j('[ 1, 2, 3 ]'), [1, 2, 3]) - assert.deepEqual(j('[ { "a": null } ]'), [{ a: null }]) - }) - - - test('objects with errors', () => { - assert.throws(() => j('{,}')) - assert.throws(() => j('{ "foo": true, }')) - assert.throws(() => j('{ "bar": 8 "xoo": "foo" }')) - assert.throws(() => j('{ ,"bar": 8 }')) - assert.throws(() => j('{ ,"bar": 8, "foo" }')) - assert.throws(() => j('{ "bar": 8, "foo": }')) - assert.throws(() => j('{ 8, "foo": 9 }')) - }) - - - test('array with errors', () => { - assert.throws(() => j('[,]')) - assert.throws(() => j('[ 1 2, 3 ]')) - assert.throws(() => j('[ ,1, 2, 3 ]')) - assert.throws(() => j('[ ,1, 2, 3, ]')) - }) - - - test('errors', () => { - assert.throws(() => j('1,1')) - assert.throws(() => j('')) - }) - - - test('disallow comments', () => { - const nc = Jsonic.make().use(Jsonc, { disallowComments: true }) - - assert.deepEqual(nc('[ 1, 2, null, "foo" ]'), [1, 2, null, 'foo']) - assert.deepEqual(nc('{ "hello": [], "world": {} }'), { hello: [], world: {} }) - - assert.throws(() => nc('{ "foo": /*comment*/ true }')) - }) - - - test('trailing comma', () => { - const jc = Jsonic.make().use(Jsonc, { allowTrailingComma: true }) - - assert.deepEqual(jc('{ "hello": [], }'), { hello: [] }) - assert.deepEqual(jc('{ "hello": [] }'), { hello: [] }) - assert.deepEqual(jc('{ "hello": [], "world": {}, }'), { hello: [], world: {} }) - assert.deepEqual(jc('{ "hello": [], "world": {} }'), { hello: [], world: {} }) - assert.deepEqual(jc('[ 1, 2, ]'), [1, 2]) - assert.deepEqual(jc('[ 1, 2 ]'), [1, 2]) - - assert.throws(() => j('{ "hello": [], }')) - assert.throws(() => j('{ "hello": [], "world": {}, }')) - assert.throws(() => j('[ 1, 2, ]')) - }) - - test('misc', () => { - - assert.deepEqual(j('{ "foo": "bar" }'), { "foo": "bar" }) - assert.deepEqual(j('{ "foo": {"bar": 1, "car": 2 } }'), { "foo": { "bar": 1, "car": 2 } }) - assert.deepEqual(j('{ "foo": {"bar": 1, "car": 8 }, "goo": {} }'), { "foo": { "bar": 1, "car": 8 }, "goo": {} }) - assert.throws(() => j('{ "dep": {"bar": 1, "car": ')) - assert.throws(() => j('{ "dep": {"bar": 1,, "car": ')) - assert.throws(() => j('{ "dep": {"bar": "na", "dar": "ma", "car": } }')) - - assert.deepEqual(j('["foo", null ]'), ["foo", null]) - assert.throws(() => j('["foo", null, ]')) - assert.throws(() => j('["foo", null,, ]')) - assert.throws(() => j('[["foo", null,, ],')) - - assert.deepEqual(j('true'), true) - assert.deepEqual(j('false'), false) - assert.deepEqual(j('null'), null) - assert.deepEqual(j('23'), 23) - assert.deepEqual(j('-1.93e-19'), -1.93e-19) - assert.deepEqual(j('"hello"'), "hello") - - assert.deepEqual(j('[]'), []) - assert.deepEqual(j('[ 1 ]'), [1]) - assert.deepEqual(j('[ 1, "x"]'), [1, "x"]) - assert.deepEqual(j('[[]]'), [[]]) - assert.deepEqual(j('{ }'), {}) - assert.deepEqual(j('{ "val": 1 }'), { "val": 1 }) - assert.deepEqual(j('{"id": "$", "v": [ null, null] }'), - { "id": "$", "v": [null, null] }) - - assert.throws(() => j('{ "id": { "foo": { } } , }')) - - assert.deepEqual(j('{ }'), {}) - assert.deepEqual(j('{ "foo": "bar" }'), { "foo": "bar" }) - assert.deepEqual(j('{ "foo": { "goo": 3 } }'), { "foo": { "goo": 3 } }) - assert.deepEqual(j('[]'), []) - assert.deepEqual(j('[ true, null, [] ]'), [true, null, []]) - assert.deepEqual(j('[\r\n0,\r\n1,\r\n2\r\n]'), [0, 1, 2]) - assert.deepEqual(j('/* g */ { "foo": //f\n"bar" }'), { foo: 'bar' }) - assert.deepEqual(j('/* g\r\n */ { "foo": //f\n"bar" }'), { foo: 'bar' }) - assert.deepEqual(j('/* g\n */ { "foo": //f\n"bar"\n}'), { foo: 'bar' }) - assert.throws(() => j('{"prop1":"foo","prop2":"foo2","prop3":{"prp1":{""}}}' )) - assert.deepEqual(j('{ "key1": { "key11": [ "val111", "val112" ] }, "key2": [ { "key21": false, "key22": 221 }, null, [{}] ] }'), - { "key1": { "key11": ["val111", "val112"] }, "key2": [{ "key21": false, "key22": 221 }, null, [{}]] }) - - }) - - - // Verify the grammar() setting {rule:{alt:{g:'jsonc'}}} tagged every - // alt installed by the jsonc plugin with 'jsonc'. - test('alt g jsonc tag', () => { - const jc: any = Jsonic.make().use(Jsonc, { allowTrailingComma: true }) - const rsm: any = jc.internal().parser.rsm - - const checks: { rule: string; side: 'open' | 'close' }[] = [ - { rule: 'val', side: 'open' }, - { rule: 'pair', side: 'close' }, - { rule: 'elem', side: 'close' }, - ] - - for (const { rule, side } of checks) { - const rs = rsm[rule] - assert.ok(rs, `rule ${rule} missing`) - const alts = rs.def[side] as any[] - const tagged = alts.filter((a) => { - const g = Array.isArray(a.g) ? a.g : String(a.g || '').split(/\s*,\s*/) - return g.includes('jsonc') - }) - assert.ok(tagged.length > 0, `rule ${rule}.${side} has no 'jsonc'-tagged alt`) - } - }) -}) diff --git a/test/jsontestsuite.test.ts b/test/jsontestsuite.test.ts deleted file mode 100644 index 6dd4a25..0000000 --- a/test/jsontestsuite.test.ts +++ /dev/null @@ -1,117 +0,0 @@ -/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */ - -// Uses the nst/JSONTestSuite corpus (Copyright (c) 2016 Nicolas Seriot, -// MIT License) vendored at test/JSONTestSuite/. The upstream LICENSE is -// kept in place; see also THIRD_PARTY_NOTICES.md. - -// Runs the nst/JSONTestSuite (RFC 8259) against the jsonc plugin in strict -// mode (disallowComments: true, no trailing commas). Each file in -// test_parsing/ is classified by prefix: -// y_* must parse successfully -// n_* must be rejected (known-lenient cases pinned in N_KNOWN_LENIENT) -// i_* implementation-defined (recorded only) -// -// Known-lenient n_* entries reflect intentional jsonic relaxations vs. strict -// RFC 8259 (e.g. leading zeros, unquoted keys). They are pinned so the set -// is caught if it grows or shrinks. - -import { test, describe } from 'node:test' -import assert from 'node:assert' -import { readdirSync, readFileSync, existsSync } from 'node:fs' -import { join } from 'node:path' - -import { Jsonic } from 'jsonic' -import { Jsonc } from '../dist/jsonc.js' - -const SUITE_DIR = join(__dirname, '..', 'test', 'JSONTestSuite', 'test_parsing') - -const j = Jsonic.make().use(Jsonc, { disallowComments: true }) - -const parse = (src: string) => j(src) - -const files = existsSync(SUITE_DIR) - ? readdirSync(SUITE_DIR).filter((f) => f.endsWith('.json')).sort() - : [] - -// Cases jsonic intentionally accepts that RFC 8259 requires rejecting. -const N_KNOWN_LENIENT = new Set([ - 'n_array_comma_after_close.json', - 'n_number_+1.json', - 'n_number_-01.json', - 'n_number_-2..json', - 'n_number_0.e1.json', - 'n_number_2.e+3.json', - 'n_number_2.e-3.json', - 'n_number_2.e3.json', - 'n_number_neg_int_starting_with_zero.json', - 'n_number_neg_real_without_int_part.json', - 'n_number_real_without_fractional_part.json', - 'n_number_with_leading_zero.json', - 'n_object_non_string_key.json', - 'n_object_non_string_key_but_huge_number_instead.json', - 'n_object_repeated_null_null.json', - 'n_object_single_quote.json', - 'n_single_space.json', - 'n_string_escape_x.json', - 'n_string_single_quote.json', - 'n_structure_object_with_trailing_garbage.json', -]) - -describe('JSONTestSuite (RFC 8259)', () => { - if (0 === files.length) { - test('suite unavailable', () => { - console.warn(`JSONTestSuite not found at ${SUITE_DIR} — skipping.`) - }) - return - } - - test('y_* accept', () => { - const fails: { file: string; err: string }[] = [] - for (const f of files.filter((x) => x.startsWith('y_'))) { - const src = readFileSync(join(SUITE_DIR, f), 'utf8') - try { - parse(src) - } catch (e: any) { - fails.push({ file: f, err: e?.code || e?.message || String(e) }) - } - } - assert.deepEqual(fails, [], `y_* files that failed to parse:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) - }) - - test('n_* reject', () => { - const unexpectedAccept: string[] = [] - const unexpectedReject: string[] = [] - for (const f of files.filter((x) => x.startsWith('n_'))) { - const src = readFileSync(join(SUITE_DIR, f), 'utf8') - let accepted = false - try { - parse(src) - accepted = true - } catch { - // expected - } - const isLenient = N_KNOWN_LENIENT.has(f) - if (accepted && !isLenient) unexpectedAccept.push(f) - if (!accepted && isLenient) unexpectedReject.push(f) - } - assert.deepEqual( - { unexpectedAccept, unexpectedReject }, - { unexpectedAccept: [], unexpectedReject: [] }, - 'n_* divergence from pinned allowlist', - ) - }) - - test('i_* implementation-defined', () => { - const results: { file: string; accepted: boolean }[] = [] - for (const f of files.filter((x) => x.startsWith('i_'))) { - const src = readFileSync(join(SUITE_DIR, f), 'utf8') - try { - parse(src) - results.push({ file: f, accepted: true }) - } catch { - results.push({ file: f, accepted: false }) - } - } - assert.ok(results.length > 0, 'expected at least one i_* file') - }) -}) From 54e12d27affee849586a0327185bc575d22c7c2f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 6 May 2026 12:02:58 +0000 Subject: [PATCH 2/4] Drop standalone helpers; route through normal jsonic call Remove parseFeed() and the j.feed() method. With the Feed plugin installed, calling the jsonic instance directly (j(src)) returns the converted feed result, matching the standard jsonic plugin pattern. Implementation: register a `bc` (before-close) action on the `xml` root rule. After @jsonic/xml's own @xml-bc copies the parsed XmlElement onto ctx.root().node, our hook replaces it with the converted feed (Atom by default, native, or raw per options.format). Tests and README updated to use the j(src) API throughout. --- README.md | 67 ++++++++++---------- src/feed.ts | 39 ++++-------- test/feed.test.ts | 71 +++++++++------------ test/feedparser.test.ts | 132 ++++++++++++++-------------------------- 4 files changed, 117 insertions(+), 192 deletions(-) diff --git a/README.md b/README.md index 9ab6c13..49e08bd 100644 --- a/README.md +++ b/README.md @@ -33,13 +33,16 @@ Install: npm install @jsonic/feed jsonic @jsonic/xml ``` -Parse a feed in any supported dialect — the result is an Atom-shaped -object regardless of input format: +Register the plugin and call the Jsonic instance as usual — the result +is an Atom-shaped object regardless of the input dialect: ```typescript -import { parseFeed } from '@jsonic/feed' +import { Jsonic } from 'jsonic' +import { Feed } from '@jsonic/feed' + +const j = Jsonic.make().use(Feed) -const atom = parseFeed(` +const atom = j(` My Blog @@ -61,26 +64,18 @@ const atom = parseFeed(` // atom.entries[0].links[0] === { href: 'https://example.com/1', rel: 'alternate' } ``` -Or wire it into a Jsonic instance via the plugin form, which adds a -`feed(src)` method: - -```typescript -import { Jsonic } from 'jsonic' -import { Feed } from '@jsonic/feed' - -const j = Jsonic.make().use(Feed) -const atom = j.feed(rssSource) -``` - ## How-to guides ### Keep the source dialect's structure (no Atom conversion) ```typescript -import { parseFeed, type Rss2Feed } from '@jsonic/feed' +import { Jsonic } from 'jsonic' +import { Feed, type Rss2Feed } from '@jsonic/feed' + +const j = Jsonic.make().use(Feed, { format: 'native' }) -const native = parseFeed(rssSource, { format: 'native' }) as Rss2Feed +const native = j(rssSource) as Rss2Feed // native.format === 'rss' // native.version === '2.0' // native.items[0].guid?.value === 'item-1-guid' @@ -97,9 +92,12 @@ The native return type is a discriminated union on `format`: ### Get the raw XML tree ```typescript -import { parseFeed } from '@jsonic/feed' +import { Jsonic } from 'jsonic' +import { Feed } from '@jsonic/feed' + +const j = Jsonic.make().use(Feed, { format: 'raw' }) -const tree = parseFeed(rssSource, { format: 'raw' }) +const tree = j(rssSource) // tree.localName === 'rss' // tree.children === [...] ``` @@ -111,34 +109,22 @@ processing, useful when you want to handle non-standard extensions. ```typescript import { Jsonic } from 'jsonic' -import { Xml } from '@jsonic/xml' -import { detect } from '@jsonic/feed' +import { Feed, detect } from '@jsonic/feed' -const root = Jsonic.make().use(Xml)(rssSource) +const j = Jsonic.make().use(Feed, { format: 'raw' }) +const root = j(rssSource) const { dialect, version } = detect(root) // e.g. { dialect: 'rss', version: 'rss20' } ``` -### Configure the plugin form - -The plugin's options are set once at `use()` time: - -```typescript -import { Jsonic } from 'jsonic' -import { Feed } from '@jsonic/feed' - -const j = Jsonic.make().use(Feed, { format: 'native' }) -const native = j.feed(rssSource) -``` - ## Reference ```typescript -function parseFeed(src: string, options?: FeedOptions): FeedResult -function detect(root: XmlElement): { dialect: FeedDialect; version: FeedVersion } const Feed: Plugin +function detect(root: XmlElement): { dialect: FeedDialect; version: FeedVersion } + type FeedOptions = { format?: 'atom' | 'native' | 'raw' // default: 'atom' } @@ -154,6 +140,15 @@ type FeedVersion = | 'unknown' ``` +Use the plugin via `Jsonic.make().use(Feed, options?)`. After +registration, invoke the jsonic instance as a function on a feed XML +source string; it returns the converted feed (or the raw `XmlElement` +tree, when `options.format === 'raw'`). + +| Option | Type | Default | Effect | +|----------|-------------------------------|----------|-------------------------------------------------------| +| `format` | `'atom' \| 'native' \| 'raw'` | `'atom'` | Output shape: normalised Atom, dialect-native, or raw XML tree | + Atom shape (the default output) follows RFC 4287 closely: ```typescript diff --git a/src/feed.ts b/src/feed.ts index dba6783..0a1f7c4 100644 --- a/src/feed.ts +++ b/src/feed.ts @@ -252,12 +252,6 @@ function isElement(node: unknown): node is XmlElement { ) } -function elementChildren(el: XmlElement): XmlElement[] { - const out: XmlElement[] = [] - for (const c of el.children) if (isElement(c)) out.push(c) - return out -} - function findChild( el: XmlElement | undefined, localName: string, @@ -915,18 +909,6 @@ function convert(root: XmlElement, opts: Required): FeedResult { return rss1ToAtom(native) } - -// --- Public functional entry point ---------------------------------------- - -function parseFeed(src: string, options?: FeedOptions): FeedResult { - const j = Jsonic.make().use(Xml) - const root = j(src) - if (!isElement(root)) { - throw new Error('feed: input did not parse to an XML element') - } - return convert(root, withDefaults(options)) -} - function withDefaults(o?: FeedOptions): Required { return { format: o?.format ?? 'atom' } } @@ -938,18 +920,21 @@ const Feed: Plugin = function Feed(jsonic, options) { jsonic.use(Xml) const opts = withDefaults(options as FeedOptions | undefined) - // Attach a `feed(src)` method that runs xml parse + feed convert. - ;(jsonic as any).feed = function (src: string): FeedResult { - const root = jsonic(src) - if (!isElement(root)) { - throw new Error('feed: input did not parse to an XML element') - } - return convert(root, opts) - } + // After @xml-bc copies the parsed XmlElement tree onto ctx.root().node, + // transform it into the feed shape selected by `opts.format`. Appending + // a second bc action runs it after the XML plugin's own. + jsonic.rule('xml', (rs) => { + rs.bc(true, (_rule, ctx) => { + const root = ctx.root() + if (isElement(root.node)) { + root.node = convert(root.node, opts) + } + }) + }) } -export { Feed, parseFeed, detect } +export { Feed, detect } export type { FeedFormat, diff --git a/test/feed.test.ts b/test/feed.test.ts index 0a00a12..8d55b69 100644 --- a/test/feed.test.ts +++ b/test/feed.test.ts @@ -4,7 +4,7 @@ import { test, describe } from 'node:test' import assert from 'node:assert' import { Jsonic } from 'jsonic' -import { Feed, parseFeed, detect } from '../dist/feed.js' +import { Feed, detect } from '../dist/feed.js' import type { AtomFeed, Rss1Feed, @@ -168,39 +168,47 @@ const RSS_090 = ` ` +// Build an atom-output parser once and reuse it for the bulk of the tests. +const atomParse = Jsonic.make().use(Feed) +const nativeParse = Jsonic.make().use(Feed, { format: 'native' }) +const rawParse = Jsonic.make().use(Feed, { format: 'raw' }) + + describe('feed - format detection', () => { + // Detection runs against the raw XmlElement tree. The `raw` parser gives + // us that tree without further conversion. test('detect atom 1.0', () => { - const root = Jsonic.make().use(require('@jsonic/xml').Xml)(ATOM_10) + const root: any = rawParse(ATOM_10) assert.deepEqual(detect(root), { dialect: 'atom', version: 'atom10' }) }) test('detect atom 0.3', () => { - const root = Jsonic.make().use(require('@jsonic/xml').Xml)(ATOM_03) + const root: any = rawParse(ATOM_03) assert.deepEqual(detect(root), { dialect: 'atom', version: 'atom03' }) }) test('detect rss 2.0', () => { - const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_20) + const root: any = rawParse(RSS_20) assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss20' }) }) test('detect rss 0.92', () => { - const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_092) + const root: any = rawParse(RSS_092) assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss092' }) }) test('detect rss 0.91', () => { - const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_091) + const root: any = rawParse(RSS_091) assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss091u' }) }) test('detect rss 1.0 (rdf)', () => { - const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_10) + const root: any = rawParse(RSS_10) assert.deepEqual(detect(root), { dialect: 'rdf', version: 'rss10' }) }) test('detect rss 0.90 (rdf)', () => { - const root = Jsonic.make().use(require('@jsonic/xml').Xml)(RSS_090) + const root: any = rawParse(RSS_090) assert.deepEqual(detect(root), { dialect: 'rdf', version: 'rss090' }) }) }) @@ -208,7 +216,7 @@ describe('feed - format detection', () => { describe('feed - default Atom output', () => { test('atom 1.0 round-trips through Atom output', () => { - const f = parseFeed(ATOM_10) as AtomFeed + const f = atomParse(ATOM_10) as AtomFeed assert.equal(f.format, 'atom') assert.equal(f.version, '1.0') assert.equal(f.id, 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6') @@ -242,7 +250,7 @@ describe('feed - default Atom output', () => { }) test('atom 0.3 maps tagline -> subtitle and modified -> updated', () => { - const f = parseFeed(ATOM_03) as AtomFeed + const f = atomParse(ATOM_03) as AtomFeed assert.equal(f.format, 'atom') assert.equal(f.version, '0.3') assert.deepEqual(f.subtitle, { type: 'text', value: 'An older feed' }) @@ -253,7 +261,7 @@ describe('feed - default Atom output', () => { }) test('rss 2.0 converts to Atom shape', () => { - const f = parseFeed(RSS_20) as AtomFeed + const f = atomParse(RSS_20) as AtomFeed assert.equal(f.format, 'atom') assert.deepEqual(f.title, { type: 'text', value: 'RSS 2 Sample' }) assert.deepEqual(f.subtitle, { type: 'text', value: 'RSS 2.0 description' }) @@ -292,19 +300,19 @@ describe('feed - default Atom output', () => { }) test('rss 0.92 / 0.91 convert to Atom', () => { - const f91 = parseFeed(RSS_091) as AtomFeed + const f91 = atomParse(RSS_091) as AtomFeed assert.equal(f91.format, 'atom') assert.deepEqual(f91.title, { type: 'text', value: 'RSS 0.91' }) assert.equal(f91.entries.length, 1) - const f92 = parseFeed(RSS_092) as AtomFeed + const f92 = atomParse(RSS_092) as AtomFeed assert.equal(f92.format, 'atom') assert.deepEqual(f92.title, { type: 'text', value: 'RSS 0.92' }) assert.equal(f92.entries[0].links?.[0].rel, 'enclosure') }) test('rss 1.0 (rdf) converts to Atom', () => { - const f = parseFeed(RSS_10) as AtomFeed + const f = atomParse(RSS_10) as AtomFeed assert.equal(f.format, 'atom') assert.deepEqual(f.title, { type: 'text', value: 'RSS 1.0 Example' }) assert.deepEqual(f.subtitle, { type: 'text', value: 'An RDF-based feed' }) @@ -317,7 +325,7 @@ describe('feed - default Atom output', () => { }) test('rss 0.90 (rdf) converts to Atom', () => { - const f = parseFeed(RSS_090) as AtomFeed + const f = atomParse(RSS_090) as AtomFeed assert.equal(f.format, 'atom') assert.deepEqual(f.title, { type: 'text', value: 'RSS 0.90' }) assert.equal(f.entries.length, 1) @@ -328,7 +336,7 @@ describe('feed - default Atom output', () => { describe('feed - native output', () => { test('rss 2.0 native shape', () => { - const f = parseFeed(RSS_20, { format: 'native' }) as Rss2Feed + const f = nativeParse(RSS_20) as Rss2Feed assert.equal(f.format, 'rss') assert.equal(f.version, '2.0') assert.equal(f.title, 'RSS 2 Sample') @@ -355,14 +363,14 @@ describe('feed - native output', () => { }) test('atom 1.0 native shape (already atom)', () => { - const f = parseFeed(ATOM_10, { format: 'native' }) as AtomFeed + const f = nativeParse(ATOM_10) as AtomFeed assert.equal(f.format, 'atom') assert.equal(f.version, '1.0') assert.equal(f.entries.length, 1) }) test('rss 1.0 native (rdf) shape', () => { - const f = parseFeed(RSS_10, { format: 'native' }) as Rss1Feed + const f = nativeParse(RSS_10) as Rss1Feed assert.equal(f.format, 'rdf') assert.equal(f.version, '1.0') assert.equal(f.about, 'http://example.org/index.rdf') @@ -375,7 +383,7 @@ describe('feed - native output', () => { describe('feed - raw output', () => { test('returns the underlying XmlElement tree', () => { - const root: any = parseFeed(ATOM_10, { format: 'raw' }) + const root: any = rawParse(ATOM_10) assert.equal(root.localName, 'feed') assert.equal(root.namespace, 'http://www.w3.org/2005/Atom') assert.ok(Array.isArray(root.children)) @@ -383,30 +391,9 @@ describe('feed - raw output', () => { }) -describe('feed - Plugin form', () => { - test('jsonic.feed(src) returns Atom by default', () => { - const j: any = Jsonic.make().use(Feed) - const f = j.feed(RSS_20) as AtomFeed - assert.equal(f.format, 'atom') - assert.equal(f.entries.length, 2) - }) - - test('jsonic.feed(src) honors plugin options', () => { - const j: any = Jsonic.make().use(Feed, { format: 'native' }) - const f = j.feed(RSS_20) as Rss2Feed - assert.equal(f.format, 'rss') - assert.equal(f.version, '2.0') - }) -}) - - describe('feed - errors', () => { test('unrecognized root element throws', () => { - assert.throws(() => parseFeed(''), /unrecognized root/) - }) - - test('non-XML input throws', () => { - assert.throws(() => parseFeed(''), /XML element|jsonic|unexpected/i) + assert.throws(() => atomParse(''), /unrecognized root/) }) }) @@ -419,7 +406,7 @@ describe('feed - xhtml content', () => {

body here

` - const f = parseFeed(src) as AtomFeed + const f = atomParse(src) as AtomFeed const e = f.entries[0] assert.equal(e.title?.type, 'xhtml') assert.match(e.title?.value || '', /Hi there<\/em>/) diff --git a/test/feedparser.test.ts b/test/feedparser.test.ts index 3ae9056..54af454 100644 --- a/test/feedparser.test.ts +++ b/test/feedparser.test.ts @@ -10,14 +10,13 @@ import assert from 'node:assert' import { readdirSync, readFileSync, existsSync } from 'node:fs' import { join } from 'node:path' -import { parseFeed, detect } from '../dist/feed.js' +import { Jsonic } from 'jsonic' +import { Feed, detect } from '../dist/feed.js' import type { AtomFeed, FeedDialect, FeedVersion, } from '../dist/feed.js' -import { Jsonic } from 'jsonic' -import { Xml } from '@jsonic/xml' const SUITE_DIR = join(__dirname, '..', 'test', 'feedparser-wellformed') @@ -36,16 +35,9 @@ const ATOM = loadDir('atom') const RSS = loadDir('rss') const RDF = loadDir('rdf') - -// Each upstream test file has a top-of-file -// preamble. We don't try to interpret arbitrary feedparser expectations here -// (their accessor model and ours differ substantially); we use the Description -// line as a label and assert on dialect+version detection plus a small set of -// hand-translated value checks below. -function description(src: string): string { - const m = src.match(/Description:\s*(.+)/) - return m ? m[1].trim() : '?' -} +// Reusable parsers — atom output (default) and raw output for detection. +const atomParse = Jsonic.make().use(Feed) +const rawParse = Jsonic.make().use(Feed, { format: 'raw' }) describe('feedparser-wellformed - dialect / version detection', () => { @@ -64,7 +56,7 @@ describe('feedparser-wellformed - dialect / version detection', () => { test(label, () => { const fails: string[] = [] for (const { file, src } of files) { - const root = Jsonic.make().use(Xml)(src) + const root: any = rawParse(src) const got = detect(root) const versionsOk = Array.isArray(expect.version) ? expect.version.includes(got.version) @@ -95,65 +87,31 @@ describe('feedparser-wellformed - dialect / version detection', () => { describe('feedparser-wellformed - parse without error', () => { if (!existsSync(SUITE_DIR)) return - test('all atom10 files parse to a feed', () => { - const fails: { file: string; err: string }[] = [] - for (const { file, src } of ATOM10) { - try { - const f = parseFeed(src) as AtomFeed - if (f.format !== 'atom') { - fails.push({ file, err: `format=${f.format}` }) - } - } catch (e: any) { - fails.push({ file, err: e?.message || String(e) }) - } - } - assert.deepEqual(fails, [], `atom10 failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) - }) - - test('all atom (0.3) files parse to a feed', () => { - const fails: { file: string; err: string }[] = [] - for (const { file, src } of ATOM) { - try { - const f = parseFeed(src) as AtomFeed - if (f.format !== 'atom') { - fails.push({ file, err: `format=${f.format}` }) - } - } catch (e: any) { - fails.push({ file, err: e?.message || String(e) }) - } - } - assert.deepEqual(fails, [], `atom failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) - }) - - test('all rss files parse to a feed', () => { - const fails: { file: string; err: string }[] = [] - for (const { file, src } of RSS) { - try { - const f = parseFeed(src) as AtomFeed - if (f.format !== 'atom') { - fails.push({ file, err: `format=${f.format}` }) + function checkAll(set: { file: string; src: string }[], label: string) { + test(`all ${label} files parse to a feed`, () => { + const fails: { file: string; err: string }[] = [] + for (const { file, src } of set) { + try { + const f = atomParse(src) as AtomFeed + if (f.format !== 'atom') { + fails.push({ file, err: `format=${f.format}` }) + } + } catch (e: any) { + fails.push({ file, err: e?.message || String(e) }) } - } catch (e: any) { - fails.push({ file, err: e?.message || String(e) }) } - } - assert.deepEqual(fails, [], `rss failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) - }) + assert.deepEqual( + fails, + [], + `${label} failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`, + ) + }) + } - test('all rdf files parse to a feed', () => { - const fails: { file: string; err: string }[] = [] - for (const { file, src } of RDF) { - try { - const f = parseFeed(src) as AtomFeed - if (f.format !== 'atom') { - fails.push({ file, err: `format=${f.format}` }) - } - } catch (e: any) { - fails.push({ file, err: e?.message || String(e) }) - } - } - assert.deepEqual(fails, [], `rdf failures:\n${fails.map((x) => ` ${x.file}: ${x.err}`).join('\n')}`) - }) + checkAll(ATOM10, 'atom10') + checkAll(ATOM, 'atom') + checkAll(RSS, 'rss') + checkAll(RDF, 'rdf') }) @@ -169,91 +127,91 @@ describe('feedparser-wellformed - targeted value checks', () => { test('atom10/entry_title -> entries[0].title.value == "Example Atom"', () => { const src = findFile(ATOM10, 'entry_title.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.entries[0].title?.value, 'Example Atom') }) test('atom10/entry_author_email -> entries[0].authors[0].email', () => { const src = findFile(ATOM10, 'entry_author_email.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.entries[0].authors?.[0].email, 'me@example.com') }) test('atom10/entry_author_name -> entries[0].authors[0].name', () => { const src = findFile(ATOM10, 'entry_author_name.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.entries[0].authors?.[0].name, 'Example author') }) test('atom10/entry_id -> entries[0].id', () => { const src = findFile(ATOM10, 'entry_id.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.ok(f.entries[0].id, 'id present') }) test('atom10/entry_link_href -> entries[0].links[0].href', () => { const src = findFile(ATOM10, 'entry_link_href.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.ok(f.entries[0].links?.[0].href, 'href present') }) test('atom/entry_title -> entries[0].title.value', () => { const src = findFile(ATOM, 'entry_title.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.ok(f.entries[0].title?.value, 'title present') }) test('atom/entry_issued -> entries[0].published', () => { const src = findFile(ATOM, 'entry_issued.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.ok(f.entries[0].published, 'published present') }) test('atom/entry_modified -> entries[0].updated', () => { const src = findFile(ATOM, 'entry_modified.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.ok(f.entries[0].updated, 'updated present') }) test('rss/channel_title -> title.value == "Example feed"', () => { const src = findFile(RSS, 'channel_title.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.title?.value, 'Example feed') }) test('rss/item_title -> entries[0].title.value', () => { const src = findFile(RSS, 'item_title.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.entries[0].title?.value, 'Item 1 title') }) test('rss/item_link -> entries[0].links[0].href', () => { const src = findFile(RSS, 'item_link.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.ok(f.entries[0].links?.[0].href, 'href present') }) test('rss/item_guid -> entries[0].id', () => { const src = findFile(RSS, 'item_guid.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.ok(f.entries[0].id, 'id present') }) test('rss/item_enclosure_url -> entries[0].links has rel=enclosure', () => { const src = findFile(RSS, 'item_enclosure_url.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed const enc = f.entries[0].links?.find((l) => l.rel === 'enclosure') assert.ok(enc, 'enclosure link present') }) @@ -261,28 +219,28 @@ describe('feedparser-wellformed - targeted value checks', () => { test('rdf/rdf_channel_title -> title.value == "Example feed"', () => { const src = findFile(RDF, 'rdf_channel_title.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.title?.value, 'Example feed') }) test('rdf/rdf_item_title -> entries[0].title.value == "Example title"', () => { const src = findFile(RDF, 'rdf_item_title.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.entries[0].title?.value, 'Example title') }) test('rdf/rss090_channel_title -> title.value == "Example title"', () => { const src = findFile(RDF, 'rss090_channel_title.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.title?.value, 'Example title') }) test('rdf/rdf_item_rdf_about -> entries[0].id is the rdf:about URI', () => { const src = findFile(RDF, 'rdf_item_rdf_about.xml') assert.ok(src, 'fixture present') - const f = parseFeed(src!) as AtomFeed + const f = atomParse(src!) as AtomFeed assert.equal(f.entries[0].id, 'http://example.org/1') }) }) From dfbb51ce10afef933c771dca2ffd2e98dee292fa Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 6 May 2026 12:43:04 +0000 Subject: [PATCH 3/4] Add Go parser with full parity, sharing fixtures via test/specs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a Go implementation of the feed parser at go/feed.go that mirrors the TypeScript plugin. Both languages now parse RSS 0.90 / 0.91 / 0.92 / 1.0 / 2.0 and Atom 0.3 / 1.0 into typed structures and default to a normalised Atom shape; format=native preserves the source dialect's structure and format=raw returns the underlying XmlElement tree from @jsonic/xml. Shared test fixtures live under test/specs/ — each base name has a .xml input, a .detect.json (expected dialect/version), an .atom.json (expected default output), and an optional .native.json. Both the TS and Go test suites enumerate the directory and JSON-compare results to expectations, so adding a fixture covers both languages automatically. The two language test suites also run the feedparser-wellformed corpus for no-error parsing plus a shared set of targeted value checks. Also fixes a re-entry bug in the bc hook: the xml rule's bc fires twice when there is trailing whitespace after the root element, so both implementations now skip the second invocation when r.Node has already been replaced with a converted feed. Makefile and CI workflow updated to build and test both languages. --- .github/workflows/build.yml | 22 + .gitignore | 3 + Makefile | 28 +- README.md | 157 +++- go/feed.go | 1265 +++++++++++++++++++++++++++ go/feed_test.go | 448 ++++++++++ go/go.mod | 8 + go/go.sum | 4 + test/feed.test.ts | 422 +-------- test/specs.test.ts | 82 ++ test/specs/README.md | 20 + test/specs/atom03-basic.atom.json | 25 + test/specs/atom03-basic.detect.json | 1 + test/specs/atom03-basic.xml | 16 + test/specs/atom10-rfc.atom.json | 37 + test/specs/atom10-rfc.detect.json | 1 + test/specs/atom10-rfc.xml | 27 + test/specs/atom10-xhtml.atom.json | 10 + test/specs/atom10-xhtml.detect.json | 1 + test/specs/atom10-xhtml.xml | 6 + test/specs/rss090-basic.atom.json | 19 + test/specs/rss090-basic.detect.json | 1 + test/specs/rss090-basic.xml | 14 + test/specs/rss091-basic.atom.json | 20 + test/specs/rss091-basic.detect.json | 1 + test/specs/rss091-basic.xml | 14 + test/specs/rss092-basic.atom.json | 18 + test/specs/rss092-basic.detect.json | 1 + test/specs/rss092-basic.xml | 12 + test/specs/rss10-basic.atom.json | 20 + test/specs/rss10-basic.detect.json | 1 + test/specs/rss10-basic.native.json | 16 + test/specs/rss10-basic.xml | 20 + test/specs/rss20-full.atom.json | 55 ++ test/specs/rss20-full.detect.json | 1 + test/specs/rss20-full.native.json | 50 ++ test/specs/rss20-full.xml | 41 + 37 files changed, 2469 insertions(+), 418 deletions(-) create mode 100644 go/feed.go create mode 100644 go/feed_test.go create mode 100644 go/go.mod create mode 100644 go/go.sum create mode 100644 test/specs.test.ts create mode 100644 test/specs/README.md create mode 100644 test/specs/atom03-basic.atom.json create mode 100644 test/specs/atom03-basic.detect.json create mode 100644 test/specs/atom03-basic.xml create mode 100644 test/specs/atom10-rfc.atom.json create mode 100644 test/specs/atom10-rfc.detect.json create mode 100644 test/specs/atom10-rfc.xml create mode 100644 test/specs/atom10-xhtml.atom.json create mode 100644 test/specs/atom10-xhtml.detect.json create mode 100644 test/specs/atom10-xhtml.xml create mode 100644 test/specs/rss090-basic.atom.json create mode 100644 test/specs/rss090-basic.detect.json create mode 100644 test/specs/rss090-basic.xml create mode 100644 test/specs/rss091-basic.atom.json create mode 100644 test/specs/rss091-basic.detect.json create mode 100644 test/specs/rss091-basic.xml create mode 100644 test/specs/rss092-basic.atom.json create mode 100644 test/specs/rss092-basic.detect.json create mode 100644 test/specs/rss092-basic.xml create mode 100644 test/specs/rss10-basic.atom.json create mode 100644 test/specs/rss10-basic.detect.json create mode 100644 test/specs/rss10-basic.native.json create mode 100644 test/specs/rss10-basic.xml create mode 100644 test/specs/rss20-full.atom.json create mode 100644 test/specs/rss20-full.detect.json create mode 100644 test/specs/rss20-full.native.json create mode 100644 test/specs/rss20-full.xml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dfa7b49..86381d6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -26,3 +26,25 @@ jobs: - run: npm i - run: npm run build --if-present - run: npm test + + build-go: + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, windows-latest, macos-latest] + + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version: '1.24' + - name: Build + working-directory: go + run: go build ./... + - name: Test + working-directory: go + run: go test -v ./... diff --git a/.gitignore b/.gitignore index e6358a0..aa45c2f 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,6 @@ dist-test package-lock.json yarn.lock + +# Go +go/vendor/ diff --git a/Makefile b/Makefile index 137b5db..4b92084 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,35 @@ -.PHONY: all build test clean reset +.PHONY: all build test clean reset build-ts build-go test-ts test-go clean-ts clean-go all: build test -build: +build: build-ts build-go + +test: test-ts test-go + +clean: clean-ts clean-go + +# TypeScript +build-ts: npm run build -test: +test-ts: npm test -clean: +clean-ts: rm -rf dist dist-test +# Go +build-go: + cd go && go build ./... + +test-go: + cd go && go test ./... + +clean-go: + cd go && go clean -cache + reset: npm run reset + cd go && go clean -cache + cd go && go build ./... + cd go && go test -v ./... diff --git a/README.md b/README.md index 49e08bd..f83910b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,19 @@ # @jsonic/feed -This plugin allows the [Jsonic](https://jsonic.senecajs.org) JSON parser -(via [`@jsonic/xml`](https://github.com/jsonicjs/xml)) to parse +A [Jsonic](https://jsonic.senecajs.org) plugin (built on +[`@jsonic/xml`](https://github.com/jsonicjs/xml)) that parses syndication feeds — **RSS 0.90, 0.91, 0.92, 1.0, 2.0** and **Atom 0.3, 1.0** — into a typed structure. By default every dialect is normalised to an Atom-shaped result; pass `format: 'native'` to keep the source dialect's structure, or `format: 'raw'` to get back the underlying -`XmlElement` tree from `@jsonic/xml`. +XML element tree from `@jsonic/xml`. + +The same parser is available in two languages: + +| Language | Package | Source | +| ---------- | -------------------------------------------------------------- | ----------------------------------- | +| TypeScript | [`@jsonic/feed`](https://npmjs.com/package/@jsonic/feed) | [`src/feed.ts`](src/feed.ts) | +| Go | [`github.com/jsonicjs/feed/go`](https://github.com/jsonicjs/feed/tree/main/go) | [`go/feed.go`](go/feed.go) | [![npm version](https://img.shields.io/npm/v/@jsonic/feed.svg)](https://npmjs.com/package/@jsonic/feed) [![build](https://github.com/jsonicjs/feed/actions/workflows/build.yml/badge.svg)](https://github.com/jsonicjs/feed/actions/workflows/build.yml) @@ -16,7 +23,7 @@ dialect's structure, or `format: 'raw'` to get back the underlying | ---------------------------------------------------- | --------------------------------------------------------------------------------------- | -The documentation below is organized along the +The documentation below is organised along the [Diátaxis](https://diataxis.fr) quadrants: - [Quick start](#quick-start) — tutorial @@ -27,15 +34,12 @@ The documentation below is organized along the ## Quick start -Install: +### TypeScript ```bash npm install @jsonic/feed jsonic @jsonic/xml ``` -Register the plugin and call the Jsonic instance as usual — the result -is an Atom-shaped object regardless of the input dialect: - ```typescript import { Jsonic } from 'jsonic' import { Feed } from '@jsonic/feed' @@ -61,7 +65,40 @@ const atom = j(` // atom.format === 'atom' // atom.title.value === 'My Blog' // atom.entries[0].id === 'https://example.com/1' -// atom.entries[0].links[0] === { href: 'https://example.com/1', rel: 'alternate' } +``` + +### Go + +```bash +go get github.com/jsonicjs/feed/go +``` + +```go +package main + +import ( + "fmt" + jsonic "github.com/jsonicjs/jsonic/go" + feed "github.com/jsonicjs/feed/go" +) + +func main() { + j := jsonic.Make() + if err := j.UseDefaults(feed.Feed, feed.Defaults); err != nil { + panic(err) + } + got, err := j.Parse(` + + My Blog + Hello1 + + `) + if err != nil { + panic(err) + } + f := got.(feed.AtomFeed) + fmt.Println(f.Title.Value, "/", f.Entries[0].ID) +} ``` @@ -69,16 +106,25 @@ const atom = j(` ### Keep the source dialect's structure (no Atom conversion) +TypeScript: + ```typescript import { Jsonic } from 'jsonic' import { Feed, type Rss2Feed } from '@jsonic/feed' const j = Jsonic.make().use(Feed, { format: 'native' }) - const native = j(rssSource) as Rss2Feed -// native.format === 'rss' -// native.version === '2.0' -// native.items[0].guid?.value === 'item-1-guid' +// native.format === 'rss', native.version === '2.0' +``` + +Go: + +```go +j := jsonic.Make() +j.UseDefaults(feed.Feed, feed.Defaults, map[string]any{"format": "native"}) +got, _ := j.Parse(rssSource) +native := got.(feed.Rss2Feed) +// native.Format == "rss", native.Version == "2.0" ``` The native return type is a discriminated union on `format`: @@ -91,35 +137,53 @@ The native return type is a discriminated union on `format`: ### Get the raw XML tree -```typescript -import { Jsonic } from 'jsonic' -import { Feed } from '@jsonic/feed' +TypeScript: +```typescript const j = Jsonic.make().use(Feed, { format: 'raw' }) - const tree = j(rssSource) -// tree.localName === 'rss' -// tree.children === [...] +// tree.localName === 'rss', tree.children === [...] +``` + +Go: + +```go +j := jsonic.Make() +j.UseDefaults(feed.Feed, feed.Defaults, map[string]any{"format": "raw"}) +got, _ := j.Parse(rssSource) +tree := got.(map[string]any) +// tree["localName"] == "rss", tree["children"].([]any) == [...] ``` -This is the `XmlElement` produced by `@jsonic/xml` with no further +This is the element tree produced by `@jsonic/xml` with no further processing, useful when you want to handle non-standard extensions. ### Detect a dialect without converting +TypeScript: + ```typescript -import { Jsonic } from 'jsonic' import { Feed, detect } from '@jsonic/feed' - const j = Jsonic.make().use(Feed, { format: 'raw' }) -const root = j(rssSource) -const { dialect, version } = detect(root) +const { dialect, version } = detect(j(rssSource)) // e.g. { dialect: 'rss', version: 'rss20' } ``` +Go: + +```go +j := jsonic.Make() +j.UseDefaults(feed.Feed, feed.Defaults, map[string]any{"format": "raw"}) +got, _ := j.Parse(rssSource) +det := feed.Detect(got) +// e.g. feed.Detection{Dialect: "rss", Version: "rss20"} +``` + ## Reference +### TypeScript + ```typescript const Feed: Plugin @@ -149,6 +213,29 @@ tree, when `options.format === 'raw'`). |----------|-------------------------------|----------|-------------------------------------------------------| | `format` | `'atom' \| 'native' \| 'raw'` | `'atom'` | Output shape: normalised Atom, dialect-native, or raw XML tree | +### Go + +```go +func Feed(j *jsonic.Jsonic, opts map[string]any) error +func Detect(root any) Detection + +var Defaults = map[string]any{ "format": "atom" } + +type Detection struct { + Dialect string `json:"dialect"` + Version string `json:"version"` +} +``` + +Register with `j.UseDefaults(feed.Feed, feed.Defaults, opts)` where +`opts` is a `map[string]any` overriding the defaults. `Parse` then +returns `(any, error)`; type-assert the result to `feed.AtomFeed`, +`feed.Rss2Feed`, or `feed.Rss1Feed` based on the `format` option. + +| Key | Type | Default | Effect | +|----------|----------|----------|-------------------------------------------------------| +| `format` | `string` | `"atom"` | Output shape: `"atom"`, `"native"`, or `"raw"` | + Atom shape (the default output) follows RFC 4287 closely: ```typescript @@ -194,9 +281,9 @@ type AtomGenerator = { uri?: string; version?: string; value: string } type AtomContent = { type: string; src?: string; value?: string } ``` -The native RSS 2/0.91/0.92 and RSS 1.0/0.90 shapes (`Rss2Feed`, -`Rss2Item`, `Rss1Feed`, `Rss1Item` …) are also exported; see -`src/feed.ts` for the full set. +The Go structs (`AtomFeed`, `AtomEntry`, `Rss2Feed`, `Rss2Item`, +`Rss1Feed`, `Rss1Item`, …) carry equivalent JSON tags so they marshal +to the same shape. See [`go/feed.go`](go/feed.go) for the full set. ## Format mapping @@ -242,6 +329,22 @@ For Atom 0.3 → Atom 1.0 the legacy element names are renamed: `copyright → rights`. +## Tests + +The TypeScript and Go test suites share fixtures from +[`test/specs/`](test/specs/) — each base name has a `.xml` input and one +or more expected JSON outputs (`.atom.json`, `.native.json`, +`.detect.json`). Both languages enumerate the directory and JSON-compare +the parser result to the expected output, so adding a new fixture is +covered by both immediately. + +Both suites also run against a focused subset of well-formed feeds +vendored from [`kurtmckee/feedparser`](https://github.com/kurtmckee/feedparser) +under BSD 2-Clause (see +[THIRD_PARTY_NOTICES.md](./THIRD_PARTY_NOTICES.md)) at +[`test/feedparser-wellformed/`](test/feedparser-wellformed/). + + ## Acknowledgments Conformance testing uses third-party corpora under permissive licenses diff --git a/go/feed.go b/go/feed.go new file mode 100644 index 0000000..0dfa0d4 --- /dev/null +++ b/go/feed.go @@ -0,0 +1,1265 @@ +// Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License + +// Package feed is a Jsonic plugin that parses RSS (0.90, 0.91, 0.92, 1.0, +// 2.0) and Atom (0.3, 1.0) syndication feeds. Built on top of +// github.com/jsonicjs/xml/go, every dialect is normalised by default to an +// Atom-shaped result; pass options{"format": "native"} to keep the source +// dialect's structure or options{"format": "raw"} to get back the raw XML +// element tree from the xml plugin. +package feed + +import ( + "fmt" + "regexp" + "strconv" + "strings" + + jsonic "github.com/jsonicjs/jsonic/go" + xml "github.com/jsonicjs/xml/go" +) + +const Version = "0.1.0" + +// Defaults are merged with caller-supplied options when the plugin is +// registered via jsonic.UseDefaults. The single supported option is +// "format" with values "atom" (default), "native", or "raw". +var Defaults = map[string]any{ + "format": "atom", +} + +// --- Public types --------------------------------------------------------- + +// AtomText carries an Atom body. +type AtomText struct { + Type string `json:"type"` + Value string `json:"value"` +} + +// AtomPerson is an author or contributor. +type AtomPerson struct { + Name string `json:"name"` + URI string `json:"uri,omitempty"` + Email string `json:"email,omitempty"` +} + +// AtomLink is an Atom . +type AtomLink struct { + Href string `json:"href"` + Rel string `json:"rel,omitempty"` + Type string `json:"type,omitempty"` + Hreflang string `json:"hreflang,omitempty"` + Title string `json:"title,omitempty"` + Length int `json:"length,omitempty"` +} + +// AtomCategory is an Atom . +type AtomCategory struct { + Term string `json:"term"` + Scheme string `json:"scheme,omitempty"` + Label string `json:"label,omitempty"` +} + +// AtomGenerator is an Atom . +type AtomGenerator struct { + URI string `json:"uri,omitempty"` + Version string `json:"version,omitempty"` + Value string `json:"value"` +} + +// AtomContent is an Atom . +type AtomContent struct { + Type string `json:"type"` + Src string `json:"src,omitempty"` + Value string `json:"value,omitempty"` +} + +// AtomEntrySource is the slim Atom-feed shape used in AtomEntry.Source. It +// mirrors the TS Partial with only the fields produced when an +// RSS element is mapped to Atom. +type AtomEntrySource struct { + Format string `json:"format"` + Version string `json:"version"` + ID string `json:"id,omitempty"` + Title *AtomText `json:"title,omitempty"` + Updated string `json:"updated,omitempty"` + Links []AtomLink `json:"links,omitempty"` +} + +// AtomEntry is an Atom . +type AtomEntry struct { + ID string `json:"id,omitempty"` + Title *AtomText `json:"title,omitempty"` + Updated string `json:"updated,omitempty"` + Published string `json:"published,omitempty"` + Authors []AtomPerson `json:"authors,omitempty"` + Contributors []AtomPerson `json:"contributors,omitempty"` + Categories []AtomCategory `json:"categories,omitempty"` + Content *AtomContent `json:"content,omitempty"` + Links []AtomLink `json:"links,omitempty"` + Rights *AtomText `json:"rights,omitempty"` + Summary *AtomText `json:"summary,omitempty"` + Source *AtomEntrySource `json:"source,omitempty"` +} + +// AtomFeed is the normalised Atom-shaped output (the default). +type AtomFeed struct { + Format string `json:"format"` + Version string `json:"version"` + ID string `json:"id,omitempty"` + Title *AtomText `json:"title,omitempty"` + Updated string `json:"updated,omitempty"` + Authors []AtomPerson `json:"authors,omitempty"` + Contributors []AtomPerson `json:"contributors,omitempty"` + Categories []AtomCategory `json:"categories,omitempty"` + Generator *AtomGenerator `json:"generator,omitempty"` + Icon string `json:"icon,omitempty"` + Logo string `json:"logo,omitempty"` + Rights *AtomText `json:"rights,omitempty"` + Subtitle *AtomText `json:"subtitle,omitempty"` + Links []AtomLink `json:"links,omitempty"` + Entries []AtomEntry `json:"entries"` +} + +// Rss2Category is an RSS 2.x . +type Rss2Category struct { + Domain string `json:"domain,omitempty"` + Value string `json:"value"` +} + +// Rss2Enclosure is an RSS 2.x . +type Rss2Enclosure struct { + URL string `json:"url"` + Length int `json:"length,omitempty"` + Type string `json:"type,omitempty"` +} + +// Rss2Guid is an RSS 2.x . +type Rss2Guid struct { + IsPermaLink *bool `json:"isPermaLink,omitempty"` + Value string `json:"value"` +} + +// Rss2Source is an RSS 2.x item . +type Rss2Source struct { + URL string `json:"url,omitempty"` + Value string `json:"value"` +} + +// Rss2Image is an RSS 2.x channel . +type Rss2Image struct { + URL string `json:"url"` + Title string `json:"title"` + Link string `json:"link"` + Width int `json:"width,omitempty"` + Height int `json:"height,omitempty"` + Description string `json:"description,omitempty"` +} + +// Rss2Cloud is an RSS 2.x channel . +type Rss2Cloud struct { + Domain string `json:"domain"` + Port int `json:"port"` + Path string `json:"path"` + RegisterProcedure string `json:"registerProcedure"` + Protocol string `json:"protocol"` +} + +// Rss2TextInput is an RSS 2.x channel . +type Rss2TextInput struct { + Title string `json:"title"` + Description string `json:"description"` + Name string `json:"name"` + Link string `json:"link"` +} + +// Rss2Item is an RSS 2.x channel item. +type Rss2Item struct { + Title string `json:"title,omitempty"` + Link string `json:"link,omitempty"` + Description string `json:"description,omitempty"` + Author string `json:"author,omitempty"` + Categories []Rss2Category `json:"categories,omitempty"` + Comments string `json:"comments,omitempty"` + Enclosure *Rss2Enclosure `json:"enclosure,omitempty"` + Guid *Rss2Guid `json:"guid,omitempty"` + PubDate string `json:"pubDate,omitempty"` + Source *Rss2Source `json:"source,omitempty"` +} + +// Rss2Feed is the native shape for RSS 0.91 / 0.92 / 2.0. +type Rss2Feed struct { + Format string `json:"format"` + Version string `json:"version"` + Title string `json:"title"` + Link string `json:"link"` + Description string `json:"description"` + Language string `json:"language,omitempty"` + Copyright string `json:"copyright,omitempty"` + ManagingEditor string `json:"managingEditor,omitempty"` + WebMaster string `json:"webMaster,omitempty"` + PubDate string `json:"pubDate,omitempty"` + LastBuildDate string `json:"lastBuildDate,omitempty"` + Categories []Rss2Category `json:"categories,omitempty"` + Generator string `json:"generator,omitempty"` + Docs string `json:"docs,omitempty"` + Cloud *Rss2Cloud `json:"cloud,omitempty"` + TTL int `json:"ttl,omitempty"` + Image *Rss2Image `json:"image,omitempty"` + TextInput *Rss2TextInput `json:"textInput,omitempty"` + SkipHours []int `json:"skipHours,omitempty"` + SkipDays []string `json:"skipDays,omitempty"` + Items []Rss2Item `json:"items"` +} + +// Rss1Item is an RSS 1.0 / 0.90 item. +type Rss1Item struct { + About string `json:"about,omitempty"` + Title string `json:"title"` + Link string `json:"link"` + Description string `json:"description,omitempty"` +} + +// Rss1Image is an RSS 1.0 / 0.90 image. +type Rss1Image struct { + About string `json:"about,omitempty"` + Title string `json:"title"` + Link string `json:"link"` + URL string `json:"url"` +} + +// Rss1TextInput is an RSS 1.0 / 0.90 textinput. +type Rss1TextInput struct { + About string `json:"about,omitempty"` + Title string `json:"title"` + Description string `json:"description"` + Name string `json:"name"` + Link string `json:"link"` +} + +// Rss1Feed is the native shape for RSS 0.90 / 1.0 (RDF). +type Rss1Feed struct { + Format string `json:"format"` + Version string `json:"version"` + About string `json:"about,omitempty"` + Title string `json:"title"` + Link string `json:"link"` + Description string `json:"description,omitempty"` + Image *Rss1Image `json:"image,omitempty"` + TextInput *Rss1TextInput `json:"textInput,omitempty"` + Items []Rss1Item `json:"items"` +} + +// Detection is the result of Detect. +type Detection struct { + Dialect string `json:"dialect"` + Version string `json:"version"` +} + +// --- Namespaces ----------------------------------------------------------- + +const ( + nsAtom10 = "http://www.w3.org/2005/Atom" + nsAtom03 = "http://purl.org/atom/ns#" + nsRSS10 = "http://purl.org/rss/1.0/" + nsRSS090 = "http://my.netscape.com/rdf/simple/0.9/" +) + +// --- XmlElement helpers --------------------------------------------------- +// +// The xml plugin returns elements as map[string]any with keys: +// name, localName, prefix, namespace, attributes (map[string]string), +// children ([]any with strings or nested element maps). + +func asElement(v any) (map[string]any, bool) { + el, ok := v.(map[string]any) + if !ok { + return nil, false + } + if _, hasChildren := el["children"]; !hasChildren { + return nil, false + } + return el, true +} + +func localName(el map[string]any) string { + if s, ok := el["localName"].(string); ok { + return s + } + if s, ok := el["name"].(string); ok { + return s + } + return "" +} + +func namespace(el map[string]any) string { + if s, ok := el["namespace"].(string); ok { + return s + } + return "" +} + +func attribute(el map[string]any, name string) (string, bool) { + a, ok := el["attributes"].(map[string]any) + if !ok { + // xml plugin usually emits attributes as map[string]string + if as, ok2 := el["attributes"].(map[string]string); ok2 { + v, ok3 := as[name] + return v, ok3 + } + return "", false + } + v, ok := a[name].(string) + return v, ok +} + +func children(el map[string]any) []any { + c, _ := el["children"].([]any) + return c +} + +func findChild(el map[string]any, name string) map[string]any { + if el == nil { + return nil + } + for _, c := range children(el) { + ce, ok := asElement(c) + if !ok { + continue + } + if localName(ce) == name { + return ce + } + } + return nil +} + +func findChildren(el map[string]any, name string) []map[string]any { + out := []map[string]any{} + if el == nil { + return out + } + for _, c := range children(el) { + ce, ok := asElement(c) + if !ok { + continue + } + if localName(ce) == name { + out = append(out, ce) + } + } + return out +} + +// textOf concatenates direct text-node children, trimmed. +func textOf(el map[string]any) string { + if el == nil { + return "" + } + var b strings.Builder + for _, c := range children(el) { + if s, ok := c.(string); ok { + b.WriteString(s) + } + } + return strings.TrimSpace(b.String()) +} + +// innerXml serialises an element's children (text + nested elements) +// back to a string. Used for xhtml content extraction. +func innerXml(el map[string]any) string { + if el == nil { + return "" + } + var b strings.Builder + for _, c := range children(el) { + if s, ok := c.(string); ok { + b.WriteString(s) + continue + } + if ce, ok := asElement(c); ok { + b.WriteString(serializeElement(ce)) + } + } + return b.String() +} + +func serializeElement(el map[string]any) string { + name, _ := el["name"].(string) + if name == "" { + name = localName(el) + } + var b strings.Builder + b.WriteByte('<') + b.WriteString(name) + switch attrs := el["attributes"].(type) { + case map[string]any: + for k, v := range attrs { + s, _ := v.(string) + b.WriteString(` `) + b.WriteString(k) + b.WriteString(`="`) + b.WriteString(escapeAttr(s)) + b.WriteString(`"`) + } + case map[string]string: + for k, v := range attrs { + b.WriteString(` `) + b.WriteString(k) + b.WriteString(`="`) + b.WriteString(escapeAttr(v)) + b.WriteString(`"`) + } + } + inner := innerXml(el) + if inner == "" { + b.WriteString("/>") + return b.String() + } + b.WriteByte('>') + b.WriteString(inner) + b.WriteString("') + return b.String() +} + +var attrReplacer = strings.NewReplacer( + `&`, `&`, + `"`, `"`, + `<`, `<`, + `>`, `>`, +) + +func escapeAttr(s string) string { return attrReplacer.Replace(s) } + +// --- Detection ------------------------------------------------------------ + +// Detect inspects a parsed XML root element and reports the feed dialect / +// version. It accepts the map[string]any element shape produced by the +// xml plugin. +func Detect(root any) Detection { + el, ok := asElement(root) + if !ok { + return Detection{Dialect: "unknown", Version: "unknown"} + } + switch localName(el) { + case "feed": + if namespace(el) == nsAtom03 { + return Detection{Dialect: "atom", Version: "atom03"} + } + return Detection{Dialect: "atom", Version: "atom10"} + + case "rss": + v, _ := attribute(el, "version") + switch v { + case "2.0", "2.0.1", "2.0.2": + return Detection{Dialect: "rss", Version: "rss20"} + case "0.92", "0.93", "0.94": + return Detection{Dialect: "rss", Version: "rss092"} + case "0.91": + return Detection{Dialect: "rss", Version: "rss091u"} + } + return Detection{Dialect: "rss", Version: "rss20"} + + case "RDF": + ch := findChild(el, "channel") + if ch != nil && namespace(ch) == nsRSS090 { + return Detection{Dialect: "rdf", Version: "rss090"} + } + return Detection{Dialect: "rdf", Version: "rss10"} + } + + return Detection{Dialect: "unknown", Version: "unknown"} +} + +// --- Atom (native) parser ------------------------------------------------- + +func parsePerson(el map[string]any) AtomPerson { + p := AtomPerson{Name: textOf(findChild(el, "name"))} + if uri := textOf(findChild(el, "uri")); uri != "" { + p.URI = uri + } else if url := textOf(findChild(el, "url")); url != "" { + p.URI = url + } + if e := textOf(findChild(el, "email")); e != "" { + p.Email = e + } + return p +} + +func parseLink(el map[string]any) AtomLink { + l := AtomLink{} + if h, ok := attribute(el, "href"); ok { + l.Href = h + } + if v, ok := attribute(el, "rel"); ok { + l.Rel = v + } + if v, ok := attribute(el, "type"); ok { + l.Type = v + } + if v, ok := attribute(el, "hreflang"); ok { + l.Hreflang = v + } + if v, ok := attribute(el, "title"); ok { + l.Title = v + } + if v, ok := attribute(el, "length"); ok { + if n, err := strconv.Atoi(v); err == nil { + l.Length = n + } + } + return l +} + +func parseCategory(el map[string]any) AtomCategory { + c := AtomCategory{} + if t, ok := attribute(el, "term"); ok { + c.Term = t + } else { + c.Term = textOf(el) + } + if v, ok := attribute(el, "scheme"); ok { + c.Scheme = v + } + if v, ok := attribute(el, "label"); ok { + c.Label = v + } + return c +} + +func parseText(el map[string]any) *AtomText { + if el == nil { + return nil + } + t := "text" + if v, ok := attribute(el, "type"); ok { + t = v + } + if t == "xhtml" { + div := findChild(el, "div") + if div == nil { + div = el + } + return &AtomText{Type: t, Value: innerXml(div)} + } + return &AtomText{Type: t, Value: textOf(el)} +} + +func parseContent(el map[string]any) *AtomContent { + t := "text" + if v, ok := attribute(el, "type"); ok { + t = v + } + out := &AtomContent{Type: t} + if v, ok := attribute(el, "src"); ok { + out.Src = v + } + if t == "xhtml" { + div := findChild(el, "div") + if div == nil { + div = el + } + out.Value = innerXml(div) + } else { + out.Value = textOf(el) + } + return out +} + +func parseGenerator(el map[string]any) *AtomGenerator { + g := &AtomGenerator{Value: textOf(el)} + if v, ok := attribute(el, "uri"); ok { + g.URI = v + } + if v, ok := attribute(el, "version"); ok { + g.Version = v + } + return g +} + +func parseAtomEntry(el map[string]any, atom03 bool) AtomEntry { + entry := AtomEntry{} + if id := findChild(el, "id"); id != nil { + entry.ID = textOf(id) + } + if t := findChild(el, "title"); t != nil { + entry.Title = parseText(t) + } + updatedTag := "updated" + publishedTag := "published" + if atom03 { + updatedTag = "modified" + publishedTag = "issued" + } + if u := findChild(el, updatedTag); u != nil { + entry.Updated = textOf(u) + } + if p := findChild(el, publishedTag); p != nil { + entry.Published = textOf(p) + } + if as := findChildren(el, "author"); len(as) > 0 { + entry.Authors = make([]AtomPerson, 0, len(as)) + for _, a := range as { + entry.Authors = append(entry.Authors, parsePerson(a)) + } + } + if cs := findChildren(el, "contributor"); len(cs) > 0 { + entry.Contributors = make([]AtomPerson, 0, len(cs)) + for _, c := range cs { + entry.Contributors = append(entry.Contributors, parsePerson(c)) + } + } + if cs := findChildren(el, "category"); len(cs) > 0 { + entry.Categories = make([]AtomCategory, 0, len(cs)) + for _, c := range cs { + entry.Categories = append(entry.Categories, parseCategory(c)) + } + } + if ls := findChildren(el, "link"); len(ls) > 0 { + entry.Links = make([]AtomLink, 0, len(ls)) + for _, l := range ls { + entry.Links = append(entry.Links, parseLink(l)) + } + } + if c := findChild(el, "content"); c != nil { + entry.Content = parseContent(c) + } + rightsTag := "rights" + if atom03 { + rightsTag = "copyright" + } + if r := findChild(el, rightsTag); r != nil { + entry.Rights = parseText(r) + } + summaryTag := "summary" + if atom03 { + summaryTag = "tagline" + } + if s := findChild(el, summaryTag); s != nil { + entry.Summary = parseText(s) + } + return entry +} + +func parseAtom(root map[string]any, atom03 bool) AtomFeed { + feed := AtomFeed{Format: "atom", Version: "1.0", Entries: []AtomEntry{}} + if atom03 { + feed.Version = "0.3" + } + if id := findChild(root, "id"); id != nil { + feed.ID = textOf(id) + } + if t := findChild(root, "title"); t != nil { + feed.Title = parseText(t) + } + updatedTag := "updated" + if atom03 { + updatedTag = "modified" + } + if u := findChild(root, updatedTag); u != nil { + feed.Updated = textOf(u) + } + if as := findChildren(root, "author"); len(as) > 0 { + feed.Authors = make([]AtomPerson, 0, len(as)) + for _, a := range as { + feed.Authors = append(feed.Authors, parsePerson(a)) + } + } + if cs := findChildren(root, "contributor"); len(cs) > 0 { + feed.Contributors = make([]AtomPerson, 0, len(cs)) + for _, c := range cs { + feed.Contributors = append(feed.Contributors, parsePerson(c)) + } + } + if cs := findChildren(root, "category"); len(cs) > 0 { + feed.Categories = make([]AtomCategory, 0, len(cs)) + for _, c := range cs { + feed.Categories = append(feed.Categories, parseCategory(c)) + } + } + if ls := findChildren(root, "link"); len(ls) > 0 { + feed.Links = make([]AtomLink, 0, len(ls)) + for _, l := range ls { + feed.Links = append(feed.Links, parseLink(l)) + } + } + if g := findChild(root, "generator"); g != nil { + feed.Generator = parseGenerator(g) + } + if i := findChild(root, "icon"); i != nil { + feed.Icon = textOf(i) + } + if l := findChild(root, "logo"); l != nil { + feed.Logo = textOf(l) + } + rightsTag := "rights" + if atom03 { + rightsTag = "copyright" + } + if r := findChild(root, rightsTag); r != nil { + feed.Rights = parseText(r) + } + subtitleTag := "subtitle" + if atom03 { + subtitleTag = "tagline" + } + if s := findChild(root, subtitleTag); s != nil { + feed.Subtitle = parseText(s) + } + for _, e := range findChildren(root, "entry") { + feed.Entries = append(feed.Entries, parseAtomEntry(e, atom03)) + } + return feed +} + +// --- RSS 2.x / 0.91 / 0.92 (native) parser -------------------------------- + +func parseRss2Image(el map[string]any) *Rss2Image { + img := &Rss2Image{ + URL: textOf(findChild(el, "url")), + Title: textOf(findChild(el, "title")), + Link: textOf(findChild(el, "link")), + } + if w := textOf(findChild(el, "width")); w != "" { + if n, err := strconv.Atoi(w); err == nil { + img.Width = n + } + } + if h := textOf(findChild(el, "height")); h != "" { + if n, err := strconv.Atoi(h); err == nil { + img.Height = n + } + } + if d := textOf(findChild(el, "description")); d != "" { + img.Description = d + } + return img +} + +func parseRss2Cloud(el map[string]any) *Rss2Cloud { + c := &Rss2Cloud{} + if v, ok := attribute(el, "domain"); ok { + c.Domain = v + } + if v, ok := attribute(el, "port"); ok { + if n, err := strconv.Atoi(v); err == nil { + c.Port = n + } + } + if v, ok := attribute(el, "path"); ok { + c.Path = v + } + if v, ok := attribute(el, "registerProcedure"); ok { + c.RegisterProcedure = v + } + if v, ok := attribute(el, "protocol"); ok { + c.Protocol = v + } + return c +} + +func parseRss2TextInput(el map[string]any) *Rss2TextInput { + return &Rss2TextInput{ + Title: textOf(findChild(el, "title")), + Description: textOf(findChild(el, "description")), + Name: textOf(findChild(el, "name")), + Link: textOf(findChild(el, "link")), + } +} + +func parseRss2Item(el map[string]any) Rss2Item { + item := Rss2Item{} + if v := findChild(el, "title"); v != nil { + item.Title = textOf(v) + } + if v := findChild(el, "link"); v != nil { + item.Link = textOf(v) + } + if v := findChild(el, "description"); v != nil { + item.Description = textOf(v) + } + if v := findChild(el, "author"); v != nil { + item.Author = textOf(v) + } + if cs := findChildren(el, "category"); len(cs) > 0 { + item.Categories = make([]Rss2Category, 0, len(cs)) + for _, c := range cs { + cat := Rss2Category{Value: textOf(c)} + if d, ok := attribute(c, "domain"); ok { + cat.Domain = d + } + item.Categories = append(item.Categories, cat) + } + } + if v := findChild(el, "comments"); v != nil { + item.Comments = textOf(v) + } + if enc := findChild(el, "enclosure"); enc != nil { + out := &Rss2Enclosure{} + if v, ok := attribute(enc, "url"); ok { + out.URL = v + } + if v, ok := attribute(enc, "length"); ok { + if n, err := strconv.Atoi(v); err == nil { + out.Length = n + } + } + if v, ok := attribute(enc, "type"); ok { + out.Type = v + } + item.Enclosure = out + } + if g := findChild(el, "guid"); g != nil { + guid := &Rss2Guid{Value: textOf(g)} + if v, ok := attribute(g, "isPermaLink"); ok { + b := v != "false" + guid.IsPermaLink = &b + } + item.Guid = guid + } + if v := findChild(el, "pubDate"); v != nil { + item.PubDate = textOf(v) + } + if s := findChild(el, "source"); s != nil { + src := &Rss2Source{Value: textOf(s)} + if v, ok := attribute(s, "url"); ok { + src.URL = v + } + item.Source = src + } + return item +} + +func parseRss2(root map[string]any, version string) Rss2Feed { + channel := findChild(root, "channel") + if channel == nil { + channel = root + } + v := "2.0" + switch version { + case "rss092": + v = "0.92" + case "rss091u", "rss091n": + v = "0.91" + } + feed := Rss2Feed{ + Format: "rss", + Version: v, + Title: textOf(findChild(channel, "title")), + Link: textOf(findChild(channel, "link")), + Description: textOf(findChild(channel, "description")), + Items: []Rss2Item{}, + } + if v := findChild(channel, "language"); v != nil { + feed.Language = textOf(v) + } + if v := findChild(channel, "copyright"); v != nil { + feed.Copyright = textOf(v) + } + if v := findChild(channel, "managingEditor"); v != nil { + feed.ManagingEditor = textOf(v) + } + if v := findChild(channel, "webMaster"); v != nil { + feed.WebMaster = textOf(v) + } + if v := findChild(channel, "pubDate"); v != nil { + feed.PubDate = textOf(v) + } + if v := findChild(channel, "lastBuildDate"); v != nil { + feed.LastBuildDate = textOf(v) + } + if cs := findChildren(channel, "category"); len(cs) > 0 { + feed.Categories = make([]Rss2Category, 0, len(cs)) + for _, c := range cs { + cat := Rss2Category{Value: textOf(c)} + if d, ok := attribute(c, "domain"); ok { + cat.Domain = d + } + feed.Categories = append(feed.Categories, cat) + } + } + if v := findChild(channel, "generator"); v != nil { + feed.Generator = textOf(v) + } + if v := findChild(channel, "docs"); v != nil { + feed.Docs = textOf(v) + } + if c := findChild(channel, "cloud"); c != nil { + feed.Cloud = parseRss2Cloud(c) + } + if t := findChild(channel, "ttl"); t != nil { + if n, err := strconv.Atoi(textOf(t)); err == nil { + feed.TTL = n + } + } + if i := findChild(channel, "image"); i != nil { + feed.Image = parseRss2Image(i) + } + ti := findChild(channel, "textInput") + if ti == nil { + ti = findChild(channel, "textinput") + } + if ti != nil { + feed.TextInput = parseRss2TextInput(ti) + } + if sh := findChild(channel, "skipHours"); sh != nil { + for _, h := range findChildren(sh, "hour") { + if n, err := strconv.Atoi(textOf(h)); err == nil { + feed.SkipHours = append(feed.SkipHours, n) + } + } + } + if sd := findChild(channel, "skipDays"); sd != nil { + for _, d := range findChildren(sd, "day") { + feed.SkipDays = append(feed.SkipDays, textOf(d)) + } + } + for _, item := range findChildren(channel, "item") { + feed.Items = append(feed.Items, parseRss2Item(item)) + } + return feed +} + +// --- RSS 1.0 / 0.90 (RDF) parser ------------------------------------------ + +func parseRss1Image(el map[string]any) *Rss1Image { + img := &Rss1Image{ + Title: textOf(findChild(el, "title")), + Link: textOf(findChild(el, "link")), + URL: textOf(findChild(el, "url")), + } + if v, ok := attribute(el, "rdf:about"); ok { + img.About = v + } + return img +} + +func parseRss1TextInput(el map[string]any) *Rss1TextInput { + ti := &Rss1TextInput{ + Title: textOf(findChild(el, "title")), + Description: textOf(findChild(el, "description")), + Name: textOf(findChild(el, "name")), + Link: textOf(findChild(el, "link")), + } + if v, ok := attribute(el, "rdf:about"); ok { + ti.About = v + } + return ti +} + +func parseRss1Item(el map[string]any) Rss1Item { + item := Rss1Item{ + Title: textOf(findChild(el, "title")), + Link: textOf(findChild(el, "link")), + } + if v, ok := attribute(el, "rdf:about"); ok { + item.About = v + } + if d := findChild(el, "description"); d != nil { + item.Description = textOf(d) + } + return item +} + +func parseRss1(root map[string]any, version string) Rss1Feed { + channel := findChild(root, "channel") + feed := Rss1Feed{ + Format: "rdf", + Version: "1.0", + Title: textOf(findChild(channel, "title")), + Link: textOf(findChild(channel, "link")), + Items: []Rss1Item{}, + } + if version == "rss090" { + feed.Version = "0.90" + } + if channel != nil { + if v, ok := attribute(channel, "rdf:about"); ok { + feed.About = v + } + if d := findChild(channel, "description"); d != nil { + feed.Description = textOf(d) + } + } + if i := findChild(root, "image"); i != nil { + feed.Image = parseRss1Image(i) + } + ti := findChild(root, "textinput") + if ti == nil { + ti = findChild(root, "textInput") + } + if ti != nil { + feed.TextInput = parseRss1TextInput(ti) + } + for _, item := range findChildren(root, "item") { + feed.Items = append(feed.Items, parseRss1Item(item)) + } + return feed +} + +// --- Native -> Atom conversions ------------------------------------------- + +var rssAuthorRe = regexp.MustCompile(`^\s*([^\s()]+@\S+)\s*(?:\(([^)]+)\))?\s*$`) + +func parseRssPerson(s string) AtomPerson { + m := rssAuthorRe.FindStringSubmatch(s) + if m == nil { + return AtomPerson{Name: strings.TrimSpace(s)} + } + name := m[2] + if name == "" { + name = m[1] + } + return AtomPerson{Name: name, Email: m[1]} +} + +func rss2ToAtom(rss Rss2Feed) AtomFeed { + out := AtomFeed{Format: "atom", Version: "1.0", Entries: []AtomEntry{}} + if rss.Title != "" { + out.Title = &AtomText{Type: "text", Value: rss.Title} + } + if rss.Description != "" { + out.Subtitle = &AtomText{Type: "text", Value: rss.Description} + } + if rss.Copyright != "" { + out.Rights = &AtomText{Type: "text", Value: rss.Copyright} + } + if rss.Link != "" { + out.ID = rss.Link + } + if rss.LastBuildDate != "" { + out.Updated = rss.LastBuildDate + } else if rss.PubDate != "" { + out.Updated = rss.PubDate + } + if rss.Generator != "" { + out.Generator = &AtomGenerator{Value: rss.Generator} + } + if rss.Image != nil && rss.Image.URL != "" { + out.Logo = rss.Image.URL + } + if rss.Link != "" { + out.Links = []AtomLink{{Href: rss.Link, Rel: "alternate"}} + } + if len(rss.Categories) > 0 { + out.Categories = make([]AtomCategory, 0, len(rss.Categories)) + for _, c := range rss.Categories { + out.Categories = append(out.Categories, AtomCategory{Term: c.Value, Scheme: c.Domain}) + } + } + if rss.ManagingEditor != "" || rss.WebMaster != "" { + me := rss.ManagingEditor + if me == "" { + me = rss.WebMaster + } + out.Authors = []AtomPerson{parseRssPerson(me)} + } + for _, item := range rss.Items { + out.Entries = append(out.Entries, rss2ItemToAtomEntry(item)) + } + return out +} + +func rss2ItemToAtomEntry(item Rss2Item) AtomEntry { + entry := AtomEntry{} + if item.Title != "" { + entry.Title = &AtomText{Type: "text", Value: item.Title} + } + if item.Description != "" { + entry.Summary = &AtomText{Type: "html", Value: item.Description} + } + if item.PubDate != "" { + entry.Published = item.PubDate + entry.Updated = item.PubDate + } + if item.Guid != nil { + entry.ID = item.Guid.Value + } else if item.Link != "" { + entry.ID = item.Link + } + links := []AtomLink{} + if item.Link != "" { + links = append(links, AtomLink{Href: item.Link, Rel: "alternate"}) + } + if item.Enclosure != nil && item.Enclosure.URL != "" { + l := AtomLink{Href: item.Enclosure.URL, Rel: "enclosure"} + if item.Enclosure.Type != "" { + l.Type = item.Enclosure.Type + } + if item.Enclosure.Length > 0 { + l.Length = item.Enclosure.Length + } + links = append(links, l) + } + if item.Comments != "" { + links = append(links, AtomLink{Href: item.Comments, Rel: "replies", Type: "text/html"}) + } + if len(links) > 0 { + entry.Links = links + } + if item.Author != "" { + entry.Authors = []AtomPerson{parseRssPerson(item.Author)} + } + if len(item.Categories) > 0 { + entry.Categories = make([]AtomCategory, 0, len(item.Categories)) + for _, c := range item.Categories { + entry.Categories = append(entry.Categories, AtomCategory{Term: c.Value, Scheme: c.Domain}) + } + } + if item.Source != nil { + src := &AtomEntrySource{Format: "atom", Version: "1.0"} + if item.Source.Value != "" { + src.Title = &AtomText{Type: "text", Value: item.Source.Value} + } + if item.Source.URL != "" { + src.Links = []AtomLink{{Href: item.Source.URL, Rel: "self"}} + } + entry.Source = src + } + return entry +} + +func rss1ToAtom(rss Rss1Feed) AtomFeed { + out := AtomFeed{Format: "atom", Version: "1.0", Entries: []AtomEntry{}} + if rss.Title != "" { + out.Title = &AtomText{Type: "text", Value: rss.Title} + } + if rss.Description != "" { + out.Subtitle = &AtomText{Type: "text", Value: rss.Description} + } + switch { + case rss.About != "": + out.ID = rss.About + case rss.Link != "": + out.ID = rss.Link + } + if rss.Link != "" { + out.Links = []AtomLink{{Href: rss.Link, Rel: "alternate"}} + } + if rss.Image != nil && rss.Image.URL != "" { + out.Logo = rss.Image.URL + } + for _, it := range rss.Items { + e := AtomEntry{} + if it.Title != "" { + e.Title = &AtomText{Type: "text", Value: it.Title} + } + if it.Description != "" { + e.Summary = &AtomText{Type: "text", Value: it.Description} + } + switch { + case it.About != "": + e.ID = it.About + case it.Link != "": + e.ID = it.Link + } + if it.Link != "" { + e.Links = []AtomLink{{Href: it.Link, Rel: "alternate"}} + } + out.Entries = append(out.Entries, e) + } + return out +} + +// --- Top-level convert ---------------------------------------------------- + +// Convert turns a parsed XML element tree (as produced by +// github.com/jsonicjs/xml/go) into the requested feed shape. +func Convert(root any, format string) (any, error) { + if format == "raw" { + return root, nil + } + el, ok := asElement(root) + if !ok { + return nil, fmt.Errorf("feed: input did not parse to an XML element") + } + d := Detect(el) + if d.Dialect == "unknown" { + return nil, fmt.Errorf( + "feed: unrecognized root element %q; expected one of feed, rss, RDF", + localName(el), + ) + } + + var native any + switch d.Dialect { + case "atom": + native = parseAtom(el, d.Version == "atom03") + case "rss": + native = parseRss2(el, d.Version) + case "rdf": + native = parseRss1(el, d.Version) + } + + if format == "native" { + return native, nil + } + + // Atom (default). + switch n := native.(type) { + case AtomFeed: + return n, nil + case Rss2Feed: + return rss2ToAtom(n), nil + case Rss1Feed: + return rss1ToAtom(n), nil + } + return nil, fmt.Errorf("feed: internal: unhandled native type") +} + +// --- jsonic Plugin -------------------------------------------------------- + +// Feed is the Jsonic plugin entry point. Register via: +// +// j := jsonic.Make() +// j.UseDefaults(feed.Feed, feed.Defaults) +// result, err := j.Parse(rssOrAtomSource) +// +// The result is an AtomFeed (default), an Rss2Feed / Rss1Feed +// (when "format" is "native"), or the raw map[string]any XML element +// tree (when "format" is "raw"). +func Feed(j *jsonic.Jsonic, options map[string]any) error { + if j.Decoration("feed-init") != nil { + return nil + } + j.Decorate("feed-init", true) + + if err := j.UseDefaults(xml.Xml, xml.Defaults); err != nil { + return fmt.Errorf("feed: setup xml: %w", err) + } + + format, _ := options["format"].(string) + if format == "" { + format = "atom" + } + + j.Rule("xml", func(rs *jsonic.RuleSpec, _ *jsonic.Parser) { + rs.AddBC(func(r *jsonic.Rule, ctx *jsonic.Context) { + // The xml rule's bc may run multiple times when there is + // trailing whitespace after the root element. Only convert + // the first time, when r.Node is still the raw XmlElement + // map produced by @xml-bc. + if r.Node == nil { + return + } + if _, ok := asElement(r.Node); !ok { + return + } + out, err := Convert(r.Node, format) + if err != nil { + ctx.ParseErr = &jsonic.Token{ + Name: "#BD", Tin: jsonic.TinBD, + Err: err.Error(), Why: err.Error(), Src: err.Error(), + } + return + } + r.Node = out + if ctx.Root != nil { + ctx.Root.Node = out + } + }) + }) + + return nil +} diff --git a/go/feed_test.go b/go/feed_test.go new file mode 100644 index 0000000..486ea5d --- /dev/null +++ b/go/feed_test.go @@ -0,0 +1,448 @@ +// Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License + +package feed_test + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "reflect" + "sort" + "strings" + "testing" + + jsonic "github.com/jsonicjs/jsonic/go" + feed "github.com/jsonicjs/feed/go" + xml "github.com/jsonicjs/xml/go" +) + +// specsDir resolves test/specs from the package directory. +func specsDir(t *testing.T) string { + t.Helper() + wd, err := os.Getwd() + if err != nil { + t.Fatalf("getwd: %v", err) + } + // go/ -> repo root + return filepath.Join(wd, "..", "test", "specs") +} + +// wellformedDir resolves test/feedparser-wellformed. +func wellformedDir(t *testing.T) string { + t.Helper() + wd, err := os.Getwd() + if err != nil { + t.Fatalf("getwd: %v", err) + } + return filepath.Join(wd, "..", "test", "feedparser-wellformed") +} + +// readJSON loads and parses a JSON file into an `any`. Used to canonicalise +// expected and actual structures so deep-equal compares them by shape, not +// by Go-typed-vs-decoded details. +func readJSON(t *testing.T, path string) any { + t.Helper() + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read %s: %v", path, err) + } + var v any + if err := json.Unmarshal(data, &v); err != nil { + t.Fatalf("parse %s: %v", path, err) + } + return v +} + +// canon marshals a Go value via JSON and unmarshals it back to `any` so +// it has the same shape as readJSON output. This collapses pointers, +// custom struct tags, and integer-vs-float-64 differences. +func canon(t *testing.T, v any) any { + t.Helper() + data, err := json.Marshal(v) + if err != nil { + t.Fatalf("marshal: %v", err) + } + var out any + if err := json.Unmarshal(data, &out); err != nil { + t.Fatalf("unmarshal: %v", err) + } + return out +} + +// buildParser returns a Jsonic instance with the Feed plugin in the +// requested format mode. +func buildParser(t *testing.T, format string) *jsonic.Jsonic { + t.Helper() + j := jsonic.Make() + opts := map[string]any{} + if format != "" { + opts["format"] = format + } + if err := j.UseDefaults(feed.Feed, feed.Defaults, opts); err != nil { + t.Fatalf("plugin init: %v", err) + } + return j +} + +// listSpecs returns base names (without extension) of all .xml fixtures +// in test/specs/. +func listSpecs(t *testing.T) []string { + t.Helper() + dir := specsDir(t) + entries, err := os.ReadDir(dir) + if err != nil { + t.Fatalf("read specs dir %s: %v", dir, err) + } + var names []string + for _, e := range entries { + if e.IsDir() { + continue + } + n := e.Name() + if strings.HasSuffix(n, ".xml") { + names = append(names, strings.TrimSuffix(n, ".xml")) + } + } + sort.Strings(names) + return names +} + + +func TestSpecsDetect(t *testing.T) { + names := listSpecs(t) + if len(names) == 0 { + t.Fatalf("no specs found") + } + rawParse := buildParser(t, "raw") + for _, name := range names { + name := name + t.Run(name, func(t *testing.T) { + expectPath := filepath.Join(specsDir(t), name+".detect.json") + if _, err := os.Stat(expectPath); err != nil { + t.Skipf("no .detect.json for %s", name) + } + src, err := os.ReadFile(filepath.Join(specsDir(t), name+".xml")) + if err != nil { + t.Fatalf("read xml: %v", err) + } + root, err := rawParse.Parse(string(src)) + if err != nil { + t.Fatalf("parse xml: %v", err) + } + got := feed.Detect(root) + want := readJSON(t, expectPath) + gotJSON := canon(t, got) + if !reflect.DeepEqual(gotJSON, want) { + t.Fatalf("detect mismatch:\n got: %v\n want: %v", gotJSON, want) + } + }) + } +} + +func TestSpecsAtom(t *testing.T) { + names := listSpecs(t) + atomParse := buildParser(t, "atom") + for _, name := range names { + name := name + t.Run(name, func(t *testing.T) { + expectPath := filepath.Join(specsDir(t), name+".atom.json") + if _, err := os.Stat(expectPath); err != nil { + t.Skipf("no .atom.json for %s", name) + } + src, err := os.ReadFile(filepath.Join(specsDir(t), name+".xml")) + if err != nil { + t.Fatalf("read xml: %v", err) + } + got, err := atomParse.Parse(string(src)) + if err != nil { + t.Fatalf("parse: %v", err) + } + gotJSON := canon(t, got) + want := readJSON(t, expectPath) + if !reflect.DeepEqual(gotJSON, want) { + gj, _ := json.MarshalIndent(gotJSON, "", " ") + wj, _ := json.MarshalIndent(want, "", " ") + t.Fatalf("atom mismatch for %s:\n--- got ---\n%s\n--- want ---\n%s", name, gj, wj) + } + }) + } +} + +func TestSpecsNative(t *testing.T) { + names := listSpecs(t) + nativeParse := buildParser(t, "native") + for _, name := range names { + name := name + t.Run(name, func(t *testing.T) { + expectPath := filepath.Join(specsDir(t), name+".native.json") + if _, err := os.Stat(expectPath); err != nil { + t.Skipf("no .native.json for %s", name) + } + src, err := os.ReadFile(filepath.Join(specsDir(t), name+".xml")) + if err != nil { + t.Fatalf("read xml: %v", err) + } + got, err := nativeParse.Parse(string(src)) + if err != nil { + t.Fatalf("parse: %v", err) + } + gotJSON := canon(t, got) + want := readJSON(t, expectPath) + if !reflect.DeepEqual(gotJSON, want) { + gj, _ := json.MarshalIndent(gotJSON, "", " ") + wj, _ := json.MarshalIndent(want, "", " ") + t.Fatalf("native mismatch for %s:\n--- got ---\n%s\n--- want ---\n%s", name, gj, wj) + } + }) + } +} + + +// --- feedparser-wellformed corpus ----------------------------------------- + +func corpusFiles(t *testing.T, sub string) []string { + t.Helper() + dir := filepath.Join(wellformedDir(t), sub) + entries, err := os.ReadDir(dir) + if err != nil { + t.Fatalf("read %s: %v", dir, err) + } + var out []string + for _, e := range entries { + if !e.IsDir() && strings.HasSuffix(e.Name(), ".xml") { + out = append(out, filepath.Join(dir, e.Name())) + } + } + sort.Strings(out) + return out +} + +type expected struct { + dialect string + versions []string +} + +var corpusExpect = map[string]expected{ + "atom10": {dialect: "atom", versions: []string{"atom10"}}, + "atom": {dialect: "atom", versions: []string{"atom03"}}, + "rss": {dialect: "rss", versions: []string{"rss20", "rss092", "rss091u", "rss091n"}}, + "rdf": {dialect: "rdf", versions: []string{"rss10", "rss090"}}, +} + +func TestCorpusDetect(t *testing.T) { + if _, err := os.Stat(wellformedDir(t)); err != nil { + t.Skip("feedparser-wellformed not vendored") + } + // Build a raw-format parser by registering the xml plugin directly; + // we don't need feed conversion to call Detect. + j := jsonic.Make() + if err := j.UseDefaults(xml.Xml, xml.Defaults); err != nil { + t.Fatalf("xml plugin: %v", err) + } + + for sub, expect := range corpusExpect { + sub, expect := sub, expect + t.Run(sub, func(t *testing.T) { + var fails []string + for _, path := range corpusFiles(t, sub) { + src, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read %s: %v", path, err) + } + root, err := j.Parse(string(src)) + if err != nil { + fails = append(fails, fmt.Sprintf("%s: parse err %v", filepath.Base(path), err)) + continue + } + got := feed.Detect(root) + if got.Dialect != expect.dialect { + fails = append(fails, fmt.Sprintf("%s: dialect=%s", filepath.Base(path), got.Dialect)) + continue + } + if !contains(expect.versions, got.Version) { + fails = append(fails, fmt.Sprintf("%s: version=%s", filepath.Base(path), got.Version)) + } + } + if len(fails) > 0 { + t.Fatalf("%s detection failures:\n %s", sub, strings.Join(fails, "\n ")) + } + }) + } +} + +func TestCorpusParseAtom(t *testing.T) { + if _, err := os.Stat(wellformedDir(t)); err != nil { + t.Skip("feedparser-wellformed not vendored") + } + atomParse := buildParser(t, "atom") + for sub := range corpusExpect { + sub := sub + t.Run(sub, func(t *testing.T) { + var fails []string + for _, path := range corpusFiles(t, sub) { + src, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read %s: %v", path, err) + } + got, err := atomParse.Parse(string(src)) + if err != nil { + fails = append(fails, fmt.Sprintf("%s: %v", filepath.Base(path), err)) + continue + } + if af, ok := got.(feed.AtomFeed); !ok || af.Format != "atom" { + fails = append(fails, fmt.Sprintf("%s: bad shape %T", filepath.Base(path), got)) + } + } + if len(fails) > 0 { + t.Fatalf("%s parse failures:\n %s", sub, strings.Join(fails, "\n ")) + } + }) + } +} + + +// --- targeted value checks (from feedparser comments) --------------------- + +func TestCorpusTargets(t *testing.T) { + if _, err := os.Stat(wellformedDir(t)); err != nil { + t.Skip("feedparser-wellformed not vendored") + } + atomParse := buildParser(t, "atom") + + cases := []struct { + path string + check func(t *testing.T, f feed.AtomFeed) + }{ + {"atom10/entry_title.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Title == nil || f.Entries[0].Title.Value != "Example Atom" { + t.Fatalf("got %+v", f.Entries[0].Title) + } + }}, + {"atom10/entry_author_email.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Authors[0].Email != "me@example.com" { + t.Fatalf("got %q", f.Entries[0].Authors[0].Email) + } + }}, + {"atom10/entry_author_name.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Authors[0].Name != "Example author" { + t.Fatalf("got %q", f.Entries[0].Authors[0].Name) + } + }}, + {"atom10/entry_id.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].ID == "" { + t.Fatalf("id missing") + } + }}, + {"atom10/entry_link_href.xml", func(t *testing.T, f feed.AtomFeed) { + if len(f.Entries[0].Links) == 0 || f.Entries[0].Links[0].Href == "" { + t.Fatalf("link missing") + } + }}, + {"atom/entry_title.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Title == nil || f.Entries[0].Title.Value == "" { + t.Fatalf("title missing") + } + }}, + {"atom/entry_issued.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Published == "" { + t.Fatalf("published missing") + } + }}, + {"atom/entry_modified.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Updated == "" { + t.Fatalf("updated missing") + } + }}, + {"rss/channel_title.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Title == nil || f.Title.Value != "Example feed" { + t.Fatalf("got %+v", f.Title) + } + }}, + {"rss/item_title.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Title == nil || f.Entries[0].Title.Value != "Item 1 title" { + t.Fatalf("got %+v", f.Entries[0].Title) + } + }}, + {"rss/item_link.xml", func(t *testing.T, f feed.AtomFeed) { + if len(f.Entries[0].Links) == 0 { + t.Fatalf("links missing") + } + }}, + {"rss/item_guid.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].ID == "" { + t.Fatalf("id missing") + } + }}, + {"rss/item_enclosure_url.xml", func(t *testing.T, f feed.AtomFeed) { + var found bool + for _, l := range f.Entries[0].Links { + if l.Rel == "enclosure" { + found = true + break + } + } + if !found { + t.Fatalf("enclosure link missing") + } + }}, + {"rdf/rdf_channel_title.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Title == nil || f.Title.Value != "Example feed" { + t.Fatalf("got %+v", f.Title) + } + }}, + {"rdf/rdf_item_title.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].Title == nil || f.Entries[0].Title.Value != "Example title" { + t.Fatalf("got %+v", f.Entries[0].Title) + } + }}, + {"rdf/rss090_channel_title.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Title == nil || f.Title.Value != "Example title" { + t.Fatalf("got %+v", f.Title) + } + }}, + {"rdf/rdf_item_rdf_about.xml", func(t *testing.T, f feed.AtomFeed) { + if f.Entries[0].ID != "http://example.org/1" { + t.Fatalf("got %q", f.Entries[0].ID) + } + }}, + } + + for _, c := range cases { + c := c + t.Run(c.path, func(t *testing.T) { + full := filepath.Join(wellformedDir(t), c.path) + src, err := os.ReadFile(full) + if err != nil { + t.Fatalf("read %s: %v", full, err) + } + got, err := atomParse.Parse(string(src)) + if err != nil { + t.Fatalf("parse: %v", err) + } + af, ok := got.(feed.AtomFeed) + if !ok { + t.Fatalf("expected AtomFeed, got %T", got) + } + c.check(t, af) + }) + } +} + + +func TestErrorOnUnknownRoot(t *testing.T) { + atomParse := buildParser(t, "atom") + _, err := atomParse.Parse(``) + if err == nil { + t.Fatalf("expected error on unknown root") + } +} + +func contains(ss []string, s string) bool { + for _, x := range ss { + if x == s { + return true + } + } + return false +} diff --git a/go/go.mod b/go/go.mod new file mode 100644 index 0000000..b0a6118 --- /dev/null +++ b/go/go.mod @@ -0,0 +1,8 @@ +module github.com/jsonicjs/feed/go + +go 1.24.7 + +require ( + github.com/jsonicjs/jsonic/go v0.1.22 + github.com/jsonicjs/xml/go v0.1.1 +) diff --git a/go/go.sum b/go/go.sum new file mode 100644 index 0000000..b7e278a --- /dev/null +++ b/go/go.sum @@ -0,0 +1,4 @@ +github.com/jsonicjs/jsonic/go v0.1.22 h1:sam238fTyjDq0nby9TYS+aCCHprLl91ArQPWLCg2O0Y= +github.com/jsonicjs/jsonic/go v0.1.22/go.mod h1:ObNKlCG7esWoi4AHCpdgkILvPINV8bpvkbCd4llGGUg= +github.com/jsonicjs/xml/go v0.1.1 h1:FFyDshu9fLB5oBVr/I6aTE3bogXE69DcfvS2L+c9gtw= +github.com/jsonicjs/xml/go v0.1.1/go.mod h1:+B5uBsX9kWgD3sFr4/iqMhw5vcmBDt8W741ugBY639k= diff --git a/test/feed.test.ts b/test/feed.test.ts index 8d55b69..572b535 100644 --- a/test/feed.test.ts +++ b/test/feed.test.ts @@ -1,416 +1,64 @@ /* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */ +// TS-only behaviour checks: error paths, the `raw` output mode, and the +// shape of the plugin registration. The bulk of dialect-by-dialect +// expectations lives in test/specs/ (driven by both this language and +// the Go test suite). + import { test, describe } from 'node:test' import assert from 'node:assert' import { Jsonic } from 'jsonic' import { Feed, detect } from '../dist/feed.js' -import type { - AtomFeed, - Rss1Feed, - Rss2Feed, -} from '../dist/feed.js' - - -// Sample feeds. The Atom 1.0 sample is the canonical example from RFC 4287 -// section 1.1. The RSS 2.0 / 0.91 / RDF samples are minimal hand-written -// fixtures that exercise the elements each parser cares about. - -const ATOM_10 = ` - - Example Feed - A subtitle. - - - 2003-12-13T18:30:02Z - - John Doe - johndoe@example.com - - urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 - (c) 2003 John Doe - Example Toolkit - - - Atom-Powered Robots Run Amok - - - urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a - 2003-12-13T18:30:02Z - 2003-12-13T08:29:29-04:00 - Some text. - <p>hi</p> - - -` - -const ATOM_03 = ` - - Example 0.3 Feed - An older feed - - 2003-12-13T18:30:02Z - Jane - tag:example.org,2003:1 - - Old Entry - - tag:example.org,2003:2 - 2003-12-13T08:29:29-04:00 - 2003-12-13T18:30:02Z - -` - -const RSS_20 = ` - - - RSS 2 Sample - http://example.com/ - RSS 2.0 description - en-us - Wed, 13 Dec 2003 18:30:02 GMT - Wed, 13 Dec 2003 19:30:02 GMT - editor@example.com (Edna Editor) - my generator - News - 60 - - http://example.com/logo.png - Logo - http://example.com/ - 96 - 32 - - 023 - Sunday - - RSS Item 1 - http://example.com/1 - Item one body - j@example.com (Jane Doe) - cats - birds - http://example.com/1#comments - - item-1-guid - Wed, 13 Dec 2003 18:30:02 GMT - Source name - - - RSS Item 2 - http://example.com/2 - - -` - -const RSS_091 = ` - - - RSS 0.91 - http://example.com/ - An old feed - en-us - - Item - http://example.com/i1 - Body - - -` - -const RSS_092 = ` - - - RSS 0.92 - http://example.com/ - 0.92 feed - - Item - - - -` - -const RSS_10 = ` - - - RSS 1.0 Example - http://example.org/ - An RDF-based feed - - - - - - - - Item One - http://example.org/items/1 - Item one - -` +import type { AtomFeed } from '../dist/feed.js' -const RSS_090 = ` - - - RSS 0.90 - http://example.org/ - old - - - Item - http://example.org/1 - -` - - -// Build an atom-output parser once and reuse it for the bulk of the tests. -const atomParse = Jsonic.make().use(Feed) -const nativeParse = Jsonic.make().use(Feed, { format: 'native' }) -const rawParse = Jsonic.make().use(Feed, { format: 'raw' }) - - -describe('feed - format detection', () => { - // Detection runs against the raw XmlElement tree. The `raw` parser gives - // us that tree without further conversion. - test('detect atom 1.0', () => { - const root: any = rawParse(ATOM_10) - assert.deepEqual(detect(root), { dialect: 'atom', version: 'atom10' }) - }) - - test('detect atom 0.3', () => { - const root: any = rawParse(ATOM_03) - assert.deepEqual(detect(root), { dialect: 'atom', version: 'atom03' }) - }) - - test('detect rss 2.0', () => { - const root: any = rawParse(RSS_20) - assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss20' }) - }) - test('detect rss 0.92', () => { - const root: any = rawParse(RSS_092) - assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss092' }) +describe('feed - errors', () => { + test('unrecognized root element throws', () => { + const j = Jsonic.make().use(Feed) + assert.throws(() => j(''), /unrecognized root/) }) +}) - test('detect rss 0.91', () => { - const root: any = rawParse(RSS_091) - assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss091u' }) - }) - test('detect rss 1.0 (rdf)', () => { - const root: any = rawParse(RSS_10) - assert.deepEqual(detect(root), { dialect: 'rdf', version: 'rss10' }) +describe('feed - raw format', () => { + test('returns the underlying XmlElement tree', () => { + const j = Jsonic.make().use(Feed, { format: 'raw' }) + const root: any = j('Hi') + assert.equal(root.localName, 'feed') + assert.equal(root.namespace, 'http://www.w3.org/2005/Atom') + assert.ok(Array.isArray(root.children)) }) - test('detect rss 0.90 (rdf)', () => { - const root: any = rawParse(RSS_090) - assert.deepEqual(detect(root), { dialect: 'rdf', version: 'rss090' }) + test('detect on raw output identifies the dialect', () => { + const j = Jsonic.make().use(Feed, { format: 'raw' }) + const root: any = j('x') + assert.deepEqual(detect(root), { dialect: 'rss', version: 'rss20' }) }) }) -describe('feed - default Atom output', () => { - test('atom 1.0 round-trips through Atom output', () => { - const f = atomParse(ATOM_10) as AtomFeed +describe('feed - plugin form', () => { + test('default is atom', () => { + const j = Jsonic.make().use(Feed) + const f = j('') as AtomFeed assert.equal(f.format, 'atom') assert.equal(f.version, '1.0') - assert.equal(f.id, 'urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6') - assert.deepEqual(f.title, { type: 'text', value: 'Example Feed' }) - assert.deepEqual(f.subtitle, { type: 'text', value: 'A subtitle.' }) - assert.equal(f.updated, '2003-12-13T18:30:02Z') - assert.equal(f.authors?.[0].name, 'John Doe') - assert.equal(f.authors?.[0].email, 'johndoe@example.com') - assert.deepEqual(f.rights, { type: 'text', value: '(c) 2003 John Doe' }) - assert.equal(f.generator?.value, 'Example Toolkit') - assert.equal(f.generator?.version, '1.2') - assert.equal(f.categories?.[0].term, 'news') - assert.equal(f.links?.length, 2) - assert.equal(f.links?.[0].rel, 'self') - - const e = f.entries[0] - assert.equal(e.id, 'urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a') - assert.deepEqual(e.title, { type: 'text', value: 'Atom-Powered Robots Run Amok' }) - assert.equal(e.updated, '2003-12-13T18:30:02Z') - assert.equal(e.published, '2003-12-13T08:29:29-04:00') - assert.deepEqual(e.summary, { type: 'text', value: 'Some text.' }) - assert.equal(e.content?.type, 'html') - assert.equal(e.content?.value, '

hi

') - assert.equal(e.categories?.[0].term, 'robots') - assert.equal(e.categories?.[0].label, 'Robots') - - const enclosure = e.links?.find((l) => l.rel === 'enclosure') - assert.equal(enclosure?.href, 'http://example.org/audio.mp3') - assert.equal(enclosure?.type, 'audio/mpeg') - assert.equal(enclosure?.length, 1337) - }) - - test('atom 0.3 maps tagline -> subtitle and modified -> updated', () => { - const f = atomParse(ATOM_03) as AtomFeed - assert.equal(f.format, 'atom') - assert.equal(f.version, '0.3') - assert.deepEqual(f.subtitle, { type: 'text', value: 'An older feed' }) - assert.equal(f.updated, '2003-12-13T18:30:02Z') - const e = f.entries[0] - assert.equal(e.published, '2003-12-13T08:29:29-04:00') - assert.equal(e.updated, '2003-12-13T18:30:02Z') - }) - - test('rss 2.0 converts to Atom shape', () => { - const f = atomParse(RSS_20) as AtomFeed - assert.equal(f.format, 'atom') - assert.deepEqual(f.title, { type: 'text', value: 'RSS 2 Sample' }) - assert.deepEqual(f.subtitle, { type: 'text', value: 'RSS 2.0 description' }) - assert.equal(f.id, 'http://example.com/') - // updated falls back from lastBuildDate - assert.equal(f.updated, 'Wed, 13 Dec 2003 19:30:02 GMT') - assert.equal(f.generator?.value, 'my generator') - assert.equal(f.logo, 'http://example.com/logo.png') - assert.equal(f.authors?.[0].email, 'editor@example.com') - assert.equal(f.authors?.[0].name, 'Edna Editor') - assert.equal(f.categories?.[0].term, 'News') - assert.equal(f.categories?.[0].scheme, 'cats') - - const e0 = f.entries[0] - assert.deepEqual(e0.title, { type: 'text', value: 'RSS Item 1' }) - assert.deepEqual(e0.summary, { type: 'html', value: 'Item one body' }) - assert.equal(e0.id, 'item-1-guid') // guid wins - assert.equal(e0.updated, 'Wed, 13 Dec 2003 18:30:02 GMT') - assert.equal(e0.published, 'Wed, 13 Dec 2003 18:30:02 GMT') - assert.equal(e0.authors?.[0].email, 'j@example.com') - assert.equal(e0.authors?.[0].name, 'Jane Doe') - assert.equal(e0.categories?.length, 2) - - const altLink = e0.links?.find((l) => l.rel === 'alternate') - assert.equal(altLink?.href, 'http://example.com/1') - const encLink = e0.links?.find((l) => l.rel === 'enclosure') - assert.equal(encLink?.href, 'http://example.com/1.mp3') - assert.equal(encLink?.length, 12345) - assert.equal(encLink?.type, 'audio/mpeg') - const reply = e0.links?.find((l) => l.rel === 'replies') - assert.equal(reply?.href, 'http://example.com/1#comments') - - // entry without guid falls back to link as id - const e1 = f.entries[1] - assert.equal(e1.id, 'http://example.com/2') - }) - - test('rss 0.92 / 0.91 convert to Atom', () => { - const f91 = atomParse(RSS_091) as AtomFeed - assert.equal(f91.format, 'atom') - assert.deepEqual(f91.title, { type: 'text', value: 'RSS 0.91' }) - assert.equal(f91.entries.length, 1) - - const f92 = atomParse(RSS_092) as AtomFeed - assert.equal(f92.format, 'atom') - assert.deepEqual(f92.title, { type: 'text', value: 'RSS 0.92' }) - assert.equal(f92.entries[0].links?.[0].rel, 'enclosure') - }) - - test('rss 1.0 (rdf) converts to Atom', () => { - const f = atomParse(RSS_10) as AtomFeed - assert.equal(f.format, 'atom') - assert.deepEqual(f.title, { type: 'text', value: 'RSS 1.0 Example' }) - assert.deepEqual(f.subtitle, { type: 'text', value: 'An RDF-based feed' }) - assert.equal(f.id, 'http://example.org/index.rdf') - assert.equal(f.entries.length, 1) - const e = f.entries[0] - assert.deepEqual(e.title, { type: 'text', value: 'Item One' }) - assert.deepEqual(e.summary, { type: 'text', value: 'Item one' }) - assert.equal(e.id, 'http://example.org/items/1') }) - test('rss 0.90 (rdf) converts to Atom', () => { - const f = atomParse(RSS_090) as AtomFeed - assert.equal(f.format, 'atom') - assert.deepEqual(f.title, { type: 'text', value: 'RSS 0.90' }) - assert.equal(f.entries.length, 1) - assert.deepEqual(f.entries[0].title, { type: 'text', value: 'Item' }) - }) -}) - - -describe('feed - native output', () => { - test('rss 2.0 native shape', () => { - const f = nativeParse(RSS_20) as Rss2Feed + test('format=native preserves the dialect shape', () => { + const j = Jsonic.make().use(Feed, { format: 'native' }) + const f: any = j('x') assert.equal(f.format, 'rss') assert.equal(f.version, '2.0') - assert.equal(f.title, 'RSS 2 Sample') - assert.equal(f.link, 'http://example.com/') - assert.equal(f.description, 'RSS 2.0 description') - assert.equal(f.language, 'en-us') - assert.equal(f.ttl, 60) - assert.equal(f.image?.url, 'http://example.com/logo.png') - assert.equal(f.image?.width, 96) - assert.deepEqual(f.skipHours, [0, 23]) - assert.deepEqual(f.skipDays, ['Sunday']) - assert.equal(f.items.length, 2) - const i0 = f.items[0] - assert.equal(i0.title, 'RSS Item 1') - assert.equal(i0.author, 'j@example.com (Jane Doe)') - assert.equal(i0.guid?.value, 'item-1-guid') - assert.equal(i0.guid?.isPermaLink, false) - assert.equal(i0.enclosure?.url, 'http://example.com/1.mp3') - assert.equal(i0.enclosure?.length, 12345) - assert.equal(i0.categories?.length, 2) - assert.equal(i0.categories?.[1].domain, 'd2') - assert.equal(i0.source?.url, 'http://example.com/source.xml') - assert.equal(i0.source?.value, 'Source name') }) - test('atom 1.0 native shape (already atom)', () => { - const f = nativeParse(ATOM_10) as AtomFeed + test('parse runs cleanly when the input has trailing whitespace', () => { + // bc on the xml rule fires twice in this case; the plugin must guard + // against re-converting the already-converted result. + const j = Jsonic.make().use(Feed) + const f = j('Hi\n \n') as AtomFeed assert.equal(f.format, 'atom') - assert.equal(f.version, '1.0') - assert.equal(f.entries.length, 1) - }) - - test('rss 1.0 native (rdf) shape', () => { - const f = nativeParse(RSS_10) as Rss1Feed - assert.equal(f.format, 'rdf') - assert.equal(f.version, '1.0') - assert.equal(f.about, 'http://example.org/index.rdf') - assert.equal(f.title, 'RSS 1.0 Example') - assert.equal(f.items.length, 1) - assert.equal(f.items[0].about, 'http://example.org/items/1') - }) -}) - - -describe('feed - raw output', () => { - test('returns the underlying XmlElement tree', () => { - const root: any = rawParse(ATOM_10) - assert.equal(root.localName, 'feed') - assert.equal(root.namespace, 'http://www.w3.org/2005/Atom') - assert.ok(Array.isArray(root.children)) - }) -}) - - -describe('feed - errors', () => { - test('unrecognized root element throws', () => { - assert.throws(() => atomParse(''), /unrecognized root/) - }) -}) - - -describe('feed - xhtml content', () => { - test('xhtml content extracts inner div body', () => { - const src = ` - - <div xmlns="http://www.w3.org/1999/xhtml">Hi <em>there</em></div> -

body here

-
-
` - const f = atomParse(src) as AtomFeed - const e = f.entries[0] - assert.equal(e.title?.type, 'xhtml') - assert.match(e.title?.value || '', /Hi there<\/em>/) - assert.equal(e.content?.type, 'xhtml') - assert.match(e.content?.value || '', /body here<\/b><\/p>/) + assert.equal(f.title?.value, 'Hi') }) }) diff --git a/test/specs.test.ts b/test/specs.test.ts new file mode 100644 index 0000000..d6f6d99 --- /dev/null +++ b/test/specs.test.ts @@ -0,0 +1,82 @@ +/* Copyright (c) 2021-2025 Richard Rodger and other contributors, MIT License */ + +// Drives the cross-language fixtures in test/specs/. Each fixture pairs a +// .xml input with one or more expected JSON outputs (.atom.json, +// .native.json, .detect.json) and is run by both this test file and +// go/feed_test.go. See test/specs/README.md. + +import { test, describe } from 'node:test' +import assert from 'node:assert' +import { readdirSync, readFileSync, existsSync } from 'node:fs' +import { join } from 'node:path' + +import { Jsonic } from 'jsonic' +import { Feed, detect } from '../dist/feed.js' + +const SPECS_DIR = join(__dirname, '..', 'test', 'specs') + +const atomParse = Jsonic.make().use(Feed) +const nativeParse = Jsonic.make().use(Feed, { format: 'native' }) +const rawParse = Jsonic.make().use(Feed, { format: 'raw' }) + +// canon JSON-roundtrips a value so deep-equal sees the same shape regardless +// of property ordering or class identity. +function canon(v: T): T { + return JSON.parse(JSON.stringify(v)) +} + +const specs = existsSync(SPECS_DIR) + ? readdirSync(SPECS_DIR) + .filter((f) => f.endsWith('.xml')) + .map((f) => f.replace(/\.xml$/, '')) + .sort() + : [] + + +describe('specs - dialect / version detection', () => { + if (specs.length === 0) { + test('no specs', () => { + console.warn(`no specs in ${SPECS_DIR}`) + }) + return + } + for (const name of specs) { + const detectPath = join(SPECS_DIR, name + '.detect.json') + if (!existsSync(detectPath)) continue + test(name, () => { + const src = readFileSync(join(SPECS_DIR, name + '.xml'), 'utf8') + const root: any = rawParse(src) + const got = detect(root) + const want = JSON.parse(readFileSync(detectPath, 'utf8')) + assert.deepEqual(canon(got), want) + }) + } +}) + + +describe('specs - atom (default) output', () => { + for (const name of specs) { + const expectedPath = join(SPECS_DIR, name + '.atom.json') + if (!existsSync(expectedPath)) continue + test(name, () => { + const src = readFileSync(join(SPECS_DIR, name + '.xml'), 'utf8') + const got = atomParse(src) + const want = JSON.parse(readFileSync(expectedPath, 'utf8')) + assert.deepEqual(canon(got), want) + }) + } +}) + + +describe('specs - native output', () => { + for (const name of specs) { + const expectedPath = join(SPECS_DIR, name + '.native.json') + if (!existsSync(expectedPath)) continue + test(name, () => { + const src = readFileSync(join(SPECS_DIR, name + '.xml'), 'utf8') + const got = nativeParse(src) + const want = JSON.parse(readFileSync(expectedPath, 'utf8')) + assert.deepEqual(canon(got), want) + }) + } +}) diff --git a/test/specs/README.md b/test/specs/README.md new file mode 100644 index 0000000..a6111af --- /dev/null +++ b/test/specs/README.md @@ -0,0 +1,20 @@ +# test/specs + +Cross-language test fixtures for `@jsonic/feed`. Each spec is a pair (or +triple) of files sharing a base name: + +``` +.xml # input feed XML +.atom.json # expected output for default ('atom') format +.native.json # optional: expected output for 'native' format +.detect.json # optional: expected { dialect, version } +``` + +Both the TypeScript and Go test suites enumerate this directory, parse +each `.xml` with the corresponding format option, and compare the +result to the expected JSON via structural deep-equal (after a +JSON marshal/unmarshal round-trip to normalise types and ordering). + +Add a new spec by dropping in the three files; both languages will +pick it up automatically. Keep the inputs minimal — exercises one +piece of behaviour each — so failures pinpoint a single mapping. diff --git a/test/specs/atom03-basic.atom.json b/test/specs/atom03-basic.atom.json new file mode 100644 index 0000000..de50f90 --- /dev/null +++ b/test/specs/atom03-basic.atom.json @@ -0,0 +1,25 @@ +{ + "format": "atom", + "version": "0.3", + "id": "tag:example.org,2003:1", + "title": { "type": "text", "value": "Example 0.3 Feed" }, + "updated": "2003-12-13T18:30:02Z", + "authors": [ + { "name": "Jane" } + ], + "subtitle": { "type": "text", "value": "An older feed" }, + "links": [ + { "href": "http://example.org/", "rel": "alternate", "type": "text/html" } + ], + "entries": [ + { + "id": "tag:example.org,2003:2", + "title": { "type": "text", "value": "Old Entry" }, + "updated": "2003-12-13T18:30:02Z", + "published": "2003-12-13T08:29:29-04:00", + "links": [ + { "href": "http://example.org/old", "rel": "alternate", "type": "text/html" } + ] + } + ] +} diff --git a/test/specs/atom03-basic.detect.json b/test/specs/atom03-basic.detect.json new file mode 100644 index 0000000..978af4b --- /dev/null +++ b/test/specs/atom03-basic.detect.json @@ -0,0 +1 @@ +{ "dialect": "atom", "version": "atom03" } diff --git a/test/specs/atom03-basic.xml b/test/specs/atom03-basic.xml new file mode 100644 index 0000000..be94e4b --- /dev/null +++ b/test/specs/atom03-basic.xml @@ -0,0 +1,16 @@ + + + Example 0.3 Feed + An older feed + + 2003-12-13T18:30:02Z + Jane + tag:example.org,2003:1 + + Old Entry + + tag:example.org,2003:2 + 2003-12-13T08:29:29-04:00 + 2003-12-13T18:30:02Z + + diff --git a/test/specs/atom10-rfc.atom.json b/test/specs/atom10-rfc.atom.json new file mode 100644 index 0000000..28756cf --- /dev/null +++ b/test/specs/atom10-rfc.atom.json @@ -0,0 +1,37 @@ +{ + "format": "atom", + "version": "1.0", + "id": "urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6", + "title": { "type": "text", "value": "Example Feed" }, + "updated": "2003-12-13T18:30:02Z", + "authors": [ + { "name": "John Doe", "email": "johndoe@example.com" } + ], + "categories": [ + { "term": "news" } + ], + "generator": { "uri": "https://example.org/g", "version": "1.2", "value": "Example Toolkit" }, + "rights": { "type": "text", "value": "(c) 2003 John Doe" }, + "subtitle": { "type": "text", "value": "A subtitle." }, + "links": [ + { "href": "http://example.org/feed/", "rel": "self" }, + { "href": "http://example.org/" } + ], + "entries": [ + { + "id": "urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a", + "title": { "type": "text", "value": "Atom-Powered Robots Run Amok" }, + "updated": "2003-12-13T18:30:02Z", + "published": "2003-12-13T08:29:29-04:00", + "categories": [ + { "term": "robots", "scheme": "http://example.org/cats", "label": "Robots" } + ], + "content": { "type": "html", "value": "

hi

" }, + "links": [ + { "href": "http://example.org/2003/12/13/atom03" }, + { "href": "http://example.org/audio.mp3", "rel": "enclosure", "type": "audio/mpeg", "length": 1337 } + ], + "summary": { "type": "text", "value": "Some text." } + } + ] +} diff --git a/test/specs/atom10-rfc.detect.json b/test/specs/atom10-rfc.detect.json new file mode 100644 index 0000000..f293a58 --- /dev/null +++ b/test/specs/atom10-rfc.detect.json @@ -0,0 +1 @@ +{ "dialect": "atom", "version": "atom10" } diff --git a/test/specs/atom10-rfc.xml b/test/specs/atom10-rfc.xml new file mode 100644 index 0000000..69c5229 --- /dev/null +++ b/test/specs/atom10-rfc.xml @@ -0,0 +1,27 @@ + + + Example Feed + A subtitle. + + + 2003-12-13T18:30:02Z + + John Doe + johndoe@example.com + + urn:uuid:60a76c80-d399-11d9-b93C-0003939e0af6 + (c) 2003 John Doe + Example Toolkit + + + Atom-Powered Robots Run Amok + + + urn:uuid:1225c695-cfb8-4ebb-aaaa-80da344efa6a + 2003-12-13T18:30:02Z + 2003-12-13T08:29:29-04:00 + Some text. + <p>hi</p> + + + diff --git a/test/specs/atom10-xhtml.atom.json b/test/specs/atom10-xhtml.atom.json new file mode 100644 index 0000000..cc14113 --- /dev/null +++ b/test/specs/atom10-xhtml.atom.json @@ -0,0 +1,10 @@ +{ + "format": "atom", + "version": "1.0", + "entries": [ + { + "title": { "type": "xhtml", "value": "Hi there" }, + "content": { "type": "xhtml", "value": "

body here

" } + } + ] +} diff --git a/test/specs/atom10-xhtml.detect.json b/test/specs/atom10-xhtml.detect.json new file mode 100644 index 0000000..f293a58 --- /dev/null +++ b/test/specs/atom10-xhtml.detect.json @@ -0,0 +1 @@ +{ "dialect": "atom", "version": "atom10" } diff --git a/test/specs/atom10-xhtml.xml b/test/specs/atom10-xhtml.xml new file mode 100644 index 0000000..0e409ff --- /dev/null +++ b/test/specs/atom10-xhtml.xml @@ -0,0 +1,6 @@ + + + <div xmlns="http://www.w3.org/1999/xhtml">Hi <em>there</em></div> +

body here

+
+
diff --git a/test/specs/rss090-basic.atom.json b/test/specs/rss090-basic.atom.json new file mode 100644 index 0000000..cba9076 --- /dev/null +++ b/test/specs/rss090-basic.atom.json @@ -0,0 +1,19 @@ +{ + "format": "atom", + "version": "1.0", + "id": "http://example.org/", + "title": { "type": "text", "value": "RSS 0.90" }, + "subtitle": { "type": "text", "value": "old" }, + "links": [ + { "href": "http://example.org/", "rel": "alternate" } + ], + "entries": [ + { + "id": "http://example.org/1", + "title": { "type": "text", "value": "Item" }, + "links": [ + { "href": "http://example.org/1", "rel": "alternate" } + ] + } + ] +} diff --git a/test/specs/rss090-basic.detect.json b/test/specs/rss090-basic.detect.json new file mode 100644 index 0000000..5c26283 --- /dev/null +++ b/test/specs/rss090-basic.detect.json @@ -0,0 +1 @@ +{ "dialect": "rdf", "version": "rss090" } diff --git a/test/specs/rss090-basic.xml b/test/specs/rss090-basic.xml new file mode 100644 index 0000000..1b45b35 --- /dev/null +++ b/test/specs/rss090-basic.xml @@ -0,0 +1,14 @@ + + + + RSS 0.90 + http://example.org/ + old + + + Item + http://example.org/1 + + diff --git a/test/specs/rss091-basic.atom.json b/test/specs/rss091-basic.atom.json new file mode 100644 index 0000000..a2ea489 --- /dev/null +++ b/test/specs/rss091-basic.atom.json @@ -0,0 +1,20 @@ +{ + "format": "atom", + "version": "1.0", + "id": "http://example.com/", + "title": { "type": "text", "value": "RSS 0.91" }, + "subtitle": { "type": "text", "value": "An old feed" }, + "links": [ + { "href": "http://example.com/", "rel": "alternate" } + ], + "entries": [ + { + "id": "http://example.com/i1", + "title": { "type": "text", "value": "Item" }, + "summary": { "type": "html", "value": "Body" }, + "links": [ + { "href": "http://example.com/i1", "rel": "alternate" } + ] + } + ] +} diff --git a/test/specs/rss091-basic.detect.json b/test/specs/rss091-basic.detect.json new file mode 100644 index 0000000..f1f8b01 --- /dev/null +++ b/test/specs/rss091-basic.detect.json @@ -0,0 +1 @@ +{ "dialect": "rss", "version": "rss091u" } diff --git a/test/specs/rss091-basic.xml b/test/specs/rss091-basic.xml new file mode 100644 index 0000000..bc29665 --- /dev/null +++ b/test/specs/rss091-basic.xml @@ -0,0 +1,14 @@ + + + + RSS 0.91 + http://example.com/ + An old feed + en-us + + Item + http://example.com/i1 + Body + + + diff --git a/test/specs/rss092-basic.atom.json b/test/specs/rss092-basic.atom.json new file mode 100644 index 0000000..9e08005 --- /dev/null +++ b/test/specs/rss092-basic.atom.json @@ -0,0 +1,18 @@ +{ + "format": "atom", + "version": "1.0", + "id": "http://example.com/", + "title": { "type": "text", "value": "RSS 0.92" }, + "subtitle": { "type": "text", "value": "0.92 feed" }, + "links": [ + { "href": "http://example.com/", "rel": "alternate" } + ], + "entries": [ + { + "title": { "type": "text", "value": "Item" }, + "links": [ + { "href": "http://example.com/x.mp3", "rel": "enclosure", "type": "audio/mpeg", "length": 100 } + ] + } + ] +} diff --git a/test/specs/rss092-basic.detect.json b/test/specs/rss092-basic.detect.json new file mode 100644 index 0000000..730830e --- /dev/null +++ b/test/specs/rss092-basic.detect.json @@ -0,0 +1 @@ +{ "dialect": "rss", "version": "rss092" } diff --git a/test/specs/rss092-basic.xml b/test/specs/rss092-basic.xml new file mode 100644 index 0000000..a42bcf6 --- /dev/null +++ b/test/specs/rss092-basic.xml @@ -0,0 +1,12 @@ + + + + RSS 0.92 + http://example.com/ + 0.92 feed + + Item + + + + diff --git a/test/specs/rss10-basic.atom.json b/test/specs/rss10-basic.atom.json new file mode 100644 index 0000000..d7c5402 --- /dev/null +++ b/test/specs/rss10-basic.atom.json @@ -0,0 +1,20 @@ +{ + "format": "atom", + "version": "1.0", + "id": "http://example.org/index.rdf", + "title": { "type": "text", "value": "RSS 1.0 Example" }, + "subtitle": { "type": "text", "value": "An RDF-based feed" }, + "links": [ + { "href": "http://example.org/", "rel": "alternate" } + ], + "entries": [ + { + "id": "http://example.org/items/1", + "title": { "type": "text", "value": "Item One" }, + "summary": { "type": "text", "value": "Item one" }, + "links": [ + { "href": "http://example.org/items/1", "rel": "alternate" } + ] + } + ] +} diff --git a/test/specs/rss10-basic.detect.json b/test/specs/rss10-basic.detect.json new file mode 100644 index 0000000..4345cdc --- /dev/null +++ b/test/specs/rss10-basic.detect.json @@ -0,0 +1 @@ +{ "dialect": "rdf", "version": "rss10" } diff --git a/test/specs/rss10-basic.native.json b/test/specs/rss10-basic.native.json new file mode 100644 index 0000000..ba9e94d --- /dev/null +++ b/test/specs/rss10-basic.native.json @@ -0,0 +1,16 @@ +{ + "format": "rdf", + "version": "1.0", + "about": "http://example.org/index.rdf", + "title": "RSS 1.0 Example", + "link": "http://example.org/", + "description": "An RDF-based feed", + "items": [ + { + "about": "http://example.org/items/1", + "title": "Item One", + "link": "http://example.org/items/1", + "description": "Item one" + } + ] +} diff --git a/test/specs/rss10-basic.xml b/test/specs/rss10-basic.xml new file mode 100644 index 0000000..61c19fa --- /dev/null +++ b/test/specs/rss10-basic.xml @@ -0,0 +1,20 @@ + + + + RSS 1.0 Example + http://example.org/ + An RDF-based feed + + + + + + + + Item One + http://example.org/items/1 + Item one + + diff --git a/test/specs/rss20-full.atom.json b/test/specs/rss20-full.atom.json new file mode 100644 index 0000000..bf15d44 --- /dev/null +++ b/test/specs/rss20-full.atom.json @@ -0,0 +1,55 @@ +{ + "format": "atom", + "version": "1.0", + "id": "http://example.com/", + "title": { "type": "text", "value": "RSS 2 Sample" }, + "updated": "Wed, 13 Dec 2003 19:30:02 GMT", + "authors": [ + { "name": "Edna Editor", "email": "editor@example.com" } + ], + "categories": [ + { "term": "News", "scheme": "cats" } + ], + "generator": { "value": "my generator" }, + "logo": "http://example.com/logo.png", + "subtitle": { "type": "text", "value": "RSS 2.0 description" }, + "links": [ + { "href": "http://example.com/", "rel": "alternate" } + ], + "entries": [ + { + "id": "item-1-guid", + "title": { "type": "text", "value": "RSS Item 1" }, + "updated": "Wed, 13 Dec 2003 18:30:02 GMT", + "published": "Wed, 13 Dec 2003 18:30:02 GMT", + "authors": [ + { "name": "Jane Doe", "email": "j@example.com" } + ], + "categories": [ + { "term": "cats" }, + { "term": "birds", "scheme": "d2" } + ], + "links": [ + { "href": "http://example.com/1", "rel": "alternate" }, + { "href": "http://example.com/1.mp3", "rel": "enclosure", "type": "audio/mpeg", "length": 12345 }, + { "href": "http://example.com/1#comments", "rel": "replies", "type": "text/html" } + ], + "summary": { "type": "html", "value": "Item one body" }, + "source": { + "format": "atom", + "version": "1.0", + "title": { "type": "text", "value": "Source name" }, + "links": [ + { "href": "http://example.com/source.xml", "rel": "self" } + ] + } + }, + { + "id": "http://example.com/2", + "title": { "type": "text", "value": "RSS Item 2" }, + "links": [ + { "href": "http://example.com/2", "rel": "alternate" } + ] + } + ] +} diff --git a/test/specs/rss20-full.detect.json b/test/specs/rss20-full.detect.json new file mode 100644 index 0000000..db5c8c2 --- /dev/null +++ b/test/specs/rss20-full.detect.json @@ -0,0 +1 @@ +{ "dialect": "rss", "version": "rss20" } diff --git a/test/specs/rss20-full.native.json b/test/specs/rss20-full.native.json new file mode 100644 index 0000000..fe0948f --- /dev/null +++ b/test/specs/rss20-full.native.json @@ -0,0 +1,50 @@ +{ + "format": "rss", + "version": "2.0", + "title": "RSS 2 Sample", + "link": "http://example.com/", + "description": "RSS 2.0 description", + "language": "en-us", + "pubDate": "Wed, 13 Dec 2003 18:30:02 GMT", + "lastBuildDate": "Wed, 13 Dec 2003 19:30:02 GMT", + "managingEditor": "editor@example.com (Edna Editor)", + "generator": "my generator", + "categories": [ + { "domain": "cats", "value": "News" } + ], + "ttl": 60, + "image": { + "url": "http://example.com/logo.png", + "title": "Logo", + "link": "http://example.com/", + "width": 96, + "height": 32 + }, + "skipHours": [0, 23], + "skipDays": ["Sunday"], + "items": [ + { + "title": "RSS Item 1", + "link": "http://example.com/1", + "description": "Item one body", + "author": "j@example.com (Jane Doe)", + "categories": [ + { "value": "cats" }, + { "domain": "d2", "value": "birds" } + ], + "comments": "http://example.com/1#comments", + "enclosure": { + "url": "http://example.com/1.mp3", + "length": 12345, + "type": "audio/mpeg" + }, + "guid": { "isPermaLink": false, "value": "item-1-guid" }, + "pubDate": "Wed, 13 Dec 2003 18:30:02 GMT", + "source": { "url": "http://example.com/source.xml", "value": "Source name" } + }, + { + "title": "RSS Item 2", + "link": "http://example.com/2" + } + ] +} diff --git a/test/specs/rss20-full.xml b/test/specs/rss20-full.xml new file mode 100644 index 0000000..c32832b --- /dev/null +++ b/test/specs/rss20-full.xml @@ -0,0 +1,41 @@ + + + + RSS 2 Sample + http://example.com/ + RSS 2.0 description + en-us + Wed, 13 Dec 2003 18:30:02 GMT + Wed, 13 Dec 2003 19:30:02 GMT + editor@example.com (Edna Editor) + my generator + News + 60 + + http://example.com/logo.png + Logo + http://example.com/ + 96 + 32 + + 023 + Sunday + + RSS Item 1 + http://example.com/1 + Item one body + j@example.com (Jane Doe) + cats + birds + http://example.com/1#comments + + item-1-guid + Wed, 13 Dec 2003 18:30:02 GMT + Source name + + + RSS Item 2 + http://example.com/2 + + + From 15530f3c83a0eba1316aa138ec6f89e6bd8b635d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 6 May 2026 13:00:12 +0000 Subject: [PATCH 4/4] Gate the xml-rule bc hook on r.child.node, mirroring @xml-bc The xml rule's bc fires once per close, including extra times when `r: xml` recurses to consume trailing whitespace after the root element. @jsonic/xml's own @xml-bc handles this idempotency by only acting when r.child.node is set (i.e. an element was just parsed in the current iteration). Mirror that idiom in our own bc hook so the guard expresses the actual condition rather than relying on the incidental fact that the previous iteration already replaced r.node. Behavior is unchanged; this is a clarity / robustness fix. --- go/feed.go | 13 +++++++------ src/feed.ts | 12 ++++++++---- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/go/feed.go b/go/feed.go index 0dfa0d4..13e1f81 100644 --- a/go/feed.go +++ b/go/feed.go @@ -1234,16 +1234,17 @@ func Feed(j *jsonic.Jsonic, options map[string]any) error { format = "atom" } + // The xml rule's bc fires once per close, including extra times when + // `r: xml` recurses to consume trailing whitespace. Mirror @xml-bc's + // own guard: only run when an element was actually parsed in *this* + // iteration (r.Child.Node is set), so the conversion happens exactly + // once on the same iteration that @xml-bc copied the element to root. j.Rule("xml", func(rs *jsonic.RuleSpec, _ *jsonic.Parser) { rs.AddBC(func(r *jsonic.Rule, ctx *jsonic.Context) { - // The xml rule's bc may run multiple times when there is - // trailing whitespace after the root element. Only convert - // the first time, when r.Node is still the raw XmlElement - // map produced by @xml-bc. - if r.Node == nil { + if r.Child == nil || r.Child == jsonic.NoRule || r.Child.Node == nil { return } - if _, ok := asElement(r.Node); !ok { + if r.Node == nil { return } out, err := Convert(r.Node, format) diff --git a/src/feed.ts b/src/feed.ts index 0a1f7c4..5595820 100644 --- a/src/feed.ts +++ b/src/feed.ts @@ -920,11 +920,15 @@ const Feed: Plugin = function Feed(jsonic, options) { jsonic.use(Xml) const opts = withDefaults(options as FeedOptions | undefined) - // After @xml-bc copies the parsed XmlElement tree onto ctx.root().node, - // transform it into the feed shape selected by `opts.format`. Appending - // a second bc action runs it after the XML plugin's own. + // The xml rule's bc fires once per close, including extra times when + // `r: xml` recurses to consume trailing whitespace. Mirror @xml-bc's + // own guard: only run when an element was actually parsed in *this* + // iteration (r.child.node is set), so the conversion happens exactly + // once on the same iteration that @xml-bc copied the element to root. jsonic.rule('xml', (rs) => { - rs.bc(true, (_rule, ctx) => { + rs.bc(true, (rule: any, ctx: any) => { + const child = rule.child + if (!child || !child.node) return const root = ctx.root() if (isElement(root.node)) { root.node = convert(root.node, opts)