From 3c8d08b45a2b3c7564d63b876de31d3173e55da2 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 4 Mar 2021 23:50:48 -0800 Subject: [PATCH 01/44] Test naming style. --- test/utility/neutrino_filter.cpp | 53 ++++++++++++++++---------------- test/wallet/witness_address.cpp | 14 ++++----- 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/test/utility/neutrino_filter.cpp b/test/utility/neutrino_filter.cpp index bf27708cc2..79c8af8f4f 100644 --- a/test/utility/neutrino_filter.cpp +++ b/test/utility/neutrino_filter.cpp @@ -117,7 +117,7 @@ BOOST_AUTO_TEST_SUITE(chain_neutrino_filter_tests) // } //} -BOOST_AUTO_TEST_CASE(compute_filter_header__get_headers__block_0__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_0__success) { const auto expected = hash_literal("21584579b7eb08997773e5aeff3a7f932700042d0ed2a6129012b7d7ae81b750"); const auto previous_header = hash_literal("0000000000000000000000000000000000000000000000000000000000000000"); @@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__get_headers__block_0__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_2__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_2__success) { const auto expected = hash_literal("186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0"); const auto previous_header = hash_literal("d7bdac13a59d745b1add0d2ce852f1a0442e8945fc1bf3848d3cbffd88c24fe1"); @@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_2__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_3__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_3__success) { const auto expected = hash_literal("8d63aadf5ab7257cb6d2316a57b16f517bff1c6388f124ec4c04af1212729d2a"); const auto previous_header = hash_literal("186afd11ef2b5e7e3504f2e8cbf8df28a1fd251fe53d60dff8b1467d1b386cf0"); @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_3__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_15007__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_15007__success) { const auto expected = hash_literal("07384b01311867949e0c046607c66b7a766d338474bb67f66c8ae9dbd454b20e"); const auto previous_header = hash_literal("18b5c2b0146d2d09d24fb00ff5b52bd0742f36c9e65527abdb9de30c027a4748"); @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_15007__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_49291__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_49291__success) { const auto expected = hash_literal("b6d98692cec5145f67585f3434ec3c2b3030182e1cb3ec58b855c5c164dfaaa3"); const auto previous_header = hash_literal("ed47705334f4643892ca46396eb3f4196a5e30880589e4009ef38eae895d4a13"); @@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_49291__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_180480__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_180480__success) { const auto expected = hash_literal("c582d51c0ca365e3fcf36c51cb646d7f83a67e867cb4743fd2128e3e022b700c"); const auto previous_header = hash_literal("d34ef98386f413769502808d4bac5f20f8dfd5bffc9eedafaa71de0eb1f01489"); @@ -171,7 +171,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_180480__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_926485__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_926485__success) { const auto expected = hash_literal("546c574a0472144bcaf9b6aeabf26372ad87c7af7d1ee0dbfae5e099abeae49c"); const auto previous_header = hash_literal("8f13b9a9c85611635b47906c3053ac53cfcec7211455d4cb0d63dc9acc13d472"); @@ -180,7 +180,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_926485__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_987876__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_987876__success) { const auto expected = hash_literal("0965a544743bbfa36f254446e75630c09404b3d164a261892372977538928ed5"); const auto previous_header = hash_literal("fe4d230dbb0f4fec9bed23a5283e08baf996e3f32b93f52c7de1f641ddfd04ad"); @@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_987876__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_1263442__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_1263442__success) { const auto expected = hash_literal("4e6d564c2a2452065c205dd7eb2791124e0c4e0dbb064c410c24968572589dec"); const auto previous_header = hash_literal("31d66d516a9eda7de865df29f6ef6cb8e4bf9309e5dac899968a9a62a5df61e3"); @@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_1263442__success) BOOST_REQUIRE_EQUAL(result, expected); } -BOOST_AUTO_TEST_CASE(compute_filter_header__block_1414221__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter_header__block_1414221__success) { const auto expected = hash_literal("021e8882ef5a0ed932edeebbecfeda1d7ce528ec7b3daa27641acf1189d7b5dc"); const auto previous_header = hash_literal("5e5e12d90693c8e936f01847859404c67482439681928353ca1296982042864e"); @@ -208,9 +208,10 @@ BOOST_AUTO_TEST_CASE(compute_filter_header__block_1414221__success) BOOST_REQUIRE_EQUAL(result, expected); } +// TODO: gcc/clang warnings on literal string length. // msvc errors on length of string containing hex encoded block, tests made conditional. #ifndef _MSC_VER -BOOST_AUTO_TEST_CASE(compute_filter__block_54503__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_54503__success) { const auto raw_block = to_chunk(base16_literal("02000000b51eb76f7cfd89ef4be99b0c7ea3e009ffbf33643661a0fc29354e010000000029cac78dd1eb1575de815d371bc652c47fcf6f15557bbd02b449513bb46de6f3de1d28518f1d021cff949bdc0401000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e03e7d40002ba00062f503253482fffffffff010095e73b01000000232103bdeb1e118a17477c9a0ec4a4ea9c19931179b61c86ac736264b590874a79e8baac0000000001000000018e619d7c523b0920c71d3d0997e54e08d2538324401b08e9a71ddee6fe932561000000006a47304402203927dc71151046d2069849e577caa31205c548a8f043fadfbe0fa59010887beb022014151ef3fb90cbe850adab4db8c539baf3b30d10c68398e41e70085f330535370121027ad5e81a327971750392e620827774f7c768d1280d4e8dfe8a7b5c5ba3dcddd7ffffffff010000000000000000fd1127ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000010000000128f9c910fc890721bb5c4ca90c8fc5e5e33dc0c4abf39e458b43f932bd8d0101010000006a47304402201df88d6e4cb171f903aa74da9b68cdd02beec2e14d6bf26455405ac1a2b92aae02200e0488e2d4c6ab0561cacd85295d5a98f08a8a739090e70208eb9ba5239f77030121027ad5e81a327971750392e620827774f7c768d1280d4e8dfe8a7b5c5ba3dcddd7ffffffff010000000000000000fd1227ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000000001000000015300a4bd8000a2b1bf083c72fc65b74e1699da78904451fc9f01626135c1775e000000006a473044022038293646b2cf80c82eb26c7f26693bb18c007ef8feacf7dec1ec97adaff1974f02207c2136289bfe947ebf657967f742d4b973acf5302a1bc8124d031713058fe389012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffff010000000000000000fd224effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000")); // const auto raw_block = to_chunk(base16_literal( @@ -1431,7 +1432,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_54503__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_54499__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_54499__success) { const auto raw_block = to_chunk(base16_literal("02000000ebf8983ec7194db57e4c85daf96b8b12c11cdb421ed8329275da0e020000000049706eabeacfc248c3e9b12e3b4ad657649b9ed8137e668c2cbd0766246de4ed4d1428518f1d021c89ebdf7b1801000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0e03e3d400028f00062f503253482fffffffff015e1d77720700000023210277a01c00f27d8a79c205c416f2d021dfdcf91950af70180483eb24c547bb9233ac000000000100000001493d69f5853aed7f3fcd35fa77e7d4a23f7f499f042d079fd591311c7eb64f55000000006b483045022100ff60367cb21d0ee0fafa49443179a201ff4c58b423b2f6ef74be350a57b9b216022065818c3e9374595add9a157b1385ce28e3ba5342fa458558df6180ad424c8d96012102950d4a0663b1d8fedfb7d87f45df3436947156b26d381fa8dfcfe9de487a8444ffffffff02b025a435000000001976a91429911c1fbf60604b99d27082c2124e55cce11fbb88ac00e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac000000000100000001916b8f6cdb8489dad5f8ed48dc5e6202bbac97b6f4b8195afd3fa260e5aa93e5010000006b483045022007030ffb3ea48284a5981e72a421caea97ddd843442e0994f337eec7eb75df69022100b6cbdb3ae8f1024d6d180018ad4bc4f41c28fc21b2250ff791bd5258af25bcb401210331e9252b3312745bb1a6c9a38870b2cb3a5ee40d3b144360b3f63c9cd0e2a3c3ffffffff010000000000000000fd1027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000100000001c0813f4a5d6cc297e2944ee68157f572e6cf0af16b0f459205ee1cf83a2ab0e5010000006b48304502210093605e7b75def08f4f869eb6775f606fa445fbb96f5b8c693df2db663fc6cc8802202d4586722caaacdd941446b3e263fe8132033a5cfe17944e76f102c23ddeb02c012103a18e6b590c89710cccb2c38455b79ca0f19e444e763dcb9f77060d4df9df452fffffffff010000000000000000fd1027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000100000001c0813f4a5d6cc297e2944ee68157f572e6cf0af16b0f459205ee1cf83a2ab0e5000000006c4930460221009b92f0d3a4e4125bddf741af6efb928b36e022c49cbd3a1834e414158dec0e40022100a01a8cbefe252a010a0ff63108d7b4525530be3a3f8fcf45e6ef4532bdab12130121029d0da5f9285b2f36e21cf4cf89b04f7568b0fd9c9301fb456bd1a43fc371af92ffffffff010000000000000000fd1027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000100000001eb651bbecd0dad19b7493c45cb02c69434105630fdaf258b3eda3102f35f3db6010000006a47304402206133682cbae0e680cffdc55de46c8d70bcd7e2b57e4a5eae036d3830c395270e02202d4c7ebc31f488f29f0c72543f567d428a96053a4e5b043a54f3dbe9ae897228012103aa9f6a4830db7aa9d1db0053c232690ba548bc2941c58f4a14fbc0a2dd8cc223ffffffff0200e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac3f7c8ad6000000001976a9142a0bfcceeff9affb881160cfbed8252b21c8681588ac000000000100000002b6c73e583c8daf613ea096a25e61fdbf699331d7a631fa72abe966cf731af0e4000000006b48304502203d71acda05f3e2e85cc3663f64003409b88a882877775ed91775a826f8b6d6b8022100eec6fea64218ddb250cb923bced9b488ac911ef10a4c445ae5d635b3dc1f45b1012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffffe7e68a00f435e8dd72018117ddf3796b840fc90db1966cc3cb09cbf02f2e3b63000000006a47304402205d83f29c1382f366acf7f169d4103675dbf0e43c193cd36752a104e9ec9f424402201447e76161254100f7f6cc1ec41f8d3697058e6ed981370c22737a07bfbdd820012103a18e6b590c89710cccb2c38455b79ca0f19e444e763dcb9f77060d4df9df452fffffffff0200e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac605af405000000001976a91470ed37a176fa31a417ac4342629fd2436626b67488ac00000000010000000270324f68a97cb9e5ab844e4a43ed145b52acef1790b9eb1a04081befe5af6345000000006c493046022100810cd5537fe302dcce4b03c87482aad33ee51a957d859c114a89a39f903bc73b022100d961c6c33011bfcf96373c490e881435190b7dfbeb4d43bbf08e11ca8f9e9707012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffff70324f68a97cb9e5ab844e4a43ed145b52acef1790b9eb1a04081befe5af6345010000006b483045022100a0bc6cfae4fa8a6655263fef5be0a8ced9b70cb7a3a21110ce67a964747340490220506e4c0c7bd9ae7fac0ed408d1b2a3fe30220a055b1de1a9ad357ce374eb8eb301210297165b240b80ef8842a4817263c2eb1de51f500455d3439df49a47740c2ab10dffffffff0200e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788acc0d3f205000000001976a9147705a7a8dc42bfb549faa3253ed13a03fe42c21588ac000000000100000002d8c66c72537abee27e95fbfd5e042f9d1e84ad5038e3eaf0e154f738865dc331000000006b4830450221008b892e0053e4c964ad1e492534aa00e9e8af94ae78acd6705298bc1b7458b935022064935c8d31cdd37d223a48c58a25f5cd6ca2f2468809124f8b724d1690613341012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffffd8c66c72537abee27e95fbfd5e042f9d1e84ad5038e3eaf0e154f738865dc331010000006b483045022076b09823f455bf09facdd10d51e38742949b85b263843b2fbca0f64dee1dbb180221008d4c180c29808c5d3b8ae98abe158c67d5f19dffd125199140b77cac98809d270121035cd39dd206d69f4525732b7a32f0b70fce98d74609a10fdbd5bc45f08332a4fbffffffff02204df105000000001976a9148c66db3c6265f127498084e7fe58abb97a0ff6cb88ac00e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac0000000001000000023891a618ddc3362cec7715122ab94af4e86f038bad119b2a6ca45dfd6c2eac74000000006b48304502207307bed5ac82d10953db234db7fa9c26ce5d371fec99d299cbc781364ee945f0022100b9d3b32dedfe4404d58b7206cd5e5702c8a14166a858cea719aead2a9f6dab010121033fb3dec9f985dd20daf30782d70980e4f56cfd664b61f2cd82928cf6c5073059ffffffff3891a618ddc3362cec7715122ab94af4e86f038bad119b2a6ca45dfd6c2eac74010000006a4730440220349055357fe5cc7ce206bbb1e71f009fbd1117aaa8058589beea34b509889354022058fdab90b2ae29b8467dce32fdf14518a744eb707536394919a4ee02cd238a98012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffff0280c6ef05000000001976a9144bc5d5b68950619e52797622a38fcec17caf2cfa88ac00e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac00000000010000000232ec7bbef9c73726678ba2a7e018619a9063a1fcae120a2108837627431a19b9000000006a47304402206762995641a2b44cafa5369b2110501f3e8923bf1fbe832b1fd0ce9763ce5e2c022042e70103e8ff6cdc3fb85f7a37ed0f97f3661acc445dce4b88c1daa57f7279ee01210273c6c6470c7dd675b57af3c1efec552f5e958618d1b392bd05eaba0a2080e7dfffffffff32ec7bbef9c73726678ba2a7e018619a9063a1fcae120a2108837627431a19b9010000006b4830450220560d50d7797bf15bda555c2158337f637129ae63f0d1088292c170c661a80d01022100efeafc82b6cb1726d5a7973a4753de3c2121b5cd4605ceed8f927701c98234e2012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffff02e03fee05000000001976a9143e766efd724a4de9950950f34e2d91c890bddc9588ac00e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac000000000100000002f2b6bda0ef180884b02588b75ed6785ab3d00c98903a64219c4d2eca50acb17c000000006b483045022064ef3924e67f07f3a2e9a95f94bd9edf05422fc5896f0cbda87952d88b192a24022100ad8b6bce884d7a8a0be0c5bdc3434c978f555048e6684d023b7bc4639c31c8b6012103c243598113e15180e2e8eebbc43528ffd45549000812827d231a330535749ee1fffffffff2b6bda0ef180884b02588b75ed6785ab3d00c98903a64219c4d2eca50acb17c010000006a473044022070add586c2b2d46cc9949e0863b2c28f22d926dbb6a7eff4edd966e125ad05860220568b76bdc9e1d26764f4fde9c440802522749d8d7a756f1e37e9e2be1a3b834f012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffff0240b9ec05000000001976a91498080ef934beb096af4ac7d90c6533db5c126d1588ac00e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac000000000100000002348a6427b5903c5dc132605485a1762d232602b7ee26a37ee55c71360f717b31000000006a473044022029da959d3246a021c0c4de059dfe7a7b4178587721119cdafea29d1d4b17b6c40220668d0524723e363688b9d979de054775616d9a8a7eca5d3b90ab369a7431e38a012102dea810bdc8da9efa42c2905cef5325aee3ddf087ca416d6fbc9f10116d0a8e54ffffffff348a6427b5903c5dc132605485a1762d232602b7ee26a37ee55c71360f717b31010000006c493046022100b7a04f6c9fa19dae2a3c7b51a2ab8168d46e02944ca52341d6f3b8802689904f022100ca93678dbcdad7ae7405e2147d924a568ba61ced44424bd17c8fd46ce39d9c16012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffff0200e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788aca032eb05000000001976a9146e3158b43777301c4ca852160047a3d6a63e3a7b88ac000000000100000002d407af38bd06a8f3152d5c4b196c3bdd4dd436e056f0f17b015b21af0f61bb1f000000006b483045022100aa427b92acd563cb16e54b77ff7e4526edacafc09fe85baa7f6f5ab3d518fa30022049daae3af56b5d5e6a8aea066e4deedd2108d7a3d44f53086c39bf55d9030d59012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffffd407af38bd06a8f3152d5c4b196c3bdd4dd436e056f0f17b015b21af0f61bb1f010000006c493046022100bbff4e7e08ee0a933e94cbe9f202c4bdfa2b5eaed9e604540faeb800a06222f7022100850046295cabdd329c4851d0776938ad5c57500966df596ab9a4394607b954d60121032bdf80a04610e3450a33a0b8fc9b0b3e743be3faec58b0ebb0c0ff2629d2fd67ffffffff0200ace905000000001976a91475ead4cb03aff9bb395c2e4f29c227450e34289888ac00e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac0000000001000000020acf571f67b008fc33e217a25fc2fe56065865799ab49f28fc31e62a82d4f152000000006b4830450220646991093d3301e64e1396b7d8c17705221a322c8fc475eecb778e369a14c29d022100d378e5676be58637c6abbf76c8d13cb89466c75bf1fcd175ed8d1d554cff5d1801210238a76168bf0516d828ac309d9950db078dcf70bad99602f1885d11c34b10b622ffffffff0acf571f67b008fc33e217a25fc2fe56065865799ab49f28fc31e62a82d4f152010000006c493046022100a4f3baabd0b2ba4b0e546453e99d8064fc207be1969f9f7d641d9758542b79de022100a61fa3f739eed3dfef340cf0d599c5e233aa71056d52f5c7079d4cbcc8a47d4a012103f59cfe3b487def9d32e2486ec596c0e3c114cff29f79d5ce6148e615fa924153ffffffff0200e1f505000000001976a91445e57901210a073630ab3c2b0f08cbb57c20d77788ac6025e805000000001976a9145040e89b865852f2f77b416b7654ac7068bde3bf88ac00000000010000000128f9c910fc890721bb5c4ca90c8fc5e5e33dc0c4abf39e458b43f932bd8d0101000000006c4930460221009c9d5b8305dcc48d8ef026620c11747ab1813c2afca1740910d9ff789f8b3daf022100fb3267ff7ff0fe1ed6dc71933561acfcd0f77b0590c039a1047d6641c57b2200012103b63e56a380ba58b6c988cf88528b78bce62b57e935689646eec4209750a2b152ffffffff026081ad2f000000001976a914955dad7ac20a0e1d85e6428ede415c245f48719588ac00e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac000000000100000001b96b58b8e27822616be48ff0e073cc4dbb05c02b8e266fe9d7a90bd121689737000000006b483045022100e490837e50bce507c736b083645ed3ac75cb40fe75721187e6f0e8f8b40857e402207ece09f00147258189dfb7ad47bb8fe3ae9c3b785cc01b4d8672ddba0b3805150121023aebc34b1f55bae5d922c1071e0b20ad374145aa08c743daf7e1c18a5ae93d27ffffffff0200e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac10ddb629000000001976a9142621344f600b9bed2f330d695a4c5e45591a613088ac0000000001000000011cacd4485489625c8a0703bde8b25e120e4d76bec630e8a8768482dcb5d64793010000006a473044022018d5de5090a0af0f8d9ccc3222c0c3dc9ad96a8fdea471e3affa6daec72f775b02203a0e1532e97cdf4528748f37f807e11306da24279626af605ba22c8015ea9763012102176affebaddb7afb8fbb20f7be70df6db307994f7ceb296632f497c4875069d7ffffffff0200e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88acc038c023000000001976a9145cd1b1ae6e1f8671e66b54f06446b19cc6baeec888ac00000000010000000186daf1fb94c28da5fc49a1313013ecf41b35167941cfd7697f7dcced310f6964010000006a47304402207ca1bd2166782c130b02e4d88b2fa20ae6f67d438ccc502e3e2017211e480394022045cc0f35536537b72c717c432be4dc90893fd1f7b805af3a9968ecdc2b79c2610121037cd8b7bb2d7487fa4ac44dfb199567163c3803b311ad9e66efae2cee92f1592fffffffff0200e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac7094c91d000000001976a9140f694e25932910a03ab4e2d25d05192e9d84c24288ac0000000001000000016f024631d8db2827e4db5ef8e95d4933b6b2490d757203140e7e64b35c4e5a33010000006a47304402200d4a0490f346f31f31a3c3531a27fdf58d9534f9372a04796babd596aaf70b3002206f4b4d7cef78b3427237166f892b13263e05421d76fc04937bae0fc1b9f691a9012102873955c51f68ddee47c86e80cbeb6627d7566753e4a1717ac4e153d4e65804dcffffffff0200e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac20f0d217000000001976a914d8d5238df70cc86c48a9c332a103ba72080667da88ac0000000001000000018e619d7c523b0920c71d3d0997e54e08d2538324401b08e9a71ddee6fe932561010000006b48304502204b4f453d4e02a0c0067860514baa4a1d9ca06913466d6562bd3916726a0d8566022100e401aaa9d451e33244f34dc4697ff8ddfc0e002f28810ecb21b920ae2b5a20790121021d38c3a7c5e87cf0fab55384b5bce63e3a56627054e5c108596d23e20d054aecffffffff02d04bdc11000000001976a9144390bb02b50e93fca3186b00a09193f342cc909888ac00e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac000000000100000001bbbd750cbb2929e03cf7e6dfcfddc8fc507edb7f9edcec0bcde93ad82137c767000000006b4830450220222a4c906f3073cad688bd48238713f15c949fdaf86a23544d3ac6d5b370c89a022100f0870bb5d49d344739066b45665336a4fd668ac3bedb41901df01c8bbd3ce5370121036aacad14feeb5f4f281ba84c5f55768a4ee313ccb750f1b6cdc5742565eec735ffffffff0280a7e50b000000001976a91434fb159d8365bcf1613f6cfd42b269b130edbe6e88ac00e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac000000000100000001bced2733abeced215ebae3cdec5aafd5a9716b52c2bed68b0c66943cd7ba8600010000006c493046022100a1befd564c64e0865b00927c4b00261865e6b2a5ad3921c39960a5a651394e84022100fdec32ca924c4aaeac8880292068e01e0c1c28a61b7f46c33c2be58df12c9a2c0121027ad5e81a327971750392e620827774f7c768d1280d4e8dfe8a7b5c5ba3dcddd7ffffffff010000000000000000fd1027ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000100000001bced2733abeced215ebae3cdec5aafd5a9716b52c2bed68b0c66943cd7ba8600000000006a473044022023ad44dd6864479e9286203bb434129289e2f7ff1d3d6f7378c99ee4db71858802200f751f497ef8b68ab80242b033a2c4b770608f6924bfeac24c72c1c2622801f101210348f4cfb29c73268624994cb9688c6f32cc150b8fa1be956f2bc6b0457295d51fffffffff0200e1f505000000001976a914f2295d6917611afbb2015ae10725fd3d93cc58aa88ac3003ef05000000001976a91439072da37d9b9ca5f614691cb18830f88ca1d8c588ac00000000")); // const auto raw_block = to_chunk(base16_literal( @@ -2852,7 +2853,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_54499__success) } #endif -BOOST_AUTO_TEST_CASE(compute_filter__block_0__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_0__success) { // const auto expected_block_hash = hash_literal("000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"); @@ -2880,7 +2881,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_0__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_2__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_2__success) { // const auto expected_block_hash = hash_literal("000000006c02c8ea6e4ff69651f7fcde348fb9d557a06e6957b65552002a7820"); @@ -2905,7 +2906,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_2__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_3__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_3__success) { // const auto expected_block_hash = hash_literal("000000008b896e272758da5297bcd98fdc6d97c9b765ecec401e286dc1fdbe10"); @@ -2930,7 +2931,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_3__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_15007__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_15007__success) { // const auto expected_block_hash = hash_literal("0000000038c44c703bae0f98cdd6bf30922326340a5996cc692aaae8bacf47ad"); @@ -2955,7 +2956,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_15007__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_49291__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_49291__success) { // const auto expected_block_hash = hash_literal("0000000018b07dca1b28b4b5a119f6d6e71698ce1ed96f143f54179ce177a19c"); @@ -3089,7 +3090,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_49291__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_180480__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_180480__success) { // const auto expected_block_hash = hash_literal("00000000fd3ceb2404ff07a785c7fdcc76619edc8ed61bd25134eaa22084366a"); @@ -3215,7 +3216,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_180480__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_926485__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_926485__success) { // const auto expected_block_hash = hash_literal("000000000000015d6077a411a8f5cc95caf775ccf11c54e27df75ce58d187313"); @@ -3360,7 +3361,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_926485__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_987876__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_987876__success) { // const auto expected_block_hash = hash_literal("0000000000000c00901f2049055e2a437c819d79a3d54fd63e6af796cd7b8a79"); @@ -3385,7 +3386,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_987876__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_1263442__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_1263442__success) { // const auto expected_block_hash = hash_literal("000000006f27ddfe1dd680044a34548f41bed47eba9e6f0b310da21423bc5f33"); @@ -3431,7 +3432,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_1263442__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(compute_filter__block_1414221__success) +BOOST_AUTO_TEST_CASE(neutrino__compute_filter__block_1414221__success) { // const auto expected_block_hash = hash_literal("0000000000000027b2b3b3381f114f674f481544ff2be37ae3788d7e078383b1"); @@ -3455,7 +3456,7 @@ BOOST_AUTO_TEST_CASE(compute_filter__block_1414221__success) BOOST_REQUIRE_EQUAL(result, expected_filter); } -BOOST_AUTO_TEST_CASE(match_filter_1__input_prevout__return_true) +BOOST_AUTO_TEST_CASE(neutrino__match_filter_1__input_prevout__return_true) { const message::compact_filter filter( bc::neutrino_filter_type, @@ -3469,7 +3470,7 @@ BOOST_AUTO_TEST_CASE(match_filter_1__input_prevout__return_true) BOOST_REQUIRE(neutrino::match_filter(filter, address)); } -BOOST_AUTO_TEST_CASE(match_filter_1__unrelated_address__return_false) +BOOST_AUTO_TEST_CASE(neutrino__match_filter_1__unrelated_address__return_false) { const message::compact_filter filter( bc::neutrino_filter_type, @@ -3483,7 +3484,7 @@ BOOST_AUTO_TEST_CASE(match_filter_1__unrelated_address__return_false) BOOST_REQUIRE(!neutrino::match_filter(filter, address)); } -BOOST_AUTO_TEST_CASE(match_filter_2__input_prevout__return_true) +BOOST_AUTO_TEST_CASE(neutrino__match_filter_2__input_prevout__return_true) { const message::compact_filter filter( bc::neutrino_filter_type, @@ -3505,7 +3506,7 @@ BOOST_AUTO_TEST_CASE(match_filter_2__input_prevout__return_true) BOOST_REQUIRE(neutrino::match_filter(filter, addresses)); } -BOOST_AUTO_TEST_CASE(match_filter_2__unrelated_address__return_false) +BOOST_AUTO_TEST_CASE(neutrino__match_filter_2__unrelated_address__return_false) { const message::compact_filter filter( bc::neutrino_filter_type, diff --git a/test/wallet/witness_address.cpp b/test/wallet/witness_address.cpp index 626e318196..5ae4d42ee0 100644 --- a/test/wallet/witness_address.cpp +++ b/test/wallet/witness_address.cpp @@ -37,7 +37,7 @@ BOOST_AUTO_TEST_SUITE(witness_address_tests) #define TESTNET_WITNESS_SCRIPT_HASH_SCRIPT "[0279BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798] checksig" // BIP 173 witness address vectors -// https://github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#test-vectors +// github.com/bitcoin/bips/blob/master/bip-0173.mediawiki#test-vectors struct test_address { std::string address; @@ -61,7 +61,7 @@ const test_address_list witness_address_nonzero_version_tests { "bc1zw508d6qejxtdg4y5r3zarvaryvg6kdaj", "5210751e76e8199196d454941c45d1b3a323" }, }; -BOOST_AUTO_TEST_CASE(witness_address__construct__mainnet_to_witness_script_hash__valid__expected) +BOOST_AUTO_TEST_CASE(witness_address__construct__mainnet_to_witness_script_hash__valid_expected) { chain::script script; script.from_string(MAINNET_WITNESS_SCRIPT_HASH_SCRIPT); @@ -70,7 +70,7 @@ BOOST_AUTO_TEST_CASE(witness_address__construct__mainnet_to_witness_script_hash_ BOOST_REQUIRE_EQUAL(address.encoded(), MAINNET_WITNESS_SCRIPT_HASH_ADDRESS); } -BOOST_AUTO_TEST_CASE(witness_address__construct__testnet_to_witness_script_hash__valid__expected) +BOOST_AUTO_TEST_CASE(witness_address__construct__testnet_to_witness_script_hash__valid_expected) { chain::script script; script.from_string(TESTNET_WITNESS_SCRIPT_HASH_SCRIPT); @@ -79,10 +79,10 @@ BOOST_AUTO_TEST_CASE(witness_address__construct__testnet_to_witness_script_hash_ BOOST_REQUIRE_EQUAL(address.encoded(), TESTNET_WITNESS_SCRIPT_HASH_ADDRESS); } -BOOST_AUTO_TEST_CASE(witness_address__construct__ec_public_to_testnet_witness_pubkey_hash__valid__expected) +BOOST_AUTO_TEST_CASE(witness_address__construct__ec_public_to_testnet_witness_pubkey_hash__valid_expected) { // Based on witness data from: - // https://www.blockchain.com/btctest/tx/d869f854e1f8788bcff294cc83b280942a8c728de71eb709a2c29d10bfe21b7c + // blockchain.com/btctest/tx/d869f854e1f8788bcff294cc83b280942a8c728de71eb709a2c29d10bfe21b7c // Create the same witness address from ec_public. const std::string test_public_key = "038262a6c6cec93c2d3ecd6c6072efea86d02ff8e3328bbd0242b20af3425990ac"; @@ -102,7 +102,7 @@ struct witness_address_accessor } }; -BOOST_AUTO_TEST_CASE(base32__witness_address_zero_version_tests__valid__expected) +BOOST_AUTO_TEST_CASE(witness_address__convert_bits__zero_version__valid_expected) { const auto zero_witness_version = 0u; const auto bech32_contracted_bit_size = 5u; @@ -134,7 +134,7 @@ BOOST_AUTO_TEST_CASE(base32__witness_address_zero_version_tests__valid__expected } } -BOOST_AUTO_TEST_CASE(base32__witness_address_nonzero_version_tests__valid__expected) +BOOST_AUTO_TEST_CASE(witness_address__convert_bits__nonzero_version__valid_expected) { // This op_version gap is used to normalize the value difference // between the defined OP_0 opcode (value 0) and the OP_1 opcode From 59ebd78b7d5e0aa5255d94a2f6ef615bd82bdaf6 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Fri, 5 Mar 2021 02:13:41 -0800 Subject: [PATCH 02/44] Update boost and secp256k1 dependencies, clear suppressions. --- builds/cmake/CMakeLists.txt | 2 +- .../libbitcoin-system-examples.props | 2 - .../libbitcoin-system-examples.vcxproj | 4 +- .../packages.config | 2 +- .../libbitcoin-system-test.props | 1 - .../libbitcoin-system-test.vcxproj | 4 +- .../libbitcoin-system-test/packages.config | 2 +- .../vs2013/libbitcoin-system.import.props | 7 +-- .../libbitcoin-system/libbitcoin-system.props | 7 +-- .../libbitcoin-system.vcxproj | 4 +- .../vs2013/libbitcoin-system/packages.config | 2 +- .../libbitcoin-system-examples.props | 2 - .../libbitcoin-system-examples.vcxproj | 56 ++++++++--------- .../packages.config | 28 ++++----- .../libbitcoin-system-test.props | 1 - .../libbitcoin-system-test.vcxproj | 60 +++++++++---------- .../libbitcoin-system-test/packages.config | 30 +++++----- .../vs2015/libbitcoin-system.import.props | 7 +-- .../libbitcoin-system/libbitcoin-system.props | 7 +-- .../libbitcoin-system.vcxproj | 56 ++++++++--------- .../vs2015/libbitcoin-system/packages.config | 28 ++++----- .../libbitcoin-system-examples.props | 2 - .../libbitcoin-system-examples.vcxproj | 56 ++++++++--------- .../packages.config | 28 ++++----- .../libbitcoin-system-test.props | 1 - .../libbitcoin-system-test.vcxproj | 60 +++++++++---------- .../libbitcoin-system-test/packages.config | 30 +++++----- .../vs2017/libbitcoin-system.import.props | 7 +-- .../libbitcoin-system/libbitcoin-system.props | 7 +-- .../libbitcoin-system.vcxproj | 56 ++++++++--------- .../vs2017/libbitcoin-system/packages.config | 28 ++++----- configure.ac | 6 +- install.sh | 6 +- 33 files changed, 292 insertions(+), 307 deletions(-) diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index 7139e8c95f..dc68ebaa17 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -129,7 +129,7 @@ endif() # Find boost #------------------------------------------------------------------------------ -find_package( Boost 1.62.0 REQUIRED COMPONENTS +find_package( Boost 1.72.0 REQUIRED COMPONENTS atomic chrono date_time diff --git a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props index 1dbabbe90a..914a8d1005 100644 --- a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props +++ b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props @@ -13,8 +13,6 @@ %(DisableSpecificWarnings) false - - _WIN32_WINNT=0x0600;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj index 9a8a23d008..74958fa3f3 100644 --- a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj @@ -97,7 +97,7 @@ - + @@ -116,7 +116,7 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-examples/packages.config b/builds/msvc/vs2013/libbitcoin-system-examples/packages.config index f1a2ef5c33..986c1f5e2e 100644 --- a/builds/msvc/vs2013/libbitcoin-system-examples/packages.config +++ b/builds/msvc/vs2013/libbitcoin-system-examples/packages.config @@ -19,5 +19,5 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props index c245869fc0..d42786722d 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props @@ -21,7 +21,6 @@ Disabled %(DisableSpecificWarnings) false - _WIN32_WINNT=0x0600;%(PreprocessorDefinitions) ENABLE_DATAGEN;%(PreprocessorDefinitions) BOOST_TEST_DYN_LINK;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj index b95ea354da..9fe125b2c0 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -236,7 +236,7 @@ - + @@ -256,7 +256,7 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-test/packages.config b/builds/msvc/vs2013/libbitcoin-system-test/packages.config index 445e6c54f8..3cdc9e01cd 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/packages.config +++ b/builds/msvc/vs2013/libbitcoin-system-test/packages.config @@ -19,6 +19,6 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system.import.props b/builds/msvc/vs2013/libbitcoin-system.import.props index f85aa20b66..530075c30f 100644 --- a/builds/msvc/vs2013/libbitcoin-system.import.props +++ b/builds/msvc/vs2013/libbitcoin-system.import.props @@ -16,11 +16,10 @@ $(ProjectDir)..\..\..\..\..\libbitcoin-system\include\;%(AdditionalIncludeDirectories) - - 4996;%(DisableSpecificWarnings) + - - WIN32_LEAN_AND_MEAN;NOMINMAX;%(PreprocessorDefinitions) + + WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) BC_STATIC;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.props b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.props index 098500b1a0..043f05e664 100644 --- a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.props +++ b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.props @@ -18,12 +18,11 @@ $(RepoRoot)include\;%(AdditionalIncludeDirectories) - - 4996;%(DisableSpecificWarnings) false + - - WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) BC_DLL;%(PreprocessorDefinitions) BC_STATIC;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj index aad4c09e0b..248d20b10e 100644 --- a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj @@ -593,7 +593,7 @@ - + @@ -612,6 +612,6 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system/packages.config b/builds/msvc/vs2013/libbitcoin-system/packages.config index f1a2ef5c33..986c1f5e2e 100644 --- a/builds/msvc/vs2013/libbitcoin-system/packages.config +++ b/builds/msvc/vs2013/libbitcoin-system/packages.config @@ -19,5 +19,5 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props index 1dbabbe90a..914a8d1005 100644 --- a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props +++ b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props @@ -13,8 +13,6 @@ %(DisableSpecificWarnings) false - - _WIN32_WINNT=0x0600;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj index 735ef698da..b869d76a3a 100644 --- a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj @@ -84,39 +84,39 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2015/libbitcoin-system-examples/packages.config b/builds/msvc/vs2015/libbitcoin-system-examples/packages.config index 3fc6e4181a..a2d4a69123 100644 --- a/builds/msvc/vs2015/libbitcoin-system-examples/packages.config +++ b/builds/msvc/vs2015/libbitcoin-system-examples/packages.config @@ -6,18 +6,18 @@ | --> - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props index c245869fc0..d42786722d 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props @@ -21,7 +21,6 @@ Disabled %(DisableSpecificWarnings) false - _WIN32_WINNT=0x0600;%(PreprocessorDefinitions) ENABLE_DATAGEN;%(PreprocessorDefinitions) BOOST_TEST_DYN_LINK;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 544641673b..bb66e1c930 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -223,41 +223,41 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2015/libbitcoin-system-test/packages.config b/builds/msvc/vs2015/libbitcoin-system-test/packages.config index 6c9d8f5f32..a62262518b 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/packages.config +++ b/builds/msvc/vs2015/libbitcoin-system-test/packages.config @@ -6,19 +6,19 @@ | --> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2015/libbitcoin-system.import.props b/builds/msvc/vs2015/libbitcoin-system.import.props index f85aa20b66..530075c30f 100644 --- a/builds/msvc/vs2015/libbitcoin-system.import.props +++ b/builds/msvc/vs2015/libbitcoin-system.import.props @@ -16,11 +16,10 @@ $(ProjectDir)..\..\..\..\..\libbitcoin-system\include\;%(AdditionalIncludeDirectories) - - 4996;%(DisableSpecificWarnings) + - - WIN32_LEAN_AND_MEAN;NOMINMAX;%(PreprocessorDefinitions) + + WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) BC_STATIC;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.props b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.props index 098500b1a0..043f05e664 100644 --- a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.props +++ b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.props @@ -18,12 +18,11 @@ $(RepoRoot)include\;%(AdditionalIncludeDirectories) - - 4996;%(DisableSpecificWarnings) false + - - WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) BC_DLL;%(PreprocessorDefinitions) BC_STATIC;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj index 55732f0842..9b81683913 100644 --- a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj @@ -577,38 +577,38 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2015/libbitcoin-system/packages.config b/builds/msvc/vs2015/libbitcoin-system/packages.config index 3fc6e4181a..a2d4a69123 100644 --- a/builds/msvc/vs2015/libbitcoin-system/packages.config +++ b/builds/msvc/vs2015/libbitcoin-system/packages.config @@ -6,18 +6,18 @@ | --> - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props index 1dbabbe90a..914a8d1005 100644 --- a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props +++ b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props @@ -13,8 +13,6 @@ %(DisableSpecificWarnings) false - - _WIN32_WINNT=0x0600;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj index f284cca98e..7496c4b1d0 100644 --- a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj @@ -84,39 +84,39 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-system-examples/packages.config b/builds/msvc/vs2017/libbitcoin-system-examples/packages.config index f763f25006..e4cd9808fa 100644 --- a/builds/msvc/vs2017/libbitcoin-system-examples/packages.config +++ b/builds/msvc/vs2017/libbitcoin-system-examples/packages.config @@ -6,18 +6,18 @@ | --> - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props index c245869fc0..d42786722d 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props @@ -21,7 +21,6 @@ Disabled %(DisableSpecificWarnings) false - _WIN32_WINNT=0x0600;%(PreprocessorDefinitions) ENABLE_DATAGEN;%(PreprocessorDefinitions) BOOST_TEST_DYN_LINK;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 19477295e2..0c2a9a71a2 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -223,41 +223,41 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-system-test/packages.config b/builds/msvc/vs2017/libbitcoin-system-test/packages.config index 7c6a8406d4..b16d276212 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/packages.config +++ b/builds/msvc/vs2017/libbitcoin-system-test/packages.config @@ -6,19 +6,19 @@ | --> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-system.import.props b/builds/msvc/vs2017/libbitcoin-system.import.props index f85aa20b66..530075c30f 100644 --- a/builds/msvc/vs2017/libbitcoin-system.import.props +++ b/builds/msvc/vs2017/libbitcoin-system.import.props @@ -16,11 +16,10 @@ $(ProjectDir)..\..\..\..\..\libbitcoin-system\include\;%(AdditionalIncludeDirectories) - - 4996;%(DisableSpecificWarnings) + - - WIN32_LEAN_AND_MEAN;NOMINMAX;%(PreprocessorDefinitions) + + WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) BC_STATIC;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.props b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.props index 098500b1a0..043f05e664 100644 --- a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.props +++ b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.props @@ -18,12 +18,11 @@ $(RepoRoot)include\;%(AdditionalIncludeDirectories) - - 4996;%(DisableSpecificWarnings) false + - - WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) + + WITH_ICU;WIN32_LEAN_AND_MEAN;NOMINMAX;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions) BC_DLL;%(PreprocessorDefinitions) BC_STATIC;%(PreprocessorDefinitions) diff --git a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj index 9a8c459400..2bc0fc140c 100644 --- a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj @@ -577,38 +577,38 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-system/packages.config b/builds/msvc/vs2017/libbitcoin-system/packages.config index f763f25006..e4cd9808fa 100644 --- a/builds/msvc/vs2017/libbitcoin-system/packages.config +++ b/builds/msvc/vs2017/libbitcoin-system/packages.config @@ -6,18 +6,18 @@ | --> - - - - - - - - - - - - - - + + + + + + + + + + + + + + diff --git a/configure.ac b/configure.ac index e3b8124091..7356f2fe87 100644 --- a/configure.ac +++ b/configure.ac @@ -171,17 +171,17 @@ AC_MSG_RESULT([$enable_isystem]) # Check dependencies. #============================================================================== -# Require Boost of at least version 1.62.0 and output ${boost_CPPFLAGS/LDFLAGS}. +# Require Boost of at least version 1.72.0 and output ${boost_CPPFLAGS/LDFLAGS}. #------------------------------------------------------------------------------ AS_CASE([${CC}], [*], - [AX_BOOST_BASE([1.62.0], + [AX_BOOST_BASE([1.72.0], [AC_SUBST([boost_CPPFLAGS], [${BOOST_CPPFLAGS}]) AC_SUBST([boost_ISYS_CPPFLAGS], [`echo ${BOOST_CPPFLAGS} | $SED s/^-I/-isystem/g | $SED s/' -I'/' -isystem'/g`]) AC_SUBST([boost_LDFLAGS], [${BOOST_LDFLAGS}]) AC_MSG_NOTICE([boost_CPPFLAGS : ${boost_CPPFLAGS}]) AC_MSG_NOTICE([boost_ISYS_CPPFLAGS : ${boost_ISYS_CPPFLAGS}]) AC_MSG_NOTICE([boost_LDFLAGS : ${boost_LDFLAGS}])], - [AC_MSG_ERROR([Boost 1.62.0 or later is required but was not found.])])]) + [AC_MSG_ERROR([Boost 1.72.0 or later is required but was not found.])])]) AS_CASE([${enable_isystem}],[yes], [AC_SUBST([boost_BUILD_CPPFLAGS], [${boost_ISYS_CPPFLAGS}])], diff --git a/install.sh b/install.sh index db5d1294ec..cfa192202b 100755 --- a/install.sh +++ b/install.sh @@ -79,8 +79,8 @@ QRENCODE_ARCHIVE="qrencode-3.4.4.tar.bz2" # Boost archive. #------------------------------------------------------------------------------ -BOOST_URL="http://downloads.sourceforge.net/project/boost/boost/1.62.0/boost_1_62_0.tar.bz2" -BOOST_ARCHIVE="boost_1_62_0.tar.bz2" +BOOST_URL="http://downloads.sourceforge.net/project/boost/boost/1.72.0/boost_1_72_0.tar.bz2" +BOOST_ARCHIVE="boost_1_72_0.tar.bz2" # Define utility functions. @@ -848,7 +848,7 @@ build_all() build_from_tarball "$PNG_URL" "$PNG_ARCHIVE" xz . "$PARALLEL" "$BUILD_PNG" "${PNG_OPTIONS[@]}" "$@" build_from_tarball "$QRENCODE_URL" "$QRENCODE_ARCHIVE" bzip2 . "$PARALLEL" "$BUILD_QRENCODE" "${QRENCODE_OPTIONS[@]}" "$@" build_from_tarball_boost "$BOOST_URL" "$BOOST_ARCHIVE" bzip2 . "$PARALLEL" "$BUILD_BOOST" "${BOOST_OPTIONS[@]}" - build_from_github libbitcoin secp256k1 version6 "$PARALLEL" "${SECP256K1_OPTIONS[@]}" "$@" + build_from_github libbitcoin secp256k1 version7 "$PARALLEL" "${SECP256K1_OPTIONS[@]}" "$@" build_from_travis libbitcoin libbitcoin-system master "$PARALLEL" "${BITCOIN_SYSTEM_OPTIONS[@]}" "$@" } From 99fcdb7232e7b7af97eb17e4ef088f54c89788bc Mon Sep 17 00:00:00 2001 From: evoskuil Date: Fri, 5 Mar 2021 21:49:16 -0800 Subject: [PATCH 03/44] Import updated lax_der_parsing.h/c (MIT License). --- src/math/external/lax_der_parsing.c | 17 ++++++++--------- src/math/external/lax_der_parsing.h | 20 ++++++++++---------- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/math/external/lax_der_parsing.c b/src/math/external/lax_der_parsing.c index cedd89da08..da26669c8f 100644 --- a/src/math/external/lax_der_parsing.c +++ b/src/math/external/lax_der_parsing.c @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ #include #include @@ -32,7 +32,7 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { + if (lenbyte > inputlen - pos) { return 0; } pos += lenbyte; @@ -51,7 +51,7 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { + if (lenbyte > inputlen - pos) { return 0; } while (lenbyte > 0 && input[pos] == 0) { @@ -89,7 +89,7 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ lenbyte = input[pos++]; if (lenbyte & 0x80) { lenbyte -= 0x80; - if (pos + lenbyte > inputlen) { + if (lenbyte > inputlen - pos) { return 0; } while (lenbyte > 0 && input[pos] == 0) { @@ -112,7 +112,6 @@ int ecdsa_signature_parse_der_lax(const secp256k1_context* ctx, secp256k1_ecdsa_ return 0; } spos = pos; - pos += slen; /* Ignore leading zeroes in R */ while (rlen > 0 && input[rpos] == 0) { diff --git a/src/math/external/lax_der_parsing.h b/src/math/external/lax_der_parsing.h index 6d27871a7c..6b7255e28f 100644 --- a/src/math/external/lax_der_parsing.h +++ b/src/math/external/lax_der_parsing.h @@ -1,8 +1,8 @@ -/********************************************************************** - * Copyright (c) 2015 Pieter Wuille * - * Distributed under the MIT software license, see the accompanying * - * file COPYING or http://www.opensource.org/licenses/mit-license.php.* - **********************************************************************/ +/*********************************************************************** + * Copyright (c) 2015 Pieter Wuille * + * Distributed under the MIT software license, see the accompanying * + * file COPYING or https://www.opensource.org/licenses/mit-license.php.* + ***********************************************************************/ /**** * Please do not link this file directly. It is not part of the libsecp256k1 @@ -48,14 +48,14 @@ * 8.3.1. */ -#ifndef _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ -#define _SECP256K1_CONTRIB_LAX_DER_PARSING_H_ +#ifndef SECP256K1_CONTRIB_LAX_DER_PARSING_H +#define SECP256K1_CONTRIB_LAX_DER_PARSING_H #include -# ifdef __cplusplus +#ifdef __cplusplus extern "C" { -# endif +#endif /** Parse a signature in "lax DER" format * @@ -88,4 +88,4 @@ int ecdsa_signature_parse_der_lax( } #endif -#endif +#endif /* SECP256K1_CONTRIB_LAX_DER_PARSING_H */ From 599646d8da622c9ca3259aeef9427232d66b5840 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Fri, 5 Mar 2021 23:23:54 -0800 Subject: [PATCH 04/44] Comments on Unicode and UTF-16, style. --- include/bitcoin/system/unicode/unicode.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/bitcoin/system/unicode/unicode.hpp b/include/bitcoin/system/unicode/unicode.hpp index a1ae364751..8390836d2c 100644 --- a/include/bitcoin/system/unicode/unicode.hpp +++ b/include/bitcoin/system/unicode/unicode.hpp @@ -30,9 +30,10 @@ // Windows and other environments, such as Java, that supported Unicode prior // to the advent of utf8 utilize 16 bit characters. These are typically encoded // as wchar_t in C++. Unicode no longer fits in 16 bits and as such these -// implementations now require variable length character encoding just as utf8. +// implementations now require variable length character encoding just as utf8 +// boost.org/doc/libs/1_75_0/libs/locale/doc/html/recommendations_and_myths.html // -// Libbitcoin embraces the "utf8 everywhere" design: http://utf8everywhere.org +// Libbitcoin embraces the "utf8 everywhere" design: utf8everywhere.org // The objective is to use utf8 as the canonical string encoding, pushing // wchar_t translation to the edge (stdio, argv, O/S and external API calls). // The macro BC_USE_LIBBITCOIN_MAIN does most of the heavy lifting to ensure From 6310b3e8c5ebff01bd2469e87a0247e98b4cea97 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 6 Mar 2021 16:16:19 -0800 Subject: [PATCH 05/44] Update m4 sources, removing our (boost) hacks. --- m4/ax_boost_base.m4 | 255 ++++---- m4/ax_boost_chrono.m4 | 10 +- m4/ax_boost_date_time.m4 | 6 +- m4/ax_boost_filesystem.m4 | 6 +- m4/ax_boost_iostreams.m4 | 6 +- m4/ax_boost_locale.m4 | 13 +- m4/ax_boost_log.m4 | 12 +- m4/ax_boost_log_setup.m4 | 12 +- m4/ax_boost_program_options.m4 | 14 +- m4/ax_boost_regex.m4 | 10 +- m4/ax_boost_system.m4 | 9 +- m4/ax_boost_thread.m4 | 178 +++--- m4/ax_boost_unit_test_framework.m4 | 12 +- m4/ax_check_compile_flag.m4 | 37 +- m4/ax_check_link_flag.m4 | 38 +- m4/ax_check_preproc_flag.m4 | 33 +- m4/ax_cxx_compile_stdcxx.m4 | 962 +++++++++++++++++++++++++++++ m4/ax_cxx_compile_stdcxx_11.m4 | 130 +--- m4/ax_java_devel.m4 | 57 -- m4/ax_jni_include_dir.m4 | 126 ---- m4/ax_prog_jar.m4 | 49 -- m4/ax_prog_java.m4 | 115 ---- m4/ax_prog_java_works.m4 | 134 ---- m4/ax_prog_javac.m4 | 79 --- m4/ax_prog_javac_works.m4 | 72 --- m4/ax_pthread.m4 | 448 ++++++++++---- m4/ax_python_devel.m4 | 324 ---------- 27 files changed, 1628 insertions(+), 1519 deletions(-) create mode 100644 m4/ax_cxx_compile_stdcxx.m4 delete mode 100644 m4/ax_java_devel.m4 delete mode 100644 m4/ax_jni_include_dir.m4 delete mode 100644 m4/ax_prog_jar.m4 delete mode 100644 m4/ax_prog_java.m4 delete mode 100644 m4/ax_prog_java_works.m4 delete mode 100644 m4/ax_prog_javac.m4 delete mode 100644 m4/ax_prog_javac_works.m4 delete mode 100644 m4/ax_python_devel.m4 diff --git a/m4/ax_boost_base.m4 b/m4/ax_boost_base.m4 index 355963c43f..519f1c9d27 100644 --- a/m4/ax_boost_base.m4 +++ b/m4/ax_boost_base.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_base.html # =========================================================================== # # SYNOPSIS @@ -11,9 +11,9 @@ # Test for the Boost C++ libraries of a particular version (or newer) # # If no path to the installed boost library is given the macro searchs -# under /usr, /usr/local, /opt and /opt/local and -# evaluates the $BOOST_ROOT environment variable. Further documentation -# is available at . +# under /usr, /usr/local, /opt and /opt/local and evaluates the +# $BOOST_ROOT environment variable. Further documentation is available at +# . # # This macro calls: # @@ -33,7 +33,15 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 23 (?) +#serial 49 + +# example boost program (need to pass version) +m4_define([_AX_BOOST_BASE_PROGRAM], + [AC_LANG_PROGRAM([[ +#include +]],[[ +(void) ((void)sizeof(char[1 - 2*!!((BOOST_VERSION) < ($1))])); +]])]) AC_DEFUN([AX_BOOST_BASE], [ @@ -44,101 +52,123 @@ AC_ARG_WITH([boost], or disable it (ARG=no) @<:@ARG=yes@:>@ ])], [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then - want_boost="yes" - ac_boost_path="" - else - want_boost="yes" - ac_boost_path="$withval" - fi + AS_CASE([$withval], + [no],[want_boost="no";_AX_BOOST_BASE_boost_path=""], + [yes],[want_boost="yes";_AX_BOOST_BASE_boost_path=""], + [want_boost="yes";_AX_BOOST_BASE_boost_path="$withval"]) ], [want_boost="yes"]) AC_ARG_WITH([boost-libdir], - AS_HELP_STRING([--with-boost-libdir=LIB_DIR], - [Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]), - [ - if test -d "$withval" - then - ac_boost_lib_path="$withval" - else - AC_MSG_ERROR(--with-boost-libdir expected directory name) - fi - ], - [ac_boost_lib_path=""] -) + [AS_HELP_STRING([--with-boost-libdir=LIB_DIR], + [Force given directory for boost libraries. + Note that this will override library path detection, + so use this parameter only if default library detection fails + and you know exactly where your boost libraries are located.])], + [ + AS_IF([test -d "$withval"], + [_AX_BOOST_BASE_boost_lib_path="$withval"], + [AC_MSG_ERROR([--with-boost-libdir expected directory name])]) + ], + [_AX_BOOST_BASE_boost_lib_path=""]) -if test "x$want_boost" = "xyes"; then - boost_lib_version_req=ifelse([$1], ,1.20.0,$1) - boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'` - boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'` - boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'` - boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` - if test "x$boost_lib_version_req_sub_minor" = "x" ; then - boost_lib_version_req_sub_minor="0" - fi - WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor` - AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req) +BOOST_LDFLAGS="" +BOOST_CPPFLAGS="" +AS_IF([test "x$want_boost" = "xyes"], + [_AX_BOOST_BASE_RUNDETECT([$1],[$2],[$3])]) +AC_SUBST(BOOST_CPPFLAGS) +AC_SUBST(BOOST_LDFLAGS) +]) + + +# convert a version string in $2 to numeric and affect to polymorphic var $1 +AC_DEFUN([_AX_BOOST_BASE_TONUMERICVERSION],[ + AS_IF([test "x$2" = "x"],[_AX_BOOST_BASE_TONUMERICVERSION_req="1.20.0"],[_AX_BOOST_BASE_TONUMERICVERSION_req="$2"]) + _AX_BOOST_BASE_TONUMERICVERSION_req_shorten=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\.[[0-9]]*\)'` + _AX_BOOST_BASE_TONUMERICVERSION_req_major=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '\([[0-9]]*\)'` + AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_major" = "x"], + [AC_MSG_ERROR([You should at least specify libboost major version])]) + _AX_BOOST_BASE_TONUMERICVERSION_req_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.\([[0-9]]*\)'` + AS_IF([test "x$_AX_BOOST_BASE_TONUMERICVERSION_req_minor" = "x"], + [_AX_BOOST_BASE_TONUMERICVERSION_req_minor="0"]) + _AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'` + AS_IF([test "X$_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor" = "X"], + [_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor="0"]) + _AX_BOOST_BASE_TONUMERICVERSION_RET=`expr $_AX_BOOST_BASE_TONUMERICVERSION_req_major \* 100000 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_minor \* 100 \+ $_AX_BOOST_BASE_TONUMERICVERSION_req_sub_minor` + AS_VAR_SET($1,$_AX_BOOST_BASE_TONUMERICVERSION_RET) +]) + +dnl Run the detection of boost should be run only if $want_boost +AC_DEFUN([_AX_BOOST_BASE_RUNDETECT],[ + _AX_BOOST_BASE_TONUMERICVERSION(WANT_BOOST_VERSION,[$1]) succeeded=no + + AC_REQUIRE([AC_CANONICAL_HOST]) dnl On 64-bit systems check for system libraries in both lib64 and lib. dnl The former is specified by FHS, but e.g. Debian does not adhere to dnl this (as it rises problems for generic multi-arch support). dnl The last entry in the list is chosen by default when no libraries dnl are found, e.g. when only header-only libraries are installed! - libsubdirs="lib" - ax_arch=`uname -m` - case $ax_arch in - x86_64|ppc64|s390x|sparc64|aarch64) - libsubdirs="lib64 lib lib64" - ;; - esac + AS_CASE([${host_cpu}], + [x86_64],[libsubdirs="lib64 libx32 lib lib64"], + [mips*64*],[libsubdirs="lib64 lib32 lib lib64"], + [ppc64|powerpc64|s390x|sparc64|aarch64|ppc64le|powerpc64le|riscv64|e2k],[libsubdirs="lib64 lib lib64"], + [libsubdirs="lib"] + ) dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give dnl them priority over the other paths since, if libs are found there, they dnl are almost assuredly the ones desired. - AC_REQUIRE([AC_CANONICAL_HOST]) - libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs" - - case ${host_cpu} in - i?86) - libsubdirs="lib/i386-${host_os} $libsubdirs" - ;; - esac + AS_CASE([${host_cpu}], + [i?86],[multiarch_libsubdir="lib/i386-${host_os}"], + [armv7l],[multiarch_libsubdir="lib/arm-${host_os}"], + [multiarch_libsubdir="lib/${host_cpu}-${host_os}"] + ) dnl first we check the system location for boost libraries dnl this location ist chosen if boost libraries are installed with the --layout=system option dnl or if you install boost with RPM - if test "$ac_boost_path" != ""; then - BOOST_CPPFLAGS="-I$ac_boost_path/include" - for ac_boost_path_tmp in $libsubdirs; do - if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then - BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp" - break - fi - done - elif test "$cross_compiling" != yes; then - for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then - for libsubdir in $libsubdirs ; do - if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + AS_IF([test "x$_AX_BOOST_BASE_boost_path" != "x"],[ + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) includes in "$_AX_BOOST_BASE_boost_path/include"]) + AS_IF([test -d "$_AX_BOOST_BASE_boost_path/include" && test -r "$_AX_BOOST_BASE_boost_path/include"],[ + AC_MSG_RESULT([yes]) + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include" + for _AX_BOOST_BASE_boost_path_tmp in $multiarch_libsubdir $libsubdirs; do + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION) lib path in "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"]) + AS_IF([test -d "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" && test -r "$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp" ],[ + AC_MSG_RESULT([yes]) + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$_AX_BOOST_BASE_boost_path_tmp"; + break; + ], + [AC_MSG_RESULT([no])]) + done],[ + AC_MSG_RESULT([no])]) + ],[ + if test X"$cross_compiling" = Xyes; then + search_libsubdirs=$multiarch_libsubdir + else + search_libsubdirs="$multiarch_libsubdir $libsubdirs" + fi + for _AX_BOOST_BASE_boost_path_tmp in /usr /usr/local /opt /opt/local ; do + if test -d "$_AX_BOOST_BASE_boost_path_tmp/include/boost" && test -r "$_AX_BOOST_BASE_boost_path_tmp/include/boost" ; then + for libsubdir in $search_libsubdirs ; do + if ls "$_AX_BOOST_BASE_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done - BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir" - BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include" + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path_tmp/$libsubdir" + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path_tmp/include" break; fi done - fi + ]) dnl overwrite ld flags if we have required special directory with dnl --with-boost-libdir parameter - if test "$ac_boost_lib_path" != ""; then - BOOST_LDFLAGS="-L$ac_boost_lib_path" - fi + AS_IF([test "x$_AX_BOOST_BASE_boost_lib_path" != "x"], + [BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_lib_path"]) + AC_MSG_CHECKING([for boostlib >= $1 ($WANT_BOOST_VERSION)]) CPPFLAGS_SAVED="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" export CPPFLAGS @@ -149,15 +179,7 @@ if test "x$want_boost" = "xyes"; then AC_REQUIRE([AC_PROG_CXX]) AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ + AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes @@ -169,30 +191,50 @@ if test "x$want_boost" = "xyes"; then dnl if we found no boost with system layout we search for boost libraries dnl built and installed without the --layout=system option or for a staged(not installed) version - if test "x$succeeded" != "xyes"; then + if test "x$succeeded" != "xyes" ; then + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + BOOST_CPPFLAGS= + if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then + BOOST_LDFLAGS= + fi _version=0 - if test "$ac_boost_path" != ""; then - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + if test -n "$_AX_BOOST_BASE_boost_path" ; then + if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path"; then + for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then + if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp fi VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` - BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE" + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path/include/boost-$VERSION_UNDERSCORE" done + dnl if nothing found search for layout used in Windows distributions + if test -z "$BOOST_CPPFLAGS"; then + if test -d "$_AX_BOOST_BASE_boost_path/boost" && test -r "$_AX_BOOST_BASE_boost_path/boost"; then + BOOST_CPPFLAGS="-I$_AX_BOOST_BASE_boost_path" + fi + fi + dnl if we found something and BOOST_LDFLAGS was unset before + dnl (because "$_AX_BOOST_BASE_boost_lib_path" = ""), set it here. + if test -n "$BOOST_CPPFLAGS" && test -z "$BOOST_LDFLAGS"; then + for libsubdir in $libsubdirs ; do + if ls "$_AX_BOOST_BASE_boost_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi + done + BOOST_LDFLAGS="-L$_AX_BOOST_BASE_boost_path/$libsubdir" + fi fi else - if test "$cross_compiling" != yes; then - for ac_boost_path in /usr /usr/local /opt /opt/local ; do - if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then - for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do - _version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` + if test "x$cross_compiling" != "xyes" ; then + for _AX_BOOST_BASE_boost_path in /usr /usr/local /opt /opt/local ; do + if test -d "$_AX_BOOST_BASE_boost_path" && test -r "$_AX_BOOST_BASE_boost_path" ; then + for i in `ls -d $_AX_BOOST_BASE_boost_path/include/boost-* 2>/dev/null`; do + _version_tmp=`echo $i | sed "s#$_AX_BOOST_BASE_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'` V_CHECK=`expr $_version_tmp \> $_version` - if test "$V_CHECK" = "1" ; then + if test "x$V_CHECK" = "x1" ; then _version=$_version_tmp - best_path=$ac_boost_path + best_path=$_AX_BOOST_BASE_boost_path fi done fi @@ -200,7 +242,7 @@ if test "x$want_boost" = "xyes"; then VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'` BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE" - if test "$ac_boost_lib_path" = ""; then + if test -z "$_AX_BOOST_BASE_boost_lib_path" ; then for libsubdir in $libsubdirs ; do if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done @@ -208,7 +250,7 @@ if test "x$want_boost" = "xyes"; then fi fi - if test "x$BOOST_ROOT" != "x"; then + if test -n "$BOOST_ROOT" ; then for libsubdir in $libsubdirs ; do if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi done @@ -217,7 +259,7 @@ if test "x$want_boost" = "xyes"; then stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'` stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'` V_CHECK=`expr $stage_version_shorten \>\= $_version` - if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then + if test "x$V_CHECK" = "x1" && test -z "$_AX_BOOST_BASE_boost_lib_path" ; then AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT) BOOST_CPPFLAGS="-I$BOOST_ROOT" BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir" @@ -232,15 +274,7 @@ if test "x$want_boost" = "xyes"; then export LDFLAGS AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ - @%:@include - ]], [[ - #if BOOST_VERSION >= $WANT_BOOST_VERSION - // Everything is okay - #else - # error Boost version is too old - #endif - ]])],[ + AC_COMPILE_IFELSE([_AX_BOOST_BASE_PROGRAM($WANT_BOOST_VERSION)],[ AC_MSG_RESULT(yes) succeeded=yes found_system=yes @@ -249,17 +283,15 @@ if test "x$want_boost" = "xyes"; then AC_LANG_POP([C++]) fi - if test "$succeeded" != "yes" ; then - if test "$_version" = "0" ; then - AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) + if test "x$succeeded" != "xyes" ; then + if test "x$_version" = "x0" ; then + AC_MSG_NOTICE([[We could not detect the boost libraries (version $1 or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in . See http://randspringer.de/boost for more documentation.]]) else AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).]) fi # execute ACTION-IF-NOT-FOUND (if present): ifelse([$3], , :, [$3]) else - AC_SUBST(BOOST_CPPFLAGS) - AC_SUBST(BOOST_LDFLAGS) AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available]) # execute ACTION-IF-FOUND (if present): ifelse([$2], , :, [$2]) @@ -267,6 +299,5 @@ if test "x$want_boost" = "xyes"; then CPPFLAGS="$CPPFLAGS_SAVED" LDFLAGS="$LDFLAGS_SAVED" -fi ]) diff --git a/m4/ax_boost_chrono.m4 b/m4/ax_boost_chrono.m4 index 9b3958ec74..4cd3b86041 100644 --- a/m4/ax_boost_chrono.m4 +++ b/m4/ax_boost_chrono.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_chrono.html # =========================================================================== # # SYNOPSIS @@ -8,7 +8,7 @@ # # DESCRIPTION # -# Test for System library from the Boost C++ libraries. The macro requires +# Test for Chrono library from the Boost C++ libraries. The macro requires # a preceding call to AX_BOOST_BASE. Further documentation is available at # . # @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 1 +#serial 5 AC_DEFUN([AX_BOOST_CHRONO], [ @@ -68,7 +68,7 @@ AC_DEFUN([AX_BOOST_CHRONO], CXXFLAGS_SAVE=$CXXFLAGS AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::chrono::system_clock::time_point time;]])], + [[boost::chrono::system_clock::time_point* time = new boost::chrono::system_clock::time_point; delete time;]])], ax_cv_boost_chrono=yes, ax_cv_boost_chrono=no) CXXFLAGS=$CXXFLAGS_SAVE AC_LANG_POP([C++]) @@ -105,7 +105,7 @@ AC_DEFUN([AX_BOOST_CHRONO], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Chrono library!) fi if test "x$link_chrono" = "xno"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/m4/ax_boost_date_time.m4 b/m4/ax_boost_date_time.m4 index ec9c0445a2..7623d04f20 100644 --- a/m4/ax_boost_date_time.m4 +++ b/m4/ax_boost_date_time.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_date_time.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_date_time.html # =========================================================================== # # SYNOPSIS @@ -30,7 +30,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 21 +#serial 23 AC_DEFUN([AX_BOOST_DATE_TIME], [ @@ -100,7 +100,7 @@ AC_DEFUN([AX_BOOST_DATE_TIME], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Date_Time library!) fi if test "x$link_date_time" != "xyes"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/m4/ax_boost_filesystem.m4 b/m4/ax_boost_filesystem.m4 index f162163cdc..12f7bc5e2e 100644 --- a/m4/ax_boost_filesystem.m4 +++ b/m4/ax_boost_filesystem.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_filesystem.html # =========================================================================== # # SYNOPSIS @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 26 +#serial 28 AC_DEFUN([AX_BOOST_FILESYSTEM], [ @@ -104,7 +104,7 @@ AC_DEFUN([AX_BOOST_FILESYSTEM], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Filesystem library!) fi if test "x$link_filesystem" != "xyes"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/m4/ax_boost_iostreams.m4 b/m4/ax_boost_iostreams.m4 index 9d736268ab..980237cf0f 100644 --- a/m4/ax_boost_iostreams.m4 +++ b/m4/ax_boost_iostreams.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_iostreams.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_iostreams.html # =========================================================================== # # SYNOPSIS @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 20 +#serial 22 AC_DEFUN([AX_BOOST_IOSTREAMS], [ @@ -103,7 +103,7 @@ AC_DEFUN([AX_BOOST_IOSTREAMS], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::IOStreams library!) fi if test "x$link_iostreams" != "xyes"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/m4/ax_boost_locale.m4 b/m4/ax_boost_locale.m4 index d48e475c7b..0f7562e5a8 100644 --- a/m4/ax_boost_locale.m4 +++ b/m4/ax_boost_locale.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_locale.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_locale.html # =========================================================================== # # SYNOPSIS @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 1 +#serial 3 AC_DEFUN([AX_BOOST_LOCALE], [ @@ -86,14 +86,14 @@ AC_DEFUN([AX_BOOST_LOCALE], ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_LOCALE_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOCALE_LIB) link_locale="yes"; break], - [link_locale="no"],[$BOOST_ICU_LIBS]) + [link_locale="no"]) done if test "x$link_locale" != "xyes"; then for libextension in `ls $BOOSTLIBDIR/boost_locale*.dll* $BOOSTLIBDIR/boost_locale*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_locale.*\)\.dll.*$;\1;' -e 's;^\(boost_locale.*\)\.a.*$;\1;'` ; do ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_LOCALE_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOCALE_LIB) link_locale="yes"; break], - [link_locale="no"],[$BOOST_ICU_LIBS]) + [link_locale="no"]) done fi @@ -101,12 +101,12 @@ AC_DEFUN([AX_BOOST_LOCALE], for ax_lib in $ax_boost_user_locale_lib boost_locale-$ax_boost_user_locale_lib; do AC_CHECK_LIB($ax_lib, exit, [BOOST_LOCALE_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOCALE_LIB) link_locale="yes"; break], - [link_locale="no"],[$BOOST_ICU_LIBS]) + [link_locale="no"]) done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Locale library!) fi if test "x$link_locale" = "xno"; then AC_MSG_ERROR(Could not link against $ax_lib !) @@ -117,4 +117,3 @@ AC_DEFUN([AX_BOOST_LOCALE], LDFLAGS="$LDFLAGS_SAVED" fi ]) - diff --git a/m4/ax_boost_log.m4 b/m4/ax_boost_log.m4 index 9f0ebbf959..99f1c93e33 100755 --- a/m4/ax_boost_log.m4 +++ b/m4/ax_boost_log.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_log.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_log.html # =========================================================================== # # SYNOPSIS @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 1 +#serial 3 AC_DEFUN([AX_BOOST_LOG], [ @@ -87,7 +87,7 @@ AC_DEFUN([AX_BOOST_LOG], ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_LOG_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOG_LIB) link_log="yes"; break], - [link_log="no"],[$BOOST_ICU_LIBS]) + [link_log="no"]) done if test "x$link_log" != "xyes"; then @@ -95,7 +95,7 @@ AC_DEFUN([AX_BOOST_LOG], ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_LOG_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOG_LIB) link_log="yes"; break], - [link_log="no"],[$BOOST_ICU_LIBS]) + [link_log="no"]) done fi @@ -103,12 +103,12 @@ AC_DEFUN([AX_BOOST_LOG], for ax_lib in $ax_boost_user_log_lib boost_log-$ax_boost_user_log_lib; do AC_CHECK_LIB($ax_lib, exit, [BOOST_LOG_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOG_LIB) link_log="yes"; break], - [link_log="no"],[$BOOST_ICU_LIBS]) + [link_log="no"]) done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Log library!) fi if test "x$link_log" = "xno"; then diff --git a/m4/ax_boost_log_setup.m4 b/m4/ax_boost_log_setup.m4 index e7258cd90f..7a6ac895f1 100644 --- a/m4/ax_boost_log_setup.m4 +++ b/m4/ax_boost_log_setup.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_log_setup.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_log_setup.html # =========================================================================== # # SYNOPSIS @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 2 +#serial 3 AC_DEFUN([AX_BOOST_LOG_SETUP], [ @@ -78,7 +78,7 @@ AC_DEFUN([AX_BOOST_LOG_SETUP], ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_LOG_SETUP_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOG_SETUP_LIB) link_log_setup="yes"; break], - [link_log_setup="no"],[$BOOST_ICU_LIBS]) + [link_log_setup="no"]) done if test "x$link_log_setup" != "xyes"; then @@ -86,7 +86,7 @@ AC_DEFUN([AX_BOOST_LOG_SETUP], ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_LOG_SETUP_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOG_SETUP_LIB) link_log_setup="yes"; break], - [link_log_setup="no"],[$BOOST_ICU_LIBS]) + [link_log_setup="no"]) done fi @@ -94,13 +94,13 @@ AC_DEFUN([AX_BOOST_LOG_SETUP], for ax_lib in $ax_boost_user_log_setup_lib boost_log_setup-$ax_boost_user_log_setup_lib; do AC_CHECK_LIB($ax_lib, exit, [BOOST_LOG_SETUP_LIB="-l$ax_lib"; AC_SUBST(BOOST_LOG_SETUP_LIB) link_log_setup="yes"; break], - [link_log_setup="no"],[$BOOST_ICU_LIBS]) + [link_log_setup="no"]) done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Log_Setup library!) fi if test "x$link_log_setup" = "xno"; then diff --git a/m4/ax_boost_program_options.m4 b/m4/ax_boost_program_options.m4 index 65a39c8c70..7d23da4648 100644 --- a/m4/ax_boost_program_options.m4 +++ b/m4/ax_boost_program_options.m4 @@ -1,6 +1,6 @@ -# ============================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_boost_program_options.html -# ============================================================================ +# ============================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_boost_program_options.html +# ============================================================================= # # SYNOPSIS # @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 22 +#serial 26 AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], [ @@ -63,9 +63,9 @@ AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], AC_CACHE_CHECK([whether the Boost::Program_Options library is available], ax_cv_boost_program_options, [AC_LANG_PUSH(C++) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::program_options::options_description generic("Generic options"); + [[boost::program_options::error err("Error message"); return 0;]])], ax_cv_boost_program_options=yes, ax_cv_boost_program_options=no) AC_LANG_POP([C++]) @@ -96,7 +96,7 @@ AC_DEFUN([AX_BOOST_PROGRAM_OPTIONS], done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Program_Options library!) fi if test "x$link_program_options" != "xyes"; then AC_MSG_ERROR([Could not link against [$ax_lib] !]) diff --git a/m4/ax_boost_regex.m4 b/m4/ax_boost_regex.m4 index 02c3372c2e..e2413c24fe 100644 --- a/m4/ax_boost_regex.m4 +++ b/m4/ax_boost_regex.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_regex.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_regex.html # =========================================================================== # # SYNOPSIS @@ -30,7 +30,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 22 +#serial 23 AC_DEFUN([AX_BOOST_REGEX], [ @@ -79,14 +79,14 @@ AC_DEFUN([AX_BOOST_REGEX], ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_REGEX_LIB="-l$ax_lib"; AC_SUBST(BOOST_REGEX_LIB) link_regex="yes"; break], - [link_regex="no"],[$BOOST_ICU_LIBS]) + [link_regex="no"]) done if test "x$link_regex" != "xyes"; then for libextension in `ls $BOOSTLIBDIR/boost_regex*.dll* $BOOSTLIBDIR/boost_regex*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^\(boost_regex.*\)\.dll.*$;\1;' -e 's;^\(boost_regex.*\)\.a.*$;\1;'` ; do ax_lib=${libextension} AC_CHECK_LIB($ax_lib, exit, [BOOST_REGEX_LIB="-l$ax_lib"; AC_SUBST(BOOST_REGEX_LIB) link_regex="yes"; break], - [link_regex="no"],[$BOOST_ICU_LIBS]) + [link_regex="no"]) done fi @@ -94,7 +94,7 @@ AC_DEFUN([AX_BOOST_REGEX], for ax_lib in $ax_boost_user_regex_lib boost_regex-$ax_boost_user_regex_lib; do AC_CHECK_LIB($ax_lib, main, [BOOST_REGEX_LIB="-l$ax_lib"; AC_SUBST(BOOST_REGEX_LIB) link_regex="yes"; break], - [link_regex="no"],[$BOOST_ICU_LIBS]) + [link_regex="no"]) done fi if test "x$ax_lib" = "x"; then diff --git a/m4/ax_boost_system.m4 b/m4/ax_boost_system.m4 index c4c45559d8..323e2a676a 100644 --- a/m4/ax_boost_system.m4 +++ b/m4/ax_boost_system.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_system.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_system.html # =========================================================================== # # SYNOPSIS @@ -31,7 +31,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 17 +#serial 20 AC_DEFUN([AX_BOOST_SYSTEM], [ @@ -68,9 +68,10 @@ AC_DEFUN([AX_BOOST_SYSTEM], ax_cv_boost_system, [AC_LANG_PUSH([C++]) CXXFLAGS_SAVE=$CXXFLAGS + CXXFLAGS= AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::system::system_category]])], + [[boost::system::error_category *a = 0;]])], ax_cv_boost_system=yes, ax_cv_boost_system=no) CXXFLAGS=$CXXFLAGS_SAVE AC_LANG_POP([C++]) @@ -107,7 +108,7 @@ AC_DEFUN([AX_BOOST_SYSTEM], fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::System library!) fi if test "x$link_system" = "xno"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/m4/ax_boost_thread.m4 b/m4/ax_boost_thread.m4 index 79e12cdb4e..75e80e6e75 100644 --- a/m4/ax_boost_thread.m4 +++ b/m4/ax_boost_thread.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_boost_thread.html +# https://www.gnu.org/software/autoconf-archive/ax_boost_thread.html # =========================================================================== # # SYNOPSIS @@ -30,73 +30,96 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 27 +#serial 33 AC_DEFUN([AX_BOOST_THREAD], [ - AC_ARG_WITH([boost-thread], - AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@], - [use the Thread library from boost - it is possible to specify a certain library for the linker - e.g. --with-boost-thread=boost_thread-gcc-mt ]), + AC_ARG_WITH([boost-thread], + AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@], + [use the Thread library from boost - + it is possible to specify a certain library for the linker + e.g. --with-boost-thread=boost_thread-gcc-mt ]), [ - if test "$withval" = "no"; then - want_boost="no" - elif test "$withval" = "yes"; then + if test "$withval" = "yes"; then want_boost="yes" ax_boost_user_thread_lib="" else - want_boost="yes" - ax_boost_user_thread_lib="$withval" - fi + want_boost="yes" + ax_boost_user_thread_lib="$withval" + fi ], [want_boost="yes"] - ) + ) - if test "x$want_boost" = "xyes"; then + if test "x$want_boost" = "xyes"; then AC_REQUIRE([AC_PROG_CC]) AC_REQUIRE([AC_CANONICAL_BUILD]) - CPPFLAGS_SAVED="$CPPFLAGS" - CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" - export CPPFLAGS + CPPFLAGS_SAVED="$CPPFLAGS" + CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" + export CPPFLAGS - LDFLAGS_SAVED="$LDFLAGS" - LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" - export LDFLAGS + LDFLAGS_SAVED="$LDFLAGS" + LDFLAGS="$LDFLAGS $BOOST_LDFLAGS" + export LDFLAGS AC_CACHE_CHECK(whether the Boost::Thread library is available, - ax_cv_boost_thread, + ax_cv_boost_thread, [AC_LANG_PUSH([C++]) - CXXFLAGS_SAVE=$CXXFLAGS + CXXFLAGS_SAVE=$CXXFLAGS + + case "x$host_os" in + xsolaris ) + CXXFLAGS="-pthreads $CXXFLAGS" + break; + ;; + xmingw32 ) + CXXFLAGS="-mthreads $CXXFLAGS" + break; + ;; + *android* ) + break; + ;; + * ) + CXXFLAGS="-pthread $CXXFLAGS" + break; + ;; + esac - if test "x$host_os" = "xsolaris" ; then - CXXFLAGS="-pthreads $CXXFLAGS" - elif test "x$host_os" = "xmingw32" ; then - CXXFLAGS="-mthreads $CXXFLAGS" - else - CXXFLAGS="-pthread $CXXFLAGS" - fi - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], - [[boost::thread_group thrds; - return 0;]])], - ax_cv_boost_thread=yes, ax_cv_boost_thread=no) - CXXFLAGS=$CXXFLAGS_SAVE + AC_COMPILE_IFELSE([ + AC_LANG_PROGRAM( + [[@%:@include ]], + [[boost::thread_group thrds; + return 0;]])], + ax_cv_boost_thread=yes, ax_cv_boost_thread=no) + CXXFLAGS=$CXXFLAGS_SAVE AC_LANG_POP([C++]) - ]) - if test "x$ax_cv_boost_thread" = "xyes"; then - if test "x$host_os" = "xsolaris" ; then - BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS" - elif test "x$host_os" = "xmingw32" ; then - BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS" - else - BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS" - fi + ]) + if test "x$ax_cv_boost_thread" = "xyes"; then + case "x$host_os" in + xsolaris ) + BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS" + break; + ;; + xmingw32 ) + BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS" + break; + ;; + *android* ) + break; + ;; + * ) + BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS" + break; + ;; + esac - AC_SUBST(BOOST_CPPFLAGS) + AC_SUBST(BOOST_CPPFLAGS) - AC_DEFINE(HAVE_BOOST_THREAD,,[define if the Boost::Thread library is available]) + AC_DEFINE(HAVE_BOOST_THREAD,, + [define if the Boost::Thread library is available]) BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'` - LDFLAGS_SAVE=$LDFLAGS + LDFLAGS_SAVE=$LDFLAGS case "x$host_os" in *bsd* ) LDFLAGS="-pthread $LDFLAGS" @@ -106,44 +129,59 @@ AC_DEFUN([AX_BOOST_THREAD], if test "x$ax_boost_user_thread_lib" = "x"; then for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], + AC_CHECK_LIB($ax_lib, exit, + [link_thread="yes"; break], [link_thread="no"]) - done + done if test "x$link_thread" != "xyes"; then for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do ax_lib=${libextension} - AC_CHECK_LIB($ax_lib, exit, - [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], + AC_CHECK_LIB($ax_lib, exit, + [link_thread="yes"; break], [link_thread="no"]) - done + done fi else for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do - AC_CHECK_LIB($ax_lib, exit, - [BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break], + AC_CHECK_LIB($ax_lib, exit, + [link_thread="yes"; break], [link_thread="no"]) done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Thread library!) fi - if test "x$link_thread" = "xno"; then - AC_MSG_ERROR(Could not link against $ax_lib !) - else - case "x$host_os" in - *bsd* ) - BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS" - break; - ;; - esac - - fi - fi + if test "x$link_thread" = "xno"; then + AC_MSG_ERROR(Could not link against $ax_lib !) + else + BOOST_THREAD_LIB="-l$ax_lib" + case "x$host_os" in + *bsd* ) + BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS" + break; + ;; + xsolaris ) + BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread" + break; + ;; + xmingw32 ) + break; + ;; + *android* ) + break; + ;; + * ) + BOOST_THREAD_LIB="$BOOST_THREAD_LIB -lpthread" + break; + ;; + esac + AC_SUBST(BOOST_THREAD_LIB) + fi + fi - CPPFLAGS="$CPPFLAGS_SAVED" - LDFLAGS="$LDFLAGS_SAVED" - fi + CPPFLAGS="$CPPFLAGS_SAVED" + LDFLAGS="$LDFLAGS_SAVED" + fi ]) diff --git a/m4/ax_boost_unit_test_framework.m4 b/m4/ax_boost_unit_test_framework.m4 index 1115f55121..4cca32fcfd 100644 --- a/m4/ax_boost_unit_test_framework.m4 +++ b/m4/ax_boost_unit_test_framework.m4 @@ -1,6 +1,6 @@ -# ================================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html -# ================================================================================ +# ================================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_boost_unit_test_framework.html +# ================================================================================= # # SYNOPSIS # @@ -29,7 +29,7 @@ # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 19 +#serial 22 AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], [ @@ -66,7 +66,7 @@ AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], [AC_LANG_PUSH([C++]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], [[using boost::unit_test::test_suite; - test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); return 0;]])], + test_suite* test= BOOST_TEST_SUITE( "Unit test example 1" ); if (test == NULL) { return 1; } else { return 0; }]])], ax_cv_boost_unit_test_framework=yes, ax_cv_boost_unit_test_framework=no) AC_LANG_POP([C++]) ]) @@ -124,7 +124,7 @@ AC_DEFUN([AX_BOOST_UNIT_TEST_FRAMEWORK], done fi if test "x$ax_lib" = "x"; then - AC_MSG_ERROR(Could not find a version of the library!) + AC_MSG_ERROR(Could not find a version of the Boost::Unit_Test_Framework library!) fi if test "x$link_unit_test_framework" != "xyes"; then AC_MSG_ERROR(Could not link against $ax_lib !) diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 index 51df0c09a7..bd753b34d7 100644 --- a/m4/ax_check_compile_flag.m4 +++ b/m4/ax_check_compile_flag.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html # =========================================================================== # # SYNOPSIS @@ -29,36 +29,15 @@ # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. -#serial 3 +#serial 6 AC_DEFUN([AX_CHECK_COMPILE_FLAG], -[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS @@ -67,7 +46,7 @@ AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [ [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) _AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 index db899ddd08..03a30ce4c7 100644 --- a/m4/ax_check_link_flag.m4 +++ b/m4/ax_check_link_flag.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html # =========================================================================== # # SYNOPSIS @@ -29,36 +29,16 @@ # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. -#serial 3 +#serial 6 AC_DEFUN([AX_CHECK_LINK_FLAG], -[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl +[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF +AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ ax_check_save_flags=$LDFLAGS LDFLAGS="$LDFLAGS $4 $1" @@ -66,7 +46,7 @@ AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [ [AS_VAR_SET(CACHEVAR,[yes])], [AS_VAR_SET(CACHEVAR,[no])]) LDFLAGS=$ax_check_save_flags]) -AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes], +AS_VAR_IF(CACHEVAR,yes, [m4_default([$2], :)], [m4_default([$3], :)]) AS_VAR_POPDEF([CACHEVAR])dnl diff --git a/m4/ax_check_preproc_flag.m4 b/m4/ax_check_preproc_flag.m4 index ca1d5ee2b6..e43560fbd3 100644 --- a/m4/ax_check_preproc_flag.m4 +++ b/m4/ax_check_preproc_flag.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html +# https://www.gnu.org/software/autoconf-archive/ax_check_preproc_flag.html # =========================================================================== # # SYNOPSIS @@ -29,33 +29,12 @@ # Copyright (c) 2008 Guido U. Draheim # Copyright (c) 2011 Maarten Bosmans # -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. -#serial 4 +#serial 6 AC_DEFUN([AX_CHECK_PREPROC_FLAG], [AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000000..9413da624d --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,962 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for no added switch, and then for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# Copyright (c) 2020 Jason Merrill +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 12 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [], [dnl + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi]) + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L + +]]) diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4 index af37acdb5c..1733fd85f9 100644 --- a/m4/ax_cxx_compile_stdcxx_11.m4 +++ b/m4/ax_cxx_compile_stdcxx_11.m4 @@ -1,133 +1,39 @@ -# ============================================================================ -# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html -# ============================================================================ +# ============================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================= # # SYNOPSIS # -# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) +# AX_CXX_COMPILE_STDCXX_11([ext|noext], [mandatory|optional]) # # DESCRIPTION # # Check for baseline language coverage in the compiler for the C++11 -# standard; if necessary, add switches to CXXFLAGS to enable support. +# standard; if necessary, add switches to CXX and CXXCPP to enable +# support. # -# The first argument, if specified, indicates whether you insist on an -# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. -# -std=c++11). If neither is specified, you get whatever works, with -# preference for an extended mode. -# -# The second argument, if specified 'mandatory' or if left unspecified, -# indicates that baseline C++11 support is required and that the macro -# should error out if no mode with that support is found. If specified -# 'optional', then configuration proceeds regardless, after defining -# HAVE_CXX11 if and only if a supporting mode is found. +# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX +# macro with the version set to C++11. The two optional arguments are +# forwarded literally as the second and third argument respectively. +# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for +# more information. If you want to use this macro, you also need to +# download the ax_cxx_compile_stdcxx.m4 file. # # LICENSE # # Copyright (c) 2008 Benjamin Kosnik # Copyright (c) 2012 Zack Weinberg # Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler # # Copying and distribution of this file, with or without modification, are # permitted in any medium without royalty provided the copyright notice # and this notice are preserved. This file is offered as-is, without any # warranty. -#serial 3 - -m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ - template - struct check - { - static_assert(sizeof(int) <= sizeof(T), "not big enough"); - }; - - typedef check> right_angle_brackets; - - int a; - decltype(a) b; - - typedef check check_type; - check_type c; - check_type&& cr = static_cast(c); - - auto d = a; -]) - -AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl - m4_if([$1], [], [], - [$1], [ext], [], - [$1], [noext], [], - [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl - m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], - [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], - [$2], [optional], [ax_cxx_compile_cxx11_required=false], - [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl - AC_LANG_PUSH([C++])dnl - ac_success=no - AC_CACHE_CHECK(whether $CXX supports C++11 features by default, - ax_cv_cxx_compile_cxx11, - [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [ax_cv_cxx_compile_cxx11=yes], - [ax_cv_cxx_compile_cxx11=no])]) - if test x$ax_cv_cxx_compile_cxx11 = xyes; then - ac_success=yes - fi - - m4_if([$1], [noext], [], [dnl - if test x$ac_success = xno; then - for switch in -std=gnu++11 -std=gnu++0x; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, - $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) - if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" - ac_success=yes - break - fi - done - fi]) - - m4_if([$1], [ext], [], [dnl - if test x$ac_success = xno; then - for switch in -std=c++11 -std=c++0x; do - cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) - AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, - $cachevar, - [ac_save_CXXFLAGS="$CXXFLAGS" - CXXFLAGS="$CXXFLAGS $switch" - AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], - [eval $cachevar=yes], - [eval $cachevar=no]) - CXXFLAGS="$ac_save_CXXFLAGS"]) - if eval test x\$$cachevar = xyes; then - CXXFLAGS="$CXXFLAGS $switch" - ac_success=yes - break - fi - done - fi]) - AC_LANG_POP([C++]) - if test x$ax_cxx_compile_cxx11_required = xtrue; then - if test x$ac_success = xno; then - AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) - fi - else - if test x$ac_success = xno; then - HAVE_CXX11=0 - AC_MSG_NOTICE([No compiler with C++11 support was found]) - else - HAVE_CXX11=1 - AC_DEFINE(HAVE_CXX11,1, - [define if the compiler supports basic C++11 syntax]) - fi +#serial 18 - AC_SUBST(HAVE_CXX11) - fi -]) +AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [AX_CXX_COMPILE_STDCXX([11], [$1], [$2])]) diff --git a/m4/ax_java_devel.m4 b/m4/ax_java_devel.m4 deleted file mode 100644 index ee1792b6bd..0000000000 --- a/m4/ax_java_devel.m4 +++ /dev/null @@ -1,57 +0,0 @@ -# Java discovery wrapper, defines JAVA_CPPFLAGS. - -AC_DEFUN([AX_JAVA_DEVEL], [ - - AX_PROG_JAVAC - AX_PROG_JAVA - AX_PROG_JAR - AX_JNI_INCLUDE_DIR - AC_PROG_MKDIR_P - - JAVA_CPPFLAGS= - for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS; do - JAVA_CPPFLAGS="$JAVA_CPPFLAGS -I$JNI_INCLUDE_DIR" - done - - # Set CPP compile flags. - AC_SUBST([JAVA_CPPFLAGS]) - - # Install .class files to ${datadir}/java. - AC_SUBST([javaexecdir], [${datadir}/java]) - - # Install .jar files to ${datadir}/java (also). - AC_SUBST([jarexecdir], [${datadir}/java]) - - # Build .class files in hidden directory. - AC_SUBST([java_builddir], [.class]) - $MKDIR_P $java_builddir - - # Build .jar files in hidden directory. - AC_SUBST([jar_builddir], [.jar]) - $MKDIR_P $jar_builddir - - # Instruct Automake to build .class files in ${java_builddir}. - AC_SUBST([JAVAROOT], [${java_builddir}]) - - ## Automake doesn't clean the modified JAVAROOT or jar builds, - ## so add following pattern in Makefile.am instead: - # - # dist_noinst_JAVA = \ - # [java files listed here] - # - # CLEANFILES = ${java_builddir}/*.class - # - # distclean-local: - # rm -rf ${java_builddir} ${jar_builddir} - # - ## Automake doesn't build .jar files, - ## so use following pattern in Makefile.am instead: - # - # nodist_jarexec_DATA = \ - # ${jar_builddir}/[jar name here]-${VERSION}.jar - # - # ${nodist_jarexec_DATA}: classnoinst.stamp - # ${JAR} cf ${JARFLAGS} ${nodist_jarexec_DATA} -C ${java_builddir} . - # - # CLEANFILES += ${jar_builddir}/*.jar -]) diff --git a/m4/ax_jni_include_dir.m4 b/m4/ax_jni_include_dir.m4 deleted file mode 100644 index b664d80b85..0000000000 --- a/m4/ax_jni_include_dir.m4 +++ /dev/null @@ -1,126 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_jni_include_dir.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_JNI_INCLUDE_DIR -# -# DESCRIPTION -# -# AX_JNI_INCLUDE_DIR finds include directories needed for compiling -# programs using the JNI interface. -# -# JNI include directories are usually in the Java distribution. This is -# deduced from the value of $JAVA_HOME, $JAVAC, or the path to "javac", in -# that order. When this macro completes, a list of directories is left in -# the variable JNI_INCLUDE_DIRS. -# -# Example usage follows: -# -# AX_JNI_INCLUDE_DIR -# -# for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS -# do -# CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" -# done -# -# If you want to force a specific compiler: -# -# - at the configure.in level, set JAVAC=yourcompiler before calling -# AX_JNI_INCLUDE_DIR -# -# - at the configure level, setenv JAVAC -# -# Note: This macro can work with the autoconf M4 macros for Java programs. -# This particular macro is not part of the original set of macros. -# -# LICENSE -# -# Copyright (c) 2008 Don Anderson -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 10 - -AU_ALIAS([AC_JNI_INCLUDE_DIR], [AX_JNI_INCLUDE_DIR]) -AC_DEFUN([AX_JNI_INCLUDE_DIR],[ - -JNI_INCLUDE_DIRS="" - -if test "x$JAVA_HOME" != x; then - _JTOPDIR="$JAVA_HOME" -else - if test "x$JAVAC" = x; then - JAVAC=javac - fi - AC_PATH_PROG([_ACJNI_JAVAC], [$JAVAC], [no]) - if test "x$_ACJNI_JAVAC" = xno; then - AC_MSG_ERROR([cannot find JDK; try setting \$JAVAC or \$JAVA_HOME]) - fi - _ACJNI_FOLLOW_SYMLINKS("$_ACJNI_JAVAC") - _JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[[^/]]*$::'` -fi - -case "$host_os" in - darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - _JINC="$_JTOPDIR/Headers";; - *) _JINC="$_JTOPDIR/include";; -esac -_AS_ECHO_LOG([_JTOPDIR=$_JTOPDIR]) -_AS_ECHO_LOG([_JINC=$_JINC]) - -# On Mac OS X 10.6.4, jni.h is a symlink: -# /System/Library/Frameworks/JavaVM.framework/Versions/Current/Headers/jni.h -# -> ../../CurrentJDK/Headers/jni.h. -AC_CHECK_FILE([$_JINC/jni.h], - [JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JINC"], - [_JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[[^/]]*$::'` - AC_CHECK_FILE([$_JTOPDIR/include/jni.h], - [JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include"], - AC_MSG_ERROR([cannot find JDK header files])) - ]) - -# get the likely subdirectories for system specific java includes -case "$host_os" in -bsdi*) _JNI_INC_SUBDIRS="bsdos";; -freebsd*) _JNI_INC_SUBDIRS="freebsd";; -linux*) _JNI_INC_SUBDIRS="linux genunix";; -osf*) _JNI_INC_SUBDIRS="alpha";; -solaris*) _JNI_INC_SUBDIRS="solaris";; -mingw*) _JNI_INC_SUBDIRS="win32";; -cygwin*) _JNI_INC_SUBDIRS="win32";; -*) _JNI_INC_SUBDIRS="genunix";; -esac - -# add any subdirectories that are present -for JINCSUBDIR in $_JNI_INC_SUBDIRS -do - if test -d "$_JTOPDIR/include/$JINCSUBDIR"; then - JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$JINCSUBDIR" - fi -done -]) - -# _ACJNI_FOLLOW_SYMLINKS -# Follows symbolic links on , -# finally setting variable _ACJNI_FOLLOWED -# ---------------------------------------- -AC_DEFUN([_ACJNI_FOLLOW_SYMLINKS],[ -# find the include directory relative to the javac executable -_cur="$1" -while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do - AC_MSG_CHECKING([symlink for $_cur]) - _slink=`ls -ld "$_cur" | sed 's/.* -> //'` - case "$_slink" in - /*) _cur="$_slink";; - # 'X' avoids triggering unwanted echo options. - *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[[^/]]*$::'`"$_slink";; - esac - AC_MSG_RESULT([$_cur]) -done -_ACJNI_FOLLOWED="$_cur" -])# _ACJNI diff --git a/m4/ax_prog_jar.m4 b/m4/ax_prog_jar.m4 deleted file mode 100644 index 3c60fcaf2d..0000000000 --- a/m4/ax_prog_jar.m4 +++ /dev/null @@ -1,49 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_jar.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_JAR -# -# DESCRIPTION -# -# AX_PROG_JAR tests for an existing jar program. It uses the environment -# variable JAR then tests in sequence various common jar programs. -# -# If you want to force a specific compiler: -# -# - at the configure.in level, set JAR=yourcompiler before calling -# AX_PROG_JAR -# -# - at the configure level, setenv JAR -# -# You can use the JAR variable in your Makefile.in, with @JAR@. -# -# Note: This macro depends on the autoconf M4 macros for Java programs. It -# is VERY IMPORTANT that you download that whole set, some macros depend -# on other. Unfortunately, the autoconf archive does not support the -# concept of set of macros, so I had to break it for submission. -# -# The general documentation of those macros, as well as the sample -# configure.in, is included in the AX_PROG_JAVA macro. -# -# LICENSE -# -# Copyright (c) 2008 Egon Willighagen -# -# Copying and distribution of this file, with or without modification, are -# permitted in any medium without royalty provided the copyright notice -# and this notice are preserved. This file is offered as-is, without any -# warranty. - -#serial 7 - -AU_ALIAS([AC_PROG_JAR], [AX_PROG_JAR]) -AC_DEFUN([AX_PROG_JAR],[ -AS_IF([test "x$JAVAPREFIX" = x], - [test "x$JAR" = x && AC_CHECK_PROGS([JAR], [jar])], - [test "x$JAR" = x && AC_CHECK_PROGS([JAR], [jar], [], [$JAVAPREFIX/bin])]) -test "x$JAR" = x && AC_MSG_ERROR([no acceptable jar program found in \$PATH]) -AC_PROVIDE([$0])dnl -]) diff --git a/m4/ax_prog_java.m4 b/m4/ax_prog_java.m4 deleted file mode 100644 index 03961db5b7..0000000000 --- a/m4/ax_prog_java.m4 +++ /dev/null @@ -1,115 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_java.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_JAVA -# -# DESCRIPTION -# -# Here is a summary of the main macros: -# -# AX_PROG_JAVAC: finds a Java compiler. -# -# AX_PROG_JAVA: finds a Java virtual machine. -# -# AX_CHECK_CLASS: finds if we have the given class (beware of CLASSPATH!). -# -# AX_CHECK_RQRD_CLASS: finds if we have the given class and stops -# otherwise. -# -# AX_TRY_COMPILE_JAVA: attempt to compile user given source. -# -# AX_TRY_RUN_JAVA: attempt to compile and run user given source. -# -# AX_JAVA_OPTIONS: adds Java configure options. -# -# AX_PROG_JAVA tests an existing Java virtual machine. It uses the -# environment variable JAVA then tests in sequence various common Java -# virtual machines. For political reasons, it starts with the free ones. -# You *must* call [AX_PROG_JAVAC] before. -# -# If you want to force a specific VM: -# -# - at the configure.in level, set JAVA=yourvm before calling AX_PROG_JAVA -# -# (but after AC_INIT) -# -# - at the configure level, setenv JAVA -# -# You can use the JAVA variable in your Makefile.in, with @JAVA@. -# -# *Warning*: its success or failure can depend on a proper setting of the -# CLASSPATH env. variable. -# -# TODO: allow to exclude virtual machines (rationale: most Java programs -# cannot run with some VM like kaffe). -# -# Note: This is part of the set of autoconf M4 macros for Java programs. -# It is VERY IMPORTANT that you download the whole set, some macros depend -# on other. Unfortunately, the autoconf archive does not support the -# concept of set of macros, so I had to break it for submission. -# -# A Web page, with a link to the latest CVS snapshot is at -# . -# -# This is a sample configure.in Process this file with autoconf to produce -# a configure script. -# -# AC_INIT(UnTag.java) -# -# dnl Checks for programs. -# AC_CHECK_CLASSPATH -# AX_PROG_JAVAC -# AX_PROG_JAVA -# -# dnl Checks for classes -# AX_CHECK_RQRD_CLASS(org.xml.sax.Parser) -# AX_CHECK_RQRD_CLASS(com.jclark.xml.sax.Driver) -# -# AC_OUTPUT(Makefile) -# -# LICENSE -# -# Copyright (c) 2008 Stephane Bortzmeyer -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 9 - -AU_ALIAS([AC_PROG_JAVA], [AX_PROG_JAVA]) -AC_DEFUN([AX_PROG_JAVA],[ -m4_define([m4_ax_prog_java_list], [kaffe java])dnl -AS_IF([test "x$JAVAPREFIX" = x], - [test x$JAVA = x && AC_CHECK_PROGS([JAVA], [m4_ax_prog_java_list])], - [test x$JAVA = x && AC_CHECK_PROGS([JAVA], [m4_ax_prog_java_list], [], [$JAVAPREFIX/bin])]) -test x$JAVA = x && AC_MSG_ERROR([no acceptable Java virtual machine found in \$PATH]) -m4_undefine([m4_ax_prog_java_list])dnl -AX_PROG_JAVA_WORKS -AC_PROVIDE([$0])dnl -]) diff --git a/m4/ax_prog_java_works.m4 b/m4/ax_prog_java_works.m4 deleted file mode 100644 index 54e132afae..0000000000 --- a/m4/ax_prog_java_works.m4 +++ /dev/null @@ -1,134 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_java_works.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_JAVA_WORKS -# -# DESCRIPTION -# -# Internal use ONLY. -# -# Note: This is part of the set of autoconf M4 macros for Java programs. -# It is VERY IMPORTANT that you download the whole set, some macros depend -# on other. Unfortunately, the autoconf archive does not support the -# concept of set of macros, so I had to break it for submission. The -# general documentation, as well as the sample configure.in, is included -# in the AX_PROG_JAVA macro. -# -# LICENSE -# -# Copyright (c) 2008 Stephane Bortzmeyer -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 9 - -AU_ALIAS([AC_PROG_JAVA_WORKS], [AX_PROG_JAVA_WORKS]) -AC_DEFUN([AX_PROG_JAVA_WORKS], [ -AC_PATH_PROG(UUDECODE, uudecode, [no]) -if test x$UUDECODE != xno; then -AC_CACHE_CHECK([if uudecode can decode base 64 file], ac_cv_prog_uudecode_base64, [ -dnl /** -dnl * Test.java: used to test if java compiler works. -dnl */ -dnl public class Test -dnl { -dnl -dnl public static void -dnl main( String[] argv ) -dnl { -dnl System.exit (0); -dnl } -dnl -dnl } -cat << \EOF > Test.uue -begin-base64 644 Test.class -yv66vgADAC0AFQcAAgEABFRlc3QHAAQBABBqYXZhL2xhbmcvT2JqZWN0AQAE -bWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51 -bWJlclRhYmxlDAAKAAsBAARleGl0AQAEKEkpVgoADQAJBwAOAQAQamF2YS9s -YW5nL1N5c3RlbQEABjxpbml0PgEAAygpVgwADwAQCgADABEBAApTb3VyY2VG -aWxlAQAJVGVzdC5qYXZhACEAAQADAAAAAAACAAkABQAGAAEABwAAACEAAQAB -AAAABQO4AAyxAAAAAQAIAAAACgACAAAACgAEAAsAAQAPABAAAQAHAAAAIQAB -AAEAAAAFKrcAErEAAAABAAgAAAAKAAIAAAAEAAQABAABABMAAAACABQ= -==== -EOF -if $UUDECODE Test.uue; then - ac_cv_prog_uudecode_base64=yes -else - echo "configure: __oline__: uudecode had trouble decoding base 64 file 'Test.uue'" >&AS_MESSAGE_LOG_FD - echo "configure: failed file was:" >&AS_MESSAGE_LOG_FD - cat Test.uue >&AS_MESSAGE_LOG_FD - ac_cv_prog_uudecode_base64=no -fi -rm -f Test.uue]) -fi -if test x$ac_cv_prog_uudecode_base64 != xyes; then - rm -f Test.class - AC_MSG_WARN([I have to compile Test.class from scratch]) - if test x$ac_cv_prog_javac_works = xno; then - AC_MSG_ERROR([Cannot compile java source. $JAVAC does not work properly]) - fi - if test x$ac_cv_prog_javac_works = x; then - AX_PROG_JAVAC - fi -fi -AC_CACHE_CHECK(if $JAVA works, ac_cv_prog_java_works, [ -JAVA_TEST=Test.java -CLASS_TEST=Test.class -TEST=Test -changequote(, )dnl -cat << \EOF > $JAVA_TEST -/* [#]line __oline__ "configure" */ -public class Test { -public static void main (String args[]) { - System.exit (0); -} } -EOF -changequote([, ])dnl -if test x$ac_cv_prog_uudecode_base64 != xyes; then - if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) && test -s $CLASS_TEST; then - : - else - echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD - cat $JAVA_TEST >&AS_MESSAGE_LOG_FD - AC_MSG_ERROR(The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)) - fi -fi -if AC_TRY_COMMAND($JAVA -classpath . $JAVAFLAGS $TEST) >/dev/null 2>&1; then - ac_cv_prog_java_works=yes -else - echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD - cat $JAVA_TEST >&AS_MESSAGE_LOG_FD - AC_MSG_ERROR(The Java VM $JAVA failed (see config.log, check the CLASSPATH?)) -fi -rm -fr $JAVA_TEST $CLASS_TEST Test.uue -]) -AC_PROVIDE([$0])dnl -] -) diff --git a/m4/ax_prog_javac.m4 b/m4/ax_prog_javac.m4 deleted file mode 100644 index d061243cdb..0000000000 --- a/m4/ax_prog_javac.m4 +++ /dev/null @@ -1,79 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_javac.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_JAVAC -# -# DESCRIPTION -# -# AX_PROG_JAVAC tests an existing Java compiler. It uses the environment -# variable JAVAC then tests in sequence various common Java compilers. For -# political reasons, it starts with the free ones. -# -# If you want to force a specific compiler: -# -# - at the configure.in level, set JAVAC=yourcompiler before calling -# AX_PROG_JAVAC -# -# - at the configure level, setenv JAVAC -# -# You can use the JAVAC variable in your Makefile.in, with @JAVAC@. -# -# *Warning*: its success or failure can depend on a proper setting of the -# CLASSPATH env. variable. -# -# TODO: allow to exclude compilers (rationale: most Java programs cannot -# compile with some compilers like guavac). -# -# Note: This is part of the set of autoconf M4 macros for Java programs. -# It is VERY IMPORTANT that you download the whole set, some macros depend -# on other. Unfortunately, the autoconf archive does not support the -# concept of set of macros, so I had to break it for submission. The -# general documentation, as well as the sample configure.in, is included -# in the AX_PROG_JAVA macro. -# -# LICENSE -# -# Copyright (c) 2008 Stephane Bortzmeyer -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 7 - -AU_ALIAS([AC_PROG_JAVAC], [AX_PROG_JAVAC]) -AC_DEFUN([AX_PROG_JAVAC],[ -m4_define([m4_ax_prog_javac_list],["gcj -C" guavac jikes javac])dnl -AS_IF([test "x$JAVAPREFIX" = x], - [test "x$JAVAC" = x && AC_CHECK_PROGS([JAVAC], [m4_ax_prog_javac_list])], - [test "x$JAVAC" = x && AC_CHECK_PROGS([JAVAC], [m4_ax_prog_javac_list], [], [$JAVAPREFIX/bin])]) -m4_undefine([m4_ax_prog_javac_list])dnl -test "x$JAVAC" = x && AC_MSG_ERROR([no acceptable Java compiler found in \$PATH]) -AX_PROG_JAVAC_WORKS -AC_PROVIDE([$0])dnl -]) diff --git a/m4/ax_prog_javac_works.m4 b/m4/ax_prog_javac_works.m4 deleted file mode 100644 index 7dfa1e37d8..0000000000 --- a/m4/ax_prog_javac_works.m4 +++ /dev/null @@ -1,72 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_prog_javac_works.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PROG_JAVAC_WORKS -# -# DESCRIPTION -# -# Internal use ONLY. -# -# Note: This is part of the set of autoconf M4 macros for Java programs. -# It is VERY IMPORTANT that you download the whole set, some macros depend -# on other. Unfortunately, the autoconf archive does not support the -# concept of set of macros, so I had to break it for submission. The -# general documentation, as well as the sample configure.in, is included -# in the AX_PROG_JAVA macro. -# -# LICENSE -# -# Copyright (c) 2008 Stephane Bortzmeyer -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation; either version 2 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 6 - -AU_ALIAS([AC_PROG_JAVAC_WORKS], [AX_PROG_JAVAC_WORKS]) -AC_DEFUN([AX_PROG_JAVAC_WORKS],[ -AC_CACHE_CHECK([if $JAVAC works], ac_cv_prog_javac_works, [ -JAVA_TEST=Test.java -CLASS_TEST=Test.class -cat << \EOF > $JAVA_TEST -/* [#]line __oline__ "configure" */ -public class Test { -} -EOF -if AC_TRY_COMMAND($JAVAC $JAVACFLAGS $JAVA_TEST) >/dev/null 2>&1; then - ac_cv_prog_javac_works=yes -else - AC_MSG_ERROR([The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)]) - echo "configure: failed program was:" >&AS_MESSAGE_LOG_FD - cat $JAVA_TEST >&AS_MESSAGE_LOG_FD -fi -rm -f $JAVA_TEST $CLASS_TEST -]) -AC_PROVIDE([$0])dnl -]) diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 index d383ad5c6d..e5858e50c3 100644 --- a/m4/ax_pthread.m4 +++ b/m4/ax_pthread.m4 @@ -1,5 +1,5 @@ # =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_pthread.html +# https://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS @@ -14,24 +14,28 @@ # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # -# Also sets PTHREAD_CC to any special C compiler that is needed for -# multi-threaded programs (defaults to the value of CC otherwise). (This -# is necessary on AIX to use the special cc_r compiler alias.) +# Also sets PTHREAD_CC and PTHREAD_CXX to any special C compiler that is +# needed for multi-threaded programs (defaults to the value of CC +# respectively CXX otherwise). (This is necessary on e.g. AIX to use the +# special cc_r/CC_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, -# but also link it with them as well. e.g. you should link with +# but also to link with them as well. For example, you might link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS +# $PTHREAD_CXX $CXXFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # -# If you are only building threads programs, you may wish to use these +# If you are only building threaded programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" +# CXXFLAGS="$CXXFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" +# CXX="$PTHREAD_CXX" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant -# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name -# (e.g. PTHREAD_CREATE_UNDETACHED on AIX). +# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to +# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with @@ -55,6 +59,7 @@ # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. +# Copyright (c) 2019 Marc Stevens # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the @@ -67,7 +72,7 @@ # Public License for more details. # # You should have received a copy of the GNU General Public License along -# with this program. If not, see . +# with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure @@ -82,35 +87,41 @@ # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. -#serial 21 +#serial 30 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ -AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_CANONICAL_TARGET]) +AC_REQUIRE([AC_PROG_CC]) +AC_REQUIRE([AC_PROG_SED]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h -# requires special compiler flags (e.g. on True64 or Sequent). +# requires special compiler flags (e.g. on Tru64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: -if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then - save_CFLAGS="$CFLAGS" +if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then + ax_pthread_save_CC="$CC" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"]) + AS_IF([test "x$PTHREAD_CXX" != "x"], [CXX="$PTHREAD_CXX"]) CFLAGS="$CFLAGS $PTHREAD_CFLAGS" - save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" - AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) - AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes]) + AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS]) + AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes]) AC_MSG_RESULT([$ax_pthread_ok]) - if test x"$ax_pthread_ok" = xno; then + if test "x$ax_pthread_ok" = "xno"; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CC="$ax_pthread_save_CC" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" fi # We must check for the threads library under a number of different @@ -118,12 +129,14 @@ fi # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). -# Create a list of thread flags to try. Items starting with a "-" are -# C compiler flags, and other items are library names, except for "none" -# which indicates that we try without any flags at all, and "pthread-config" -# which is a program returning the flags for the Pth emulation library. +# Create a list of thread flags to try. Items with a "," contain both +# C compiler flags (before ",") and linker flags (after ","). Other items +# starting with a "-" are C compiler flags, and remaining items are +# library names, except for "none" which indicates that we try without +# any flags at all, and "pthread-config" which is a program returning +# the flags for the Pth emulation library. -ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" +ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: @@ -132,82 +145,163 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) -# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) -# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) -# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) -# -pthreads: Solaris/gcc -# -mthreads: Mingw32/gcc, Lynx/gcc +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64 +# (Note: HP C rejects this with "bad form for `-t' option") +# -pthreads: Solaris/gcc (Note: HP C also rejects) # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it -# doesn't hurt to check since this sometimes defines pthreads too; -# also defines -D_REENTRANT) -# ... -mt is also the pthreads flag for HP/aCC +# doesn't hurt to check since this sometimes defines pthreads and +# -D_REENTRANT too), HP C (must be checked before -lpthread, which +# is present but should not be used directly; and before -mthreads, +# because the compiler interprets this as "-mt" + "-hreads") +# -mthreads: Mingw32/gcc, Lynx/gcc # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) -case ${host_os} in +case $target_os in + + freebsd*) + + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + + ax_pthread_flags="-kthread lthread $ax_pthread_flags" + ;; + + hpux*) + + # From the cc(1) man page: "[-mt] Sets various -D flags to enable + # multi-threading and also sets -lpthread." + + ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags" + ;; + + openedition*) + + # IBM z/OS requires a feature-test macro to be defined in order to + # enable POSIX threads at all, so give the user a hint if this is + # not set. (We don't define these ourselves, as they can affect + # other portions of the system API in unpredictable ways.) + + AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING], + [ +# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS) + AX_PTHREAD_ZOS_MISSING +# endif + ], + [AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])]) + ;; + solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based - # tests will erroneously succeed. (We need to link with -pthreads/-mt/ - # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather - # a function called by this macro, so we could check for that, but - # who knows whether they'll stub that too in a future libc.) So, - # we'll just look for -pthreads and -lpthread first: + # tests will erroneously succeed. (N.B.: The stubs are missing + # pthread_cleanup_push, or rather a function called by this macro, + # so we could check for that, but who knows whether they'll stub + # that too in a future libc.) So we'll check first for the + # standard Solaris way of linking pthreads (-mt -lpthread). + + ax_pthread_flags="-mt,-lpthread pthread $ax_pthread_flags" + ;; +esac + +# Are we compiling with Clang? + +AC_CACHE_CHECK([whether $CC is Clang], + [ax_cv_PTHREAD_CLANG], + [ax_cv_PTHREAD_CLANG=no + # Note that Autoconf sets GCC=yes for Clang as well as GCC + if test "x$GCC" = "xyes"; then + AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG], + [/* Note: Clang 2.7 lacks __clang_[a-z]+__ */ +# if defined(__clang__) && defined(__llvm__) + AX_PTHREAD_CC_IS_CLANG +# endif + ], + [ax_cv_PTHREAD_CLANG=yes]) + fi + ]) +ax_pthread_clang="$ax_cv_PTHREAD_CLANG" + + +# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC) + +# Note that for GCC and Clang -pthread generally implies -lpthread, +# except when -nostdlib is passed. +# This is problematic using libtool to build C++ shared libraries with pthread: +# [1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=25460 +# [2] https://bugzilla.redhat.com/show_bug.cgi?id=661333 +# [3] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=468555 +# To solve this, first try -pthread together with -lpthread for GCC + +AS_IF([test "x$GCC" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread -pthreads $ax_pthread_flags"]) + +# Clang takes -pthread (never supported any other flag), but we'll try with -lpthread first + +AS_IF([test "x$ax_pthread_clang" = "xyes"], + [ax_pthread_flags="-pthread,-lpthread -pthread"]) - ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" + +# The presence of a feature test macro requesting re-entrant function +# definitions is, on some systems, a strong hint that pthreads support is +# correctly enabled + +case $target_os in + darwin* | hpux* | linux* | osf* | solaris*) + ax_pthread_check_macro="_REENTRANT" ;; - darwin*) - ax_pthread_flags="-pthread $ax_pthread_flags" + aix*) + ax_pthread_check_macro="_THREAD_SAFE" ;; -esac -# Clang doesn't consider unrecognized options an error unless we specify -# -Werror. We throw in some extra Clang-specific options to ensure that -# this doesn't happen for GCC, which also accepts -Werror. + *) + ax_pthread_check_macro="--" + ;; +esac +AS_IF([test "x$ax_pthread_check_macro" = "x--"], + [ax_pthread_check_cond=0], + [ax_pthread_check_cond="!defined($ax_pthread_check_macro)"]) -AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags]) -save_CFLAGS="$CFLAGS" -ax_pthread_extra_flags="-Werror" -CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument" -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])], - [AC_MSG_RESULT([yes])], - [ax_pthread_extra_flags= - AC_MSG_RESULT([no])]) -CFLAGS="$save_CFLAGS" -if test x"$ax_pthread_ok" = xno; then -for flag in $ax_pthread_flags; do +if test "x$ax_pthread_ok" = "xno"; then +for ax_pthread_try_flag in $ax_pthread_flags; do - case $flag in + case $ax_pthread_try_flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; + *,*) + PTHREAD_CFLAGS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\1/"` + PTHREAD_LIBS=`echo $ax_pthread_try_flag | sed "s/^\(.*\),\(.*\)$/\2/"` + AC_MSG_CHECKING([whether pthreads work with "$PTHREAD_CFLAGS" and "$PTHREAD_LIBS"]) + ;; + -*) - AC_MSG_CHECKING([whether pthreads work with $flag]) - PTHREAD_CFLAGS="$flag" + AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag]) + PTHREAD_CFLAGS="$ax_pthread_try_flag" ;; pthread-config) AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no]) - if test x"$ax_pthread_config" = xno; then continue; fi + AS_IF([test "x$ax_pthread_config" = "xno"], [continue]) PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) - AC_MSG_CHECKING([for the pthreads library -l$flag]) - PTHREAD_LIBS="-l$flag" + AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag]) + PTHREAD_LIBS="-l$ax_pthread_try_flag" ;; esac - save_LIBS="$LIBS" - save_CFLAGS="$CFLAGS" + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" - CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we @@ -218,8 +312,18 @@ for flag in $ax_pthread_flags; do # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include - static void routine(void *a) { a = 0; } +# if $ax_pthread_check_cond +# error "$ax_pthread_check_macro must be defined" +# endif + static void *some_global = NULL; + static void routine(void *a) + { + /* To avoid any unused-parameter or + unused-but-set-parameter warning. */ + some_global = a; + } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); @@ -227,101 +331,187 @@ for flag in $ax_pthread_flags; do pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], - [ax_pthread_ok=yes], - []) + [ax_pthread_ok=yes], + []) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" AC_MSG_RESULT([$ax_pthread_ok]) - if test "x$ax_pthread_ok" = xyes; then - break; - fi + AS_IF([test "x$ax_pthread_ok" = "xyes"], [break]) PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi + +# Clang needs special handling, because older versions handle the -pthread +# option in a rather... idiosyncratic way + +if test "x$ax_pthread_clang" = "xyes"; then + + # Clang takes -pthread; it has never supported any other flag + + # (Note 1: This will need to be revisited if a system that Clang + # supports has POSIX threads in a separate library. This tends not + # to be the way of modern systems, but it's conceivable.) + + # (Note 2: On some systems, notably Darwin, -pthread is not needed + # to get POSIX threads support; the API is always present and + # active. We could reasonably leave PTHREAD_CFLAGS empty. But + # -pthread does define _REENTRANT, and while the Darwin headers + # ignore this macro, third-party headers might not.) + + # However, older versions of Clang make a point of warning the user + # that, in an invocation where only linking and no compilation is + # taking place, the -pthread option has no effect ("argument unused + # during compilation"). They expect -pthread to be passed in only + # when source code is being compiled. + # + # Problem is, this is at odds with the way Automake and most other + # C build frameworks function, which is that the same flags used in + # compilation (CFLAGS) are also used in linking. Many systems + # supported by AX_PTHREAD require exactly this for POSIX threads + # support, and in fact it is often not straightforward to specify a + # flag that is used only in the compilation phase and not in + # linking. Such a scenario is extremely rare in practice. + # + # Even though use of the -pthread flag in linking would only print + # a warning, this can be a nuisance for well-run software projects + # that build with -Werror. So if the active version of Clang has + # this misfeature, we search for an option to squash it. + + AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG], + [ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown + # Create an alternate version of $ac_link that compiles and + # links in two steps (.c -> .o, .o -> exe) instead of one + # (.c -> exe), because the warning occurs only in the second + # step + ax_pthread_save_ac_link="$ac_link" + ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g' + ax_pthread_link_step=`AS_ECHO(["$ac_link"]) | sed "$ax_pthread_sed"` + ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)" + ax_pthread_save_CFLAGS="$CFLAGS" + for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do + AS_IF([test "x$ax_pthread_try" = "xunknown"], [break]) + CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS" + ac_link="$ax_pthread_save_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [ac_link="$ax_pthread_2step_ac_link" + AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])], + [break]) + ]) + done + ac_link="$ax_pthread_save_ac_link" + CFLAGS="$ax_pthread_save_CFLAGS" + AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no]) + ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try" + ]) + + case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in + no | unknown) ;; + *) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;; + esac + +fi # $ax_pthread_clang = yes + + + # Various other checks: -if test "x$ax_pthread_ok" = xyes; then - save_LIBS="$LIBS" - LIBS="$PTHREAD_LIBS $LIBS" - save_CFLAGS="$CFLAGS" +if test "x$ax_pthread_ok" = "xyes"; then + ax_pthread_save_CFLAGS="$CFLAGS" + ax_pthread_save_LIBS="$LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. - AC_MSG_CHECKING([for joinable pthread attribute]) - attr_name=unknown - for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do - AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], - [int attr = $attr; return attr /* ; */])], - [attr_name=$attr; break], - []) - done - AC_MSG_RESULT([$attr_name]) - if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then - AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name], - [Define to necessary symbol if this constant - uses a non-standard name on your system.]) - fi - - AC_MSG_CHECKING([if more special flags are required for pthreads]) - flag=no - case ${host_os} in - aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; - osf* | hpux*) flag="-D_REENTRANT";; - solaris*) - if test "$GCC" = "yes"; then - flag="-D_REENTRANT" - else - # TODO: What about Clang on Solaris? - flag="-mt -D_REENTRANT" - fi - ;; - esac - AC_MSG_RESULT([$flag]) - if test "x$flag" != xno; then - PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" - fi + AC_CACHE_CHECK([for joinable pthread attribute], + [ax_cv_PTHREAD_JOINABLE_ATTR], + [ax_cv_PTHREAD_JOINABLE_ATTR=unknown + for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do + AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], + [int attr = $ax_pthread_attr; return attr /* ; */])], + [ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break], + []) + done + ]) + AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \ + test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \ + test "x$ax_pthread_joinable_attr_defined" != "xyes"], + [AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], + [$ax_cv_PTHREAD_JOINABLE_ATTR], + [Define to necessary symbol if this constant + uses a non-standard name on your system.]) + ax_pthread_joinable_attr_defined=yes + ]) + + AC_CACHE_CHECK([whether more special flags are required for pthreads], + [ax_cv_PTHREAD_SPECIAL_FLAGS], + [ax_cv_PTHREAD_SPECIAL_FLAGS=no + case $target_os in + solaris*) + ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS" + ;; + esac + ]) + AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \ + test "x$ax_pthread_special_flags_added" != "xyes"], + [PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS" + ax_pthread_special_flags_added=yes]) AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], - [ax_cv_PTHREAD_PRIO_INHERIT], [ - AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], - [[int i = PTHREAD_PRIO_INHERIT;]])], - [ax_cv_PTHREAD_PRIO_INHERIT=yes], - [ax_cv_PTHREAD_PRIO_INHERIT=no]) + [ax_cv_PTHREAD_PRIO_INHERIT], + [AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], + [[int i = PTHREAD_PRIO_INHERIT; + return i;]])], + [ax_cv_PTHREAD_PRIO_INHERIT=yes], + [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) - AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], - [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])]) + AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \ + test "x$ax_pthread_prio_inherit_defined" != "xyes"], + [AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.]) + ax_pthread_prio_inherit_defined=yes + ]) - LIBS="$save_LIBS" - CFLAGS="$save_CFLAGS" + CFLAGS="$ax_pthread_save_CFLAGS" + LIBS="$ax_pthread_save_LIBS" # More AIX lossage: compile with *_r variant - if test "x$GCC" != xyes; then - case $host_os in + if test "x$GCC" != "xyes"; then + case $target_os in aix*) AS_CASE(["x/$CC"], - [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], - [#handle absolute path differently from PATH based program lookup - AS_CASE(["x$CC"], - [x/*], - [AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])], - [AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])]) + [x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6], + [#handle absolute path differently from PATH based program lookup + AS_CASE(["x$CC"], + [x/*], + [ + AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"]) + AS_IF([test "x${CXX}" != "x"], [AS_IF([AS_EXECUTABLE_P([${CXX}_r])],[PTHREAD_CXX="${CXX}_r"])]) + ], + [ + AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC]) + AS_IF([test "x${CXX}" != "x"], [AC_CHECK_PROGS([PTHREAD_CXX],[${CXX}_r],[$CXX])]) + ] + ) + ]) ;; esac fi fi test -n "$PTHREAD_CC" || PTHREAD_CC="$CC" +test -n "$PTHREAD_CXX" || PTHREAD_CXX="$CXX" AC_SUBST([PTHREAD_LIBS]) AC_SUBST([PTHREAD_CFLAGS]) AC_SUBST([PTHREAD_CC]) +AC_SUBST([PTHREAD_CXX]) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: -if test x"$ax_pthread_ok" = xyes; then +if test "x$ax_pthread_ok" = "xyes"; then ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1]) : else diff --git a/m4/ax_python_devel.m4 b/m4/ax_python_devel.m4 deleted file mode 100644 index 59a2ff0903..0000000000 --- a/m4/ax_python_devel.m4 +++ /dev/null @@ -1,324 +0,0 @@ -# =========================================================================== -# http://www.gnu.org/software/autoconf-archive/ax_python_devel.html -# =========================================================================== -# -# SYNOPSIS -# -# AX_PYTHON_DEVEL([version]) -# -# DESCRIPTION -# -# Note: Defines as a precious variable "PYTHON_VERSION". Don't override it -# in your configure.ac. -# -# This macro checks for Python and tries to get the include path to -# 'Python.h'. It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) -# output variables. It also exports $(PYTHON_EXTRA_LIBS) and -# $(PYTHON_EXTRA_LDFLAGS) for embedding Python in your code. -# -# You can search for some particular version of Python by passing a -# parameter to this macro, for example ">= '2.3.1'", or "== '2.4'". Please -# note that you *have* to pass also an operator along with the version to -# match, and pay special attention to the single quotes surrounding the -# version number. Don't use "PYTHON_VERSION" for this: that environment -# variable is declared as precious and thus reserved for the end-user. -# -# This macro should work for all versions of Python >= 2.1.0. As an end -# user, you can disable the check for the python version by setting the -# PYTHON_NOVERSIONCHECK environment variable to something else than the -# empty string. -# -# If you need to use this macro for an older Python version, please -# contact the authors. We're always open for feedback. -# -# LICENSE -# -# Copyright (c) 2009 Sebastian Huber -# Copyright (c) 2009 Alan W. Irwin -# Copyright (c) 2009 Rafael Laboissiere -# Copyright (c) 2009 Andrew Collier -# Copyright (c) 2009 Matteo Settenvini -# Copyright (c) 2009 Horst Knorr -# Copyright (c) 2013 Daniel Mullner -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the -# Free Software Foundation, either version 3 of the License, or (at your -# option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General -# Public License for more details. -# -# You should have received a copy of the GNU General Public License along -# with this program. If not, see . -# -# As a special exception, the respective Autoconf Macro's copyright owner -# gives unlimited permission to copy, distribute and modify the configure -# scripts that are the output of Autoconf when processing the Macro. You -# need not follow the terms of the GNU General Public License when using -# or distributing such scripts, even though portions of the text of the -# Macro appear in them. The GNU General Public License (GPL) does govern -# all other use of the material that constitutes the Autoconf Macro. -# -# This special exception to the GPL applies to versions of the Autoconf -# Macro released by the Autoconf Archive. When you make and distribute a -# modified version of the Autoconf Macro, you may extend this special -# exception to the GPL to apply to your modified version as well. - -#serial 17 - -AU_ALIAS([AC_PYTHON_DEVEL], [AX_PYTHON_DEVEL]) -AC_DEFUN([AX_PYTHON_DEVEL],[ - # - # Allow the use of a (user set) custom python version - # - AC_ARG_VAR([PYTHON_VERSION],[The installed Python - version to use, for example '2.3'. This string - will be appended to the Python interpreter - canonical name.]) - - AC_PATH_PROG([PYTHON],[python[$PYTHON_VERSION]]) - if test -z "$PYTHON"; then - AC_MSG_ERROR([Cannot find python$PYTHON_VERSION in your system path]) - PYTHON_VERSION="" - fi - - # - # Check for a version of Python >= 2.1.0 - # - AC_MSG_CHECKING([for a version of Python >= '2.1.0']) - ac_supports_python_ver=`$PYTHON -c "import sys; \ - ver = sys.version.split ()[[0]]; \ - print (ver >= '2.1.0')"` - if test "$ac_supports_python_ver" != "True"; then - if test -z "$PYTHON_NOVERSIONCHECK"; then - AC_MSG_RESULT([no]) - AC_MSG_FAILURE([ -This version of the AC@&t@_PYTHON_DEVEL macro -doesn't work properly with versions of Python before -2.1.0. You may need to re-run configure, setting the -variables PYTHON_CPPFLAGS, PYTHON_LDFLAGS, PYTHON_SITE_PKG, -PYTHON_EXTRA_LIBS and PYTHON_EXTRA_LDFLAGS by hand. -Moreover, to disable this check, set PYTHON_NOVERSIONCHECK -to something else than an empty string. -]) - else - AC_MSG_RESULT([skip at user request]) - fi - else - AC_MSG_RESULT([yes]) - fi - - # - # if the macro parameter ``version'' is set, honour it - # - if test -n "$1"; then - AC_MSG_CHECKING([for a version of Python $1]) - ac_supports_python_ver=`$PYTHON -c "import sys; \ - ver = sys.version.split ()[[0]]; \ - print (ver $1)"` - if test "$ac_supports_python_ver" = "True"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_ERROR([this package requires Python $1. -If you have it installed, but it isn't the default Python -interpreter in your system path, please pass the PYTHON_VERSION -variable to configure. See ``configure --help'' for reference. -]) - PYTHON_VERSION="" - fi - fi - - # - # Check if you have distutils, else fail - # - AC_MSG_CHECKING([for the distutils Python package]) - ac_distutils_result=`$PYTHON -c "import distutils" 2>&1` - if test -z "$ac_distutils_result"; then - AC_MSG_RESULT([yes]) - else - AC_MSG_RESULT([no]) - AC_MSG_ERROR([cannot import Python module "distutils". -Please check your Python installation. The error was: -$ac_distutils_result]) - PYTHON_VERSION="" - fi - - # - # Check for Python include path - # - AC_MSG_CHECKING([for Python include path]) - if test -z "$PYTHON_CPPFLAGS"; then - python_path=`$PYTHON -c "import distutils.sysconfig; \ - print (distutils.sysconfig.get_python_inc ());"` - plat_python_path=`$PYTHON -c "import distutils.sysconfig; \ - print (distutils.sysconfig.get_python_inc (plat_specific=1));"` - if test -n "${python_path}"; then - if test "${plat_python_path}" != "${python_path}"; then - python_path="-I$python_path -I$plat_python_path" - else - python_path="-I$python_path" - fi - fi - PYTHON_CPPFLAGS=$python_path - fi - AC_MSG_RESULT([$PYTHON_CPPFLAGS]) - AC_SUBST([PYTHON_CPPFLAGS]) - - # - # Check for Python library path - # - AC_MSG_CHECKING([for Python library path]) - if test -z "$PYTHON_LDFLAGS"; then - # (makes two attempts to ensure we've got a version number - # from the interpreter) - ac_python_version=`cat<]], - [[Py_Initialize();]]) - ],[pythonexists=yes],[pythonexists=no]) - AC_LANG_POP([C]) - # turn back to default flags - CPPFLAGS="$ac_save_CPPFLAGS" - LIBS="$ac_save_LIBS" - - AC_MSG_RESULT([$pythonexists]) - - if test ! "x$pythonexists" = "xyes"; then - AC_MSG_FAILURE([ - Could not link test program to Python. Maybe the main Python library has been - installed in some non-standard library path. If so, pass it to configure, - via the LDFLAGS environment variable. - Example: ./configure LDFLAGS="-L/usr/non-standard-path/python/lib" - ============================================================================ - ERROR! - You probably have to install the development version of the Python package - for your distribution. The exact name of this package varies among them. - ============================================================================ - ]) - PYTHON_VERSION="" - fi - - # - # all done! - # -]) From 1e9760c4d6e5e0f15535c3c58867da91a44fb358 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 6 Mar 2021 16:18:26 -0800 Subject: [PATCH 06/44] Remove boost ICU_LINK (broken since boost 1.72.0). --- install.sh | 37 ++++++++++++++++++++++++------------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/install.sh b/install.sh index cfa192202b..366b4a5916 100755 --- a/install.sh +++ b/install.sh @@ -612,7 +612,7 @@ build_from_tarball() pop_directory } -# Because boost ICU detection assumes in incorrect ICU path. +# Because boost ICU static lib detection assumes in incorrect ICU path. circumvent_boost_icu_detection() { # Boost expects a directory structure for ICU which is incorrect. @@ -652,27 +652,30 @@ initialize_boost_configuration() } # Because boost doesn't use pkg-config. +# The hacks below are still required as of boost 1.72.0. initialize_boost_icu_configuration() { BOOST_ICU_ICONV="on" BOOST_ICU_POSIX="on" if [[ $WITH_ICU ]]; then - circumvent_boost_icu_detection - # Restrict other locale options when compiling boost with icu. BOOST_ICU_ICONV="off" BOOST_ICU_POSIX="off" + + # Work around boost ICU static lib discovery bug. + circumvent_boost_icu_detection + + # Extract ICU prefix directory from package config variable. + ICU_PREFIX=$(pkg-config icu-i18n --variable=prefix) + # Because boost doesn't use pkg-config. # Extract ICU libs from package config variables and augment with -ldl. ICU_LIBS="$(pkg-config icu-i18n --libs) -ldl" # This is a hack for boost m4 scripts that fail with ICU dependency. # See custom edits in ax-boost-locale.m4 and ax_boost_regex.m4. export BOOST_ICU_LIBS=("${ICU_LIBS[@]}") - - # Extract ICU prefix directory from package config variable. - ICU_PREFIX=$(pkg-config icu-i18n --variable=prefix) fi } @@ -721,7 +724,7 @@ build_from_tarball_boost() display_message "boost.locale.posix : $BOOST_ICU_POSIX" display_message "-sNO_BZIP2 : 1" display_message "-sICU_PATH : $ICU_PREFIX" - display_message "-sICU_LINK : " "${ICU_LIBS[*]}" + ## display_message "-sICU_LINK : " "${ICU_LIBS[*]}" display_message "-sZLIB_LIBPATH : $PREFIX/lib" display_message "-sZLIB_INCLUDE : $PREFIX/include" display_message "-j : $JOBS" @@ -732,15 +735,24 @@ build_from_tarball_boost() display_message "BOOST_OPTIONS : $*" display_message "--------------------------------------------------------------------" - # boost_iostreams + ./bootstrap.sh \ + "--prefix=$PREFIX" \ + "--with-icu=$ICU_PREFIX" + + # boost_iostreams: # The zlib options prevent boost linkage to system libs in the case where # we have built zlib in a prefix dir. Disabling zlib in boost is broken in - # all versions (through 1.60). https://svn.boost.org/trac/boost/ticket/9156 + # all versions (through 1.61). There has been a patch pull request since + # 2015 but not merged as of 3/5/2021. svn.boost.org/trac/boost/ticket/9156 # The bzip2 auto-detection is not implemented, but disabling it works. - ./bootstrap.sh \ - "--prefix=$PREFIX" \ - "--with-icu=$ICU_PREFIX" + ## Succeed all (0) + # boost_regex: + # As of boost 1.72.0 the ICU_LINK symbol is no longer supported and + # produces a hard stop if WITH_ICU is also defined. Removal is sufficient. + # github.com/libbitcoin/libbitcoin-system/issues/1192 + # ICU_LIBS should be BOOST_ICU_LIBS as ICU_LIBS isn't exported, but moot. + # "-sICU_LINK=${ICU_LIBS[*]}" ./b2 install \ "variant=release" \ @@ -753,7 +765,6 @@ build_from_tarball_boost() "boost.locale.posix=$BOOST_ICU_POSIX" \ "-sNO_BZIP2=1" \ "-sICU_PATH=$ICU_PREFIX" \ - "-sICU_LINK=${ICU_LIBS[*]}" \ "-sZLIB_LIBPATH=$PREFIX/lib" \ "-sZLIB_INCLUDE=$PREFIX/include" \ "-j $JOBS" \ From e7ab053d1bdb8c197a1ad104c9159ce9d123117a Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 6 Mar 2021 16:18:41 -0800 Subject: [PATCH 07/44] Remove dead code. --- builds/msvc/vs2017/libbitcoin-system.import.props | 6 ------ 1 file changed, 6 deletions(-) diff --git a/builds/msvc/vs2017/libbitcoin-system.import.props b/builds/msvc/vs2017/libbitcoin-system.import.props index 530075c30f..ade8e7fb40 100644 --- a/builds/msvc/vs2017/libbitcoin-system.import.props +++ b/builds/msvc/vs2017/libbitcoin-system.import.props @@ -34,12 +34,6 @@ $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) - - - $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib\arm;%(AdditionalLibraryDirectories) - $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib\amd64;%(AdditionalLibraryDirectories) - $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib;%(AdditionalLibraryDirectories) - From db531c7c0a47fbef6bd346a4bb6a3db7a6c947c3 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 6 Mar 2021 18:22:45 -0800 Subject: [PATCH 08/44] Bump qrencode. --- builds/cmake/CMakeLists.txt | 2 +- builds/msvc/vs2017/libbitcoin-system.import.props | 6 ++++++ configure.ac | 12 ++++++------ install.sh | 5 ++--- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index dc68ebaa17..928712ce20 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -210,7 +210,7 @@ endif() # Find qrencode #------------------------------------------------------------------------------ if (with-qrencode) - find_package( Qrencode 3.4.4 REQUIRED ) + find_package( Qrencode 4.1.1 REQUIRED ) endif() # Find secp256k1 diff --git a/builds/msvc/vs2017/libbitcoin-system.import.props b/builds/msvc/vs2017/libbitcoin-system.import.props index ade8e7fb40..530075c30f 100644 --- a/builds/msvc/vs2017/libbitcoin-system.import.props +++ b/builds/msvc/vs2017/libbitcoin-system.import.props @@ -34,6 +34,12 @@ $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + + $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib\arm;%(AdditionalLibraryDirectories) + $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib\amd64;%(AdditionalLibraryDirectories) + $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib;%(AdditionalLibraryDirectories) + diff --git a/configure.ac b/configure.ac index 7356f2fe87..3f7a49d99a 100644 --- a/configure.ac +++ b/configure.ac @@ -337,14 +337,14 @@ AS_CASE([${enable_isystem}],[yes], AC_MSG_NOTICE([png_BUILD_CPPFLAGS : ${png_BUILD_CPPFLAGS}]) -# Require qrencode of at least version 3.4.4 and output ${qrencode_CPPFLAGS/LIBS/PKG}. +# Require qrencode of at least version 4.1.1 and output ${qrencode_CPPFLAGS/LIBS/PKG}. #------------------------------------------------------------------------------ AS_CASE([${with_qrencode}], [yes], - [PKG_CHECK_MODULES([qrencode], [libqrencode >= 3.4.4], - [qrencode_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libqrencode >= 3.4.4" 2>/dev/null`" - qrencode_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libqrencode >= 3.4.4" 2>/dev/null`"], - [AC_MSG_ERROR([--with-qrencode specified but libqrencode >= 3.4.4 was not found.])]) - AC_SUBST([qrencode_PKG], ['libqrencode >= 3.4.4']) + [PKG_CHECK_MODULES([qrencode], [libqrencode >= 4.1.1], + [qrencode_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libqrencode >= 4.1.1" 2>/dev/null`" + qrencode_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libqrencode >= 4.1.1" 2>/dev/null`"], + [AC_MSG_ERROR([--with-qrencode specified but libqrencode >= 4.1.1 was not found.])]) + AC_SUBST([qrencode_PKG], ['libqrencode >= 4.1.1']) AC_SUBST([qrencode_CPPFLAGS], [${qrencode_CFLAGS}]) AS_IF([test x${qrencode_INCLUDEDIR} != "x"], [AC_SUBST([qrencode_ISYS_CPPFLAGS], ["-isystem${qrencode_INCLUDEDIR} ${qrencode_OTHER_CFLAGS}"])], diff --git a/install.sh b/install.sh index 366b4a5916..53ed09dfea 100755 --- a/install.sh +++ b/install.sh @@ -74,8 +74,8 @@ PNG_ARCHIVE="libpng-1.6.37.tar.xz" # QREncode archive. #------------------------------------------------------------------------------ -QRENCODE_URL="http://fukuchi.org/works/qrencode/qrencode-3.4.4.tar.bz2" -QRENCODE_ARCHIVE="qrencode-3.4.4.tar.bz2" +QRENCODE_URL="http://fukuchi.org/works/qrencode/qrencode-4.1.1.tar.bz2" +QRENCODE_ARCHIVE="qrencode-4.1.1.tar.bz2" # Boost archive. #------------------------------------------------------------------------------ @@ -746,7 +746,6 @@ build_from_tarball_boost() # 2015 but not merged as of 3/5/2021. svn.boost.org/trac/boost/ticket/9156 # The bzip2 auto-detection is not implemented, but disabling it works. - ## Succeed all (0) # boost_regex: # As of boost 1.72.0 the ICU_LINK symbol is no longer supported and # produces a hard stop if WITH_ICU is also defined. Removal is sufficient. From 1c2cbdc239e7aea557de797744771d18280aca4c Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 6 Mar 2021 23:09:04 -0800 Subject: [PATCH 09/44] Fix comment. --- src/chain/chain_state.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/chain/chain_state.cpp b/src/chain/chain_state.cpp index 05c3b69c8e..4231d4eeb1 100644 --- a/src/chain/chain_state.cpp +++ b/src/chain/chain_state.cpp @@ -399,7 +399,7 @@ uint32_t chain_state::easy_time_limit(const chain_state::data& values, const int64_t high = timestamp_high(values); //************************************************************************* - // CONSENSUS: add unsigned 32 bit numbers in signed 64 bit space in + // CONSENSUS: add signed 32 bit numbers in signed 64 bit space in // order to prevent overflow before applying the domain constraint. //************************************************************************* return domain_constrain(cast_add(high, spacing)); From a45d744d81eb9a47f40f911448badf48d4ff0b51 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sun, 7 Mar 2021 02:45:27 -0800 Subject: [PATCH 10/44] Set --enable-experimental and --enable-module-schnorrsig on secp256k1. --- install.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/install.sh b/install.sh index 53ed09dfea..43f286a97a 100755 --- a/install.sh +++ b/install.sh @@ -482,8 +482,9 @@ BOOST_OPTIONS=( #------------------------------------------------------------------------------ SECP256K1_OPTIONS=( "--disable-tests" \ +"--enable-experimental" \ "--enable-module-recovery" \ -"--enable-endomorphism") +"--enable-module-schnorrsig") # Define bitcoin-system options. #------------------------------------------------------------------------------ @@ -662,19 +663,17 @@ initialize_boost_icu_configuration() # Restrict other locale options when compiling boost with icu. BOOST_ICU_ICONV="off" BOOST_ICU_POSIX="off" - + # Work around boost ICU static lib discovery bug. circumvent_boost_icu_detection # Extract ICU prefix directory from package config variable. ICU_PREFIX=$(pkg-config icu-i18n --variable=prefix) - # Because boost doesn't use pkg-config. # Extract ICU libs from package config variables and augment with -ldl. ICU_LIBS="$(pkg-config icu-i18n --libs) -ldl" # This is a hack for boost m4 scripts that fail with ICU dependency. - # See custom edits in ax-boost-locale.m4 and ax_boost_regex.m4. export BOOST_ICU_LIBS=("${ICU_LIBS[@]}") fi } @@ -724,7 +723,7 @@ build_from_tarball_boost() display_message "boost.locale.posix : $BOOST_ICU_POSIX" display_message "-sNO_BZIP2 : 1" display_message "-sICU_PATH : $ICU_PREFIX" - ## display_message "-sICU_LINK : " "${ICU_LIBS[*]}" + # display_message "-sICU_LINK : " "${ICU_LIBS[*]}" display_message "-sZLIB_LIBPATH : $PREFIX/lib" display_message "-sZLIB_INCLUDE : $PREFIX/include" display_message "-j : $JOBS" @@ -750,7 +749,6 @@ build_from_tarball_boost() # As of boost 1.72.0 the ICU_LINK symbol is no longer supported and # produces a hard stop if WITH_ICU is also defined. Removal is sufficient. # github.com/libbitcoin/libbitcoin-system/issues/1192 - # ICU_LIBS should be BOOST_ICU_LIBS as ICU_LIBS isn't exported, but moot. # "-sICU_LINK=${ICU_LIBS[*]}" ./b2 install \ From 526b2208aa7d036685e930e35888b079a0265fe9 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sun, 7 Mar 2021 18:14:05 -0800 Subject: [PATCH 11/44] Modify qrcode test to emit base16 on failure. --- test/wallet/qrcode.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/test/wallet/qrcode.cpp b/test/wallet/qrcode.cpp index 2d0a7edeba..75d6865809 100644 --- a/test/wallet/qrcode.cpp +++ b/test/wallet/qrcode.cpp @@ -28,9 +28,9 @@ BOOST_AUTO_TEST_SUITE(qrcode_tests) #ifdef WITH_QRENCODE -BOOST_AUTO_TEST_CASE(qrcode__invoke__qrencode_data__success) +BOOST_AUTO_TEST_CASE(qrcode__construct__always__expected) { - static const uint8_t expected_data[] + static const data_chunk expected { 0x03, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, @@ -105,12 +105,11 @@ BOOST_AUTO_TEST_CASE(qrcode__invoke__qrencode_data__success) 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02 }; - static const auto expected_data_length = sizeof(expected_data) / sizeof(uint8_t); - static const std::string address = "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus"; - const auto encoded_qrcode = qr::encode(to_chunk(address)); + const auto qrcode = qr::encode(to_chunk(std::string{ "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus" })); + BOOST_REQUIRE_EQUAL(qrcode.size(), expected.size()); - BOOST_REQUIRE_EQUAL(encoded_qrcode.size(), expected_data_length); - BOOST_REQUIRE(std::memcmp(encoded_qrcode.data(), expected_data, expected_data_length) == 0); + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qrcode), encode_base16(expected)); } #endif // WITH_QRENCODE From 5b9ebcf0876de728a3c0450cfcd3d3dd3130d853 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sun, 7 Mar 2021 20:12:51 -0800 Subject: [PATCH 12/44] Modify png test to emit base16 on failure. --- include/bitcoin/system/define.hpp | 7 ++++--- test/utility/png.cpp | 21 +++++++++------------ test/wallet/qrcode.cpp | 8 ++++---- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/include/bitcoin/system/define.hpp b/include/bitcoin/system/define.hpp index 3d20d5a22d..51a7a6717f 100644 --- a/include/bitcoin/system/define.hpp +++ b/include/bitcoin/system/define.hpp @@ -32,15 +32,16 @@ namespace bc = libbitcoin; // See http://gcc.gnu.org/wiki/Visibility // Generic helper definitions for shared library support +// GNU visibilty attribute overrides compiler flag `fvisibility`. #if defined _MSC_VER || defined __CYGWIN__ #define BC_HELPER_DLL_IMPORT __declspec(dllimport) #define BC_HELPER_DLL_EXPORT __declspec(dllexport) #define BC_HELPER_DLL_LOCAL #else #if __GNUC__ >= 4 - #define BC_HELPER_DLL_IMPORT __attribute__ ((visibility ("default"))) - #define BC_HELPER_DLL_EXPORT __attribute__ ((visibility ("default"))) - #define BC_HELPER_DLL_LOCAL __attribute__ ((visibility ("internal"))) + #define BC_HELPER_DLL_IMPORT __attribute__((visibility("default"))) + #define BC_HELPER_DLL_EXPORT __attribute__((visibility("default"))) + #define BC_HELPER_DLL_LOCAL __attribute__((visibility("internal"))) #else #define BC_HELPER_DLL_IMPORT #define BC_HELPER_DLL_EXPORT diff --git a/test/utility/png.cpp b/test/utility/png.cpp index fa2ad55ebd..35d35484bf 100644 --- a/test/utility/png.cpp +++ b/test/utility/png.cpp @@ -27,12 +27,10 @@ BOOST_AUTO_TEST_SUITE(png_tests) #ifdef WITH_PNG -BOOST_AUTO_TEST_CASE(png__size_one__success) +// This test may be sensitive to changes in dependency conversion formatting. +BOOST_AUTO_TEST_CASE(png__write_png__size_one__success) { - data_chunk out; - data_sink ostream(out); - - const uint8_t raw_input_data[] = + const data_chunk bitmap { 0x03, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, @@ -106,9 +104,8 @@ BOOST_AUTO_TEST_CASE(png__size_one__success) 0x85, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02 }; - const auto input_data = to_chunk(raw_input_data); - const uint8_t expected_data[] = + const data_chunk expected { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x21, @@ -135,13 +132,13 @@ BOOST_AUTO_TEST_CASE(png__size_one__success) 0x00, 0x15, 0x36, 0x6f, 0x4e, 0xff, 0x43, 0x64, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 }; - constexpr uint32_t expected_data_length = 285; - constexpr uint32_t size = 1; - /* result */ png::write_png(input_data, size, ostream); + data_chunk portable; + data_sink stream(portable); + BOOST_REQUIRE(png::write_png(bitmap, 1, stream)); - BOOST_REQUIRE_EQUAL(out.size(), expected_data_length); - BOOST_REQUIRE_EQUAL(std::memcmp(out.data(), expected_data, expected_data_length), 0); + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(portable), encode_base16(expected)); } #endif // WITH_PNG diff --git a/test/wallet/qrcode.cpp b/test/wallet/qrcode.cpp index 75d6865809..ea8e5c1290 100644 --- a/test/wallet/qrcode.cpp +++ b/test/wallet/qrcode.cpp @@ -18,7 +18,6 @@ */ #include -#include #include using namespace bc::system; @@ -28,6 +27,7 @@ BOOST_AUTO_TEST_SUITE(qrcode_tests) #ifdef WITH_QRENCODE +// This test may be sensitive to changes in dependency conversion formatting. BOOST_AUTO_TEST_CASE(qrcode__construct__always__expected) { static const data_chunk expected @@ -105,11 +105,11 @@ BOOST_AUTO_TEST_CASE(qrcode__construct__always__expected) 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02 }; - const auto qrcode = qr::encode(to_chunk(std::string{ "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus" })); - BOOST_REQUIRE_EQUAL(qrcode.size(), expected.size()); + const auto bitmap = qr::encode(to_chunk(std::string{ "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus" })); + BOOST_REQUIRE_EQUAL(bitmap.size(), expected.size()); // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qrcode), encode_base16(expected)); + BOOST_REQUIRE_EQUAL(encode_base16(bitmap), encode_base16(expected)); } #endif // WITH_QRENCODE From 216447ace3b2465111da49d56a4c9ade75961944 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 8 Mar 2021 16:19:51 -0800 Subject: [PATCH 13/44] Update VS builds. --- .../libbitcoin-system-examples.props | 2 +- .../libbitcoin-system-examples.vcxproj | 4 +- .../packages.config | 2 +- .../libbitcoin-system-test.props | 2 +- .../libbitcoin-system-test.vcxproj | 4 +- .../libbitcoin-system-test/packages.config | 2 +- .../vs2013/libbitcoin-system.import.props | 63 +++++-------------- .../libbitcoin-system.vcxproj | 4 +- .../vs2013/libbitcoin-system/packages.config | 2 +- .../libbitcoin-system-examples.props | 2 +- .../libbitcoin-system-examples.vcxproj | 4 +- .../packages.config | 2 +- .../libbitcoin-system-test.props | 2 +- .../libbitcoin-system-test.vcxproj | 4 +- .../libbitcoin-system-test/packages.config | 2 +- .../vs2015/libbitcoin-system.import.props | 63 +++++-------------- .../libbitcoin-system.vcxproj | 4 +- .../vs2015/libbitcoin-system/packages.config | 2 +- .../libbitcoin-system-examples.props | 2 +- .../libbitcoin-system-examples.vcxproj | 4 +- .../packages.config | 2 +- .../libbitcoin-system-test.props | 2 +- .../libbitcoin-system-test.vcxproj | 4 +- .../libbitcoin-system-test/packages.config | 2 +- .../vs2017/libbitcoin-system.import.props | 63 +++++-------------- .../libbitcoin-system.vcxproj | 4 +- .../vs2017/libbitcoin-system/packages.config | 2 +- 27 files changed, 81 insertions(+), 174 deletions(-) diff --git a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props index 914a8d1005..2f535cd331 100644 --- a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props +++ b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.props @@ -43,7 +43,7 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj index 74958fa3f3..31bb6b8426 100644 --- a/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj @@ -97,7 +97,7 @@ - + @@ -116,7 +116,7 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-examples/packages.config b/builds/msvc/vs2013/libbitcoin-system-examples/packages.config index 986c1f5e2e..3daffc7047 100644 --- a/builds/msvc/vs2013/libbitcoin-system-examples/packages.config +++ b/builds/msvc/vs2013/libbitcoin-system-examples/packages.config @@ -19,5 +19,5 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props index d42786722d..9d4eb7e969 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.props @@ -56,7 +56,7 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 9fe125b2c0..26a0fd030a 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -236,7 +236,7 @@ - + @@ -256,7 +256,7 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system-test/packages.config b/builds/msvc/vs2013/libbitcoin-system-test/packages.config index 3cdc9e01cd..d3cf2183f5 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/packages.config +++ b/builds/msvc/vs2013/libbitcoin-system-test/packages.config @@ -19,6 +19,6 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system.import.props b/builds/msvc/vs2013/libbitcoin-system.import.props index 530075c30f..dd6f87a366 100644 --- a/builds/msvc/vs2013/libbitcoin-system.import.props +++ b/builds/msvc/vs2013/libbitcoin-system.import.props @@ -27,12 +27,24 @@ - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + @@ -41,47 +53,4 @@ $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib;%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj index 248d20b10e..dc2810a75c 100644 --- a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj @@ -593,7 +593,7 @@ - + @@ -612,6 +612,6 @@ - + diff --git a/builds/msvc/vs2013/libbitcoin-system/packages.config b/builds/msvc/vs2013/libbitcoin-system/packages.config index 986c1f5e2e..3daffc7047 100644 --- a/builds/msvc/vs2013/libbitcoin-system/packages.config +++ b/builds/msvc/vs2013/libbitcoin-system/packages.config @@ -19,5 +19,5 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props index 914a8d1005..2f535cd331 100644 --- a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props +++ b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.props @@ -43,7 +43,7 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj index b869d76a3a..f8d69356d0 100644 --- a/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj @@ -97,7 +97,7 @@ - + @@ -116,7 +116,7 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system-examples/packages.config b/builds/msvc/vs2015/libbitcoin-system-examples/packages.config index a2d4a69123..6876c22de2 100644 --- a/builds/msvc/vs2015/libbitcoin-system-examples/packages.config +++ b/builds/msvc/vs2015/libbitcoin-system-examples/packages.config @@ -19,5 +19,5 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props index d42786722d..9d4eb7e969 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.props @@ -56,7 +56,7 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj index bb66e1c930..3a6600b98d 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -236,7 +236,7 @@ - + @@ -256,7 +256,7 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system-test/packages.config b/builds/msvc/vs2015/libbitcoin-system-test/packages.config index a62262518b..1459f63269 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/packages.config +++ b/builds/msvc/vs2015/libbitcoin-system-test/packages.config @@ -19,6 +19,6 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system.import.props b/builds/msvc/vs2015/libbitcoin-system.import.props index 530075c30f..dd6f87a366 100644 --- a/builds/msvc/vs2015/libbitcoin-system.import.props +++ b/builds/msvc/vs2015/libbitcoin-system.import.props @@ -27,12 +27,24 @@ - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + @@ -41,47 +53,4 @@ $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib;%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj index 9b81683913..82247bcd1e 100644 --- a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj @@ -590,7 +590,7 @@ - + @@ -609,6 +609,6 @@ - + diff --git a/builds/msvc/vs2015/libbitcoin-system/packages.config b/builds/msvc/vs2015/libbitcoin-system/packages.config index a2d4a69123..6876c22de2 100644 --- a/builds/msvc/vs2015/libbitcoin-system/packages.config +++ b/builds/msvc/vs2015/libbitcoin-system/packages.config @@ -19,5 +19,5 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props index 914a8d1005..2f535cd331 100644 --- a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props +++ b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.props @@ -43,7 +43,7 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj index 7496c4b1d0..105132c598 100644 --- a/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system-examples/libbitcoin-system-examples.vcxproj @@ -97,7 +97,7 @@ - + @@ -116,7 +116,7 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system-examples/packages.config b/builds/msvc/vs2017/libbitcoin-system-examples/packages.config index e4cd9808fa..de4d71bfec 100644 --- a/builds/msvc/vs2017/libbitcoin-system-examples/packages.config +++ b/builds/msvc/vs2017/libbitcoin-system-examples/packages.config @@ -19,5 +19,5 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props index d42786722d..9d4eb7e969 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.props @@ -56,7 +56,7 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 0c2a9a71a2..1af8bd6406 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -236,7 +236,7 @@ - + @@ -256,7 +256,7 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system-test/packages.config b/builds/msvc/vs2017/libbitcoin-system-test/packages.config index b16d276212..b072cb460d 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/packages.config +++ b/builds/msvc/vs2017/libbitcoin-system-test/packages.config @@ -19,6 +19,6 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system.import.props b/builds/msvc/vs2017/libbitcoin-system.import.props index 530075c30f..dd6f87a366 100644 --- a/builds/msvc/vs2017/libbitcoin-system.import.props +++ b/builds/msvc/vs2017/libbitcoin-system.import.props @@ -27,12 +27,24 @@ - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Debug\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Release\CTP_Nov2013\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) - $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Debug\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + + + $(ProjectDir)..\..\..\..\..\libbitcoin-system\bin\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\; + $(ProjectDir)..\..\..\..\..\libbitcoin-system\obj\libbitcoin-system\$(PlatformName)\Release\$(PlatformToolset)\$(Linkage-libbitcoin-system)\;%(AdditionalLibraryDirectories) + @@ -41,47 +53,4 @@ $(ProgramFiles)\Microsoft Visual C++ Compiler Nov 2013 CTP\lib;%(AdditionalLibraryDirectories) - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj index 2bc0fc140c..2344d784e6 100644 --- a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj @@ -590,7 +590,7 @@ - + @@ -609,6 +609,6 @@ - + diff --git a/builds/msvc/vs2017/libbitcoin-system/packages.config b/builds/msvc/vs2017/libbitcoin-system/packages.config index e4cd9808fa..de4d71bfec 100644 --- a/builds/msvc/vs2017/libbitcoin-system/packages.config +++ b/builds/msvc/vs2017/libbitcoin-system/packages.config @@ -19,5 +19,5 @@ - + From d30542c71a9fd60857b2929cffb6b6d47862b854 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 8 Mar 2021 22:03:46 -0800 Subject: [PATCH 14/44] Require secp256k1 custom version to prevent breaks (unversioned lib). --- builds/cmake/CMakeLists.txt | 2 +- configure.ac | 12 ++++++------ libbitcoin-system.pc.in | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index 928712ce20..237d33a4c9 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -215,7 +215,7 @@ endif() # Find secp256k1 #------------------------------------------------------------------------------ -find_package( Secp256K1 0.0.1 REQUIRED ) +find_package( Secp256K1 0.1.0.19 REQUIRED ) # Define project common includes directories #------------------------------------------------------------------------------ diff --git a/configure.ac b/configure.ac index 3f7a49d99a..fb32819ebb 100644 --- a/configure.ac +++ b/configure.ac @@ -362,13 +362,13 @@ AS_CASE([${enable_isystem}],[yes], AC_MSG_NOTICE([qrencode_BUILD_CPPFLAGS : ${qrencode_BUILD_CPPFLAGS}]) -# Require secp256k1 of at least version 0.0.1 and output ${secp256k1_CPPFLAGS/LIBS/PKG}. +# Require secp256k1 of at least version 0.1.0.19 and output ${secp256k1_CPPFLAGS/LIBS/PKG}. #------------------------------------------------------------------------------ -PKG_CHECK_MODULES([secp256k1], [libsecp256k1 >= 0.0.1], - [secp256k1_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libsecp256k1 >= 0.0.1" 2>/dev/null`" - secp256k1_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libsecp256k1 >= 0.0.1" 2>/dev/null`"], - [AC_MSG_ERROR([libsecp256k1 >= 0.0.1 is required but was not found.])]) -AC_SUBST([secp256k1_PKG], ['libsecp256k1 >= 0.0.1']) +PKG_CHECK_MODULES([secp256k1], [libsecp256k1 >= 0.1.0.19], + [secp256k1_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libsecp256k1 >= 0.1.0.19" 2>/dev/null`" + secp256k1_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libsecp256k1 >= 0.1.0.19" 2>/dev/null`"], + [AC_MSG_ERROR([libsecp256k1 >= 0.1.0.19 is required but was not found.])]) +AC_SUBST([secp256k1_PKG], ['libsecp256k1 >= 0.1.0.19']) AC_SUBST([secp256k1_CPPFLAGS], [${secp256k1_CFLAGS}]) AS_IF([test x${secp256k1_INCLUDEDIR} != "x"], [AC_SUBST([secp256k1_ISYS_CPPFLAGS], ["-isystem${secp256k1_INCLUDEDIR} ${secp256k1_OTHER_CFLAGS}"])], diff --git a/libbitcoin-system.pc.in b/libbitcoin-system.pc.in index f894408936..608309d78c 100644 --- a/libbitcoin-system.pc.in +++ b/libbitcoin-system.pc.in @@ -25,7 +25,7 @@ Version: @PACKAGE_VERSION@ #============================================================================== # Dependencies that publish package configuration. #------------------------------------------------------------------------------ -Requires: @icu_i18n_PKG@ @png_PKG@ @qrencode_PKG@ libsecp256k1 >= 0.0.1 +Requires: @icu_i18n_PKG@ @png_PKG@ @qrencode_PKG@ libsecp256k1 >= 0.1.0.19 # Include directory and any other required compiler flags. #------------------------------------------------------------------------------ From c6ed647e2c7a4f8891b48e1d01c4588dace65038 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Mar 2021 02:27:30 -0700 Subject: [PATCH 15/44] Replace unsigned with size_t ostreamX to prevent 64bit overflow. --- include/bitcoin/system/impl/utility/ostream_bit_writer.ipp | 4 ++-- include/bitcoin/system/impl/utility/ostream_writer.ipp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/bitcoin/system/impl/utility/ostream_bit_writer.ipp b/include/bitcoin/system/impl/utility/ostream_bit_writer.ipp index 6502401879..e25ac4715a 100644 --- a/include/bitcoin/system/impl/utility/ostream_bit_writer.ipp +++ b/include/bitcoin/system/impl/utility/ostream_bit_writer.ipp @@ -33,14 +33,14 @@ template void ostream_bit_writer::write_forward(const byte_array& value) { // write_bytes(value.data(), Size); - for (unsigned index = 0; index < Size; index++) + for (size_t index = 0; index < Size; index++) write_byte(value[index]); } template void ostream_bit_writer::write_reverse(const byte_array& value) { - for (unsigned index = 0; index < Size; index++) + for (size_t index = 0; index < Size; index++) write_byte(value[Size - (index + 1)]); } diff --git a/include/bitcoin/system/impl/utility/ostream_writer.ipp b/include/bitcoin/system/impl/utility/ostream_writer.ipp index d7253fbc7c..6b517eb09d 100644 --- a/include/bitcoin/system/impl/utility/ostream_writer.ipp +++ b/include/bitcoin/system/impl/utility/ostream_writer.ipp @@ -37,7 +37,7 @@ void ostream_writer::write_forward(const byte_array& value) template void ostream_writer::write_reverse(const byte_array& value) { - for (unsigned index = 0; index < Size; index++) + for (size_t index = 0; index < Size; index++) write_byte(value[Size - (index + 1)]); } From 8dea1d04426a5f777baf6835e2d9e09eadc1c130 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Mar 2021 02:28:45 -0700 Subject: [PATCH 16/44] Remove dead code (unimplemented headers), style: whitespace. --- include/bitcoin/system/utility/array_slice.hpp | 1 - include/bitcoin/system/utility/binary.hpp | 3 --- include/bitcoin/system/wallet/witness_address.hpp | 3 --- 3 files changed, 7 deletions(-) diff --git a/include/bitcoin/system/utility/array_slice.hpp b/include/bitcoin/system/utility/array_slice.hpp index 62b088463f..9999a53472 100644 --- a/include/bitcoin/system/utility/array_slice.hpp +++ b/include/bitcoin/system/utility/array_slice.hpp @@ -60,4 +60,3 @@ class array_slice #include #endif - diff --git a/include/bitcoin/system/utility/binary.hpp b/include/bitcoin/system/utility/binary.hpp index 2749e7211d..3f999480c6 100644 --- a/include/bitcoin/system/utility/binary.hpp +++ b/include/bitcoin/system/utility/binary.hpp @@ -68,9 +68,6 @@ class BC_API binary friend std::ostream& operator<<(std::ostream& out, const binary& of); private: - static uint8_t shift_block_right(uint8_t next, uint8_t current, uint8_t prior, - size_type original_offset, size_type intended_offset); - data_chunk blocks_; uint8_t final_block_excess_; }; diff --git a/include/bitcoin/system/wallet/witness_address.hpp b/include/bitcoin/system/wallet/witness_address.hpp index 334bcf3069..6bfadbffc5 100644 --- a/include/bitcoin/system/wallet/witness_address.hpp +++ b/include/bitcoin/system/wallet/witness_address.hpp @@ -98,9 +98,6 @@ class BC_API witness_address bool pad, const data_chunk& in, size_t in_offset); private: - /// Validators. - static bool is_address(data_slice decoded); - /// Factories. static witness_address from_string(const std::string& address, address_format format=address_format::witness_pubkey_hash, From b7d64ddc981be1c1bdef92d6a7d30b6c8e7babaf Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Mar 2021 02:30:01 -0700 Subject: [PATCH 17/44] Add writer method to read full input stream. --- include/bitcoin/system/impl/utility/serializer.ipp | 7 +++++++ include/bitcoin/system/utility/ostream_bit_writer.hpp | 3 +++ include/bitcoin/system/utility/ostream_writer.hpp | 4 ++++ include/bitcoin/system/utility/serializer.hpp | 4 ++++ include/bitcoin/system/utility/writer.hpp | 4 ++++ src/utility/ostream_bit_writer.cpp | 6 ++++++ src/utility/ostream_writer.cpp | 6 ++++++ test/utility/bit_stream.cpp | 6 ++++++ test/utility/serializer.cpp | 6 ++++++ test/utility/stream.cpp | 6 ++++++ 10 files changed, 52 insertions(+) diff --git a/include/bitcoin/system/impl/utility/serializer.ipp b/include/bitcoin/system/impl/utility/serializer.ipp index 38701becaa..06dbec700e 100755 --- a/include/bitcoin/system/impl/utility/serializer.ipp +++ b/include/bitcoin/system/impl/utility/serializer.ipp @@ -183,6 +183,13 @@ void serializer::write_size_little_endian(size_t value) // Bytes (unchecked). //----------------------------------------------------------------------------- +template +void serializer::write(reader& in) +{ + while (!in.is_exhausted()) + write_byte(in.read_byte()); +} + template void serializer::write_byte(uint8_t value) { diff --git a/include/bitcoin/system/utility/ostream_bit_writer.hpp b/include/bitcoin/system/utility/ostream_bit_writer.hpp index 1843ecb7ae..389d95deb8 100644 --- a/include/bitcoin/system/utility/ostream_bit_writer.hpp +++ b/include/bitcoin/system/utility/ostream_bit_writer.hpp @@ -77,6 +77,9 @@ class BC_API ostream_bit_writer void write_variable_little_endian(uint64_t value); void write_size_little_endian(size_t value); + /// Write until reader is exhausted. + void write(reader& in); + /// Write bit. void write_bit(bool value); diff --git a/include/bitcoin/system/utility/ostream_writer.hpp b/include/bitcoin/system/utility/ostream_writer.hpp index 16483125b5..ab1818572e 100644 --- a/include/bitcoin/system/utility/ostream_writer.hpp +++ b/include/bitcoin/system/utility/ostream_writer.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include namespace libbitcoin { @@ -69,6 +70,9 @@ class BC_API ostream_writer void write_variable_little_endian(uint64_t value); void write_size_little_endian(size_t value); + /// Write until reader is exhausted. + void write(reader& in); + /// Write one byte. void write_byte(uint8_t value); diff --git a/include/bitcoin/system/utility/serializer.hpp b/include/bitcoin/system/utility/serializer.hpp index d5909dd893..c7a122f8e5 100644 --- a/include/bitcoin/system/utility/serializer.hpp +++ b/include/bitcoin/system/utility/serializer.hpp @@ -27,6 +27,7 @@ #include #include ////#include +#include #include namespace libbitcoin { @@ -78,6 +79,9 @@ class serializer void write_variable_little_endian(uint64_t value); void write_size_little_endian(size_t value); + /// Write until reader is exhausted. + void write(reader& in); + /// Write one byte. void write_byte(uint8_t value); diff --git a/include/bitcoin/system/utility/writer.hpp b/include/bitcoin/system/utility/writer.hpp index 6ba3f11eb8..7f9a63683b 100644 --- a/include/bitcoin/system/utility/writer.hpp +++ b/include/bitcoin/system/utility/writer.hpp @@ -25,6 +25,7 @@ #include #include #include +#include namespace libbitcoin { namespace system { @@ -56,6 +57,9 @@ class BC_API writer virtual void write_variable_little_endian(uint64_t value) = 0; virtual void write_size_little_endian(size_t value) = 0; + /// Write until reader is exhausted. + virtual void write(reader& in) = 0; + /// Write one byte. virtual void write_byte(uint8_t value) = 0; diff --git a/src/utility/ostream_bit_writer.cpp b/src/utility/ostream_bit_writer.cpp index ec4ef26b5b..3cc6b04283 100644 --- a/src/utility/ostream_bit_writer.cpp +++ b/src/utility/ostream_bit_writer.cpp @@ -224,6 +224,12 @@ void ostream_bit_writer::write_size_little_endian(size_t value) // Bytes. //----------------------------------------------------------------------------- +void ostream_bit_writer::write(reader& in) +{ + while (!in.is_exhausted()) + write_byte(in.read_byte()); +} + void ostream_bit_writer::write_bit(bool value) { uint8_t byte_value = value ? 0x80 : 0x00; diff --git a/src/utility/ostream_writer.cpp b/src/utility/ostream_writer.cpp index 65d19b23d5..49158b8706 100644 --- a/src/utility/ostream_writer.cpp +++ b/src/utility/ostream_writer.cpp @@ -164,6 +164,12 @@ void ostream_writer::write_size_little_endian(size_t value) // Bytes. //----------------------------------------------------------------------------- +void ostream_writer::write(reader& in) +{ + while (!in.is_exhausted()) + write_byte(in.read_byte()); +} + void ostream_writer::write_byte(uint8_t value) { stream_.put(value); diff --git a/test/utility/bit_stream.cpp b/test/utility/bit_stream.cpp index 99b5992ecb..166ab7c467 100644 --- a/test/utility/bit_stream.cpp +++ b/test/utility/bit_stream.cpp @@ -635,6 +635,12 @@ BOOST_AUTO_TEST_CASE(roundtrip_variable_uint_big_endian_8_bytes) BOOST_REQUIRE_EQUAL(false, !source); } +// TODO +BOOST_AUTO_TEST_CASE(roundtrip_stream) +{ + BOOST_REQUIRE(true); +} + BOOST_AUTO_TEST_CASE(roundtrip_data_chunk) { const data_chunk expected diff --git a/test/utility/serializer.cpp b/test/utility/serializer.cpp index 54931ec65a..1c8c9855b5 100644 --- a/test/utility/serializer.cpp +++ b/test/utility/serializer.cpp @@ -371,6 +371,12 @@ BOOST_AUTO_TEST_CASE(roundtrip_variable_uint_big_endian_8_bytes) BOOST_REQUIRE_EQUAL(false, !source); } +// TODO +BOOST_AUTO_TEST_CASE(roundtrip_stream) +{ + BOOST_REQUIRE(true); +} + BOOST_AUTO_TEST_CASE(roundtrip_data_chunk) { static const data_chunk expected diff --git a/test/utility/stream.cpp b/test/utility/stream.cpp index eda0fd3854..57173d7003 100644 --- a/test/utility/stream.cpp +++ b/test/utility/stream.cpp @@ -334,6 +334,12 @@ BOOST_AUTO_TEST_CASE(roundtrip_variable_uint_big_endian_8_bytes) BOOST_REQUIRE_EQUAL(false, !source); } +// TODO +BOOST_AUTO_TEST_CASE(roundtrip_stream) +{ + BOOST_REQUIRE(true); +} + BOOST_AUTO_TEST_CASE(roundtrip_data_chunk) { const data_chunk expected From 1e1fd685aa6c9ddb488c6c6dd0a6ce4d8344b416 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Mar 2021 02:33:52 -0700 Subject: [PATCH 18/44] Change png to tiff, rename, refactor and move qr_code to utility. --- Makefile.am | 12 +- builds/cmake/CMakeLists.txt | 8 +- .../libbitcoin-system-test.vcxproj | 4 +- .../libbitcoin-system-test.vcxproj.filters | 12 +- .../libbitcoin-system.vcxproj | 8 +- .../libbitcoin-system.vcxproj.filters | 24 +- .../libbitcoin-system-test.vcxproj | 4 +- .../libbitcoin-system-test.vcxproj.filters | 12 +- .../libbitcoin-system.vcxproj | 8 +- .../libbitcoin-system.vcxproj.filters | 24 +- .../libbitcoin-system-test.vcxproj | 4 +- .../libbitcoin-system-test.vcxproj.filters | 12 +- .../libbitcoin-system.vcxproj | 8 +- .../libbitcoin-system.vcxproj.filters | 24 +- include/bitcoin/system.hpp | 4 +- include/bitcoin/system/utility/png.hpp | 95 ------ include/bitcoin/system/utility/qr_code.hpp | 67 +++++ include/bitcoin/system/utility/tiff.hpp | 50 ++++ include/bitcoin/system/wallet/qrcode.hpp | 82 ------ src/utility/png.cpp | 206 ------------- src/utility/qr_code.cpp | 230 +++++++++++++++ src/utility/tiff.cpp | 272 ++++++++++++++++++ src/wallet/qrcode.cpp | 97 ------- test/utility/png.cpp | 146 ---------- test/utility/qr_code.cpp | 58 ++++ test/utility/tiff.cpp | 190 ++++++++++++ test/wallet/qrcode.cpp | 117 -------- 27 files changed, 951 insertions(+), 827 deletions(-) delete mode 100644 include/bitcoin/system/utility/png.hpp create mode 100644 include/bitcoin/system/utility/qr_code.hpp create mode 100644 include/bitcoin/system/utility/tiff.hpp delete mode 100644 include/bitcoin/system/wallet/qrcode.hpp delete mode 100644 src/utility/png.cpp create mode 100644 src/utility/qr_code.cpp create mode 100644 src/utility/tiff.cpp delete mode 100644 src/wallet/qrcode.cpp delete mode 100644 test/utility/png.cpp create mode 100644 test/utility/qr_code.cpp create mode 100644 test/utility/tiff.cpp delete mode 100644 test/wallet/qrcode.cpp diff --git a/Makefile.am b/Makefile.am index 0108f7bebf..73fffa8bf0 100755 --- a/Makefile.am +++ b/Makefile.am @@ -188,10 +188,10 @@ src_libbitcoin_system_la_SOURCES = \ src/utility/neutrino_filter.cpp \ src/utility/ostream_bit_writer.cpp \ src/utility/ostream_writer.cpp \ - src/utility/png.cpp \ src/utility/prioritized_mutex.cpp \ src/utility/property_tree.cpp \ src/utility/pseudo_random.cpp \ + src/utility/qr_code.cpp \ src/utility/scope_lock.cpp \ src/utility/sequencer.cpp \ src/utility/sequential_lock.cpp \ @@ -199,6 +199,7 @@ src_libbitcoin_system_la_SOURCES = \ src/utility/string.cpp \ src/utility/thread.cpp \ src/utility/threadpool.cpp \ + src/utility/tiff.cpp \ src/utility/work.cpp \ src/wallet/bitcoin_uri.cpp \ src/wallet/dictionary_en.cpp \ @@ -228,7 +229,6 @@ src_libbitcoin_system_la_SOURCES = \ src/wallet/mini_keys.cpp \ src/wallet/mnemonic.cpp \ src/wallet/payment_address.cpp \ - src/wallet/qrcode.cpp \ src/wallet/select_outputs.cpp \ src/wallet/stealth_address.cpp \ src/wallet/stealth_receiver.cpp \ @@ -371,12 +371,13 @@ test_libbitcoin_system_test_SOURCES = \ test/utility/data.cpp \ test/utility/endian.cpp \ test/utility/neutrino_filter.cpp \ - test/utility/png.cpp \ test/utility/property_tree.cpp \ test/utility/pseudo_random.cpp \ + test/utility/qr_code.cpp \ test/utility/serializer.cpp \ test/utility/stream.cpp \ test/utility/thread.cpp \ + test/utility/tiff.cpp \ test/wallet/bitcoin_uri.cpp \ test/wallet/ec_private.cpp \ test/wallet/ec_public.cpp \ @@ -388,7 +389,6 @@ test_libbitcoin_system_test_SOURCES = \ test/wallet/mnemonic.cpp \ test/wallet/mnemonic.hpp \ test/wallet/payment_address.cpp \ - test/wallet/qrcode.cpp \ test/wallet/select_outputs.cpp \ test/wallet/stealth_address.cpp \ test/wallet/stealth_receiver.cpp \ @@ -651,10 +651,10 @@ include_bitcoin_system_utility_HEADERS = \ include/bitcoin/system/utility/ostream_bit_writer.hpp \ include/bitcoin/system/utility/ostream_writer.hpp \ include/bitcoin/system/utility/pending.hpp \ - include/bitcoin/system/utility/png.hpp \ include/bitcoin/system/utility/prioritized_mutex.hpp \ include/bitcoin/system/utility/property_tree.hpp \ include/bitcoin/system/utility/pseudo_random.hpp \ + include/bitcoin/system/utility/qr_code.hpp \ include/bitcoin/system/utility/reader.hpp \ include/bitcoin/system/utility/resubscriber.hpp \ include/bitcoin/system/utility/scope_lock.hpp \ @@ -667,6 +667,7 @@ include_bitcoin_system_utility_HEADERS = \ include/bitcoin/system/utility/synchronizer.hpp \ include/bitcoin/system/utility/thread.hpp \ include/bitcoin/system/utility/threadpool.hpp \ + include/bitcoin/system/utility/tiff.hpp \ include/bitcoin/system/utility/timer.hpp \ include/bitcoin/system/utility/track.hpp \ include/bitcoin/system/utility/work.hpp \ @@ -690,7 +691,6 @@ include_bitcoin_system_wallet_HEADERS = \ include/bitcoin/system/wallet/mini_keys.hpp \ include/bitcoin/system/wallet/mnemonic.hpp \ include/bitcoin/system/wallet/payment_address.hpp \ - include/bitcoin/system/wallet/qrcode.hpp \ include/bitcoin/system/wallet/select_outputs.hpp \ include/bitcoin/system/wallet/stealth_address.hpp \ include/bitcoin/system/wallet/stealth_receiver.hpp \ diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index 237d33a4c9..a88a1f7566 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -471,10 +471,10 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/utility/neutrino_filter.cpp" "../../src/utility/ostream_bit_writer.cpp" "../../src/utility/ostream_writer.cpp" - "../../src/utility/png.cpp" "../../src/utility/prioritized_mutex.cpp" "../../src/utility/property_tree.cpp" "../../src/utility/pseudo_random.cpp" + "../../src/utility/qr_code.cpp" "../../src/utility/scope_lock.cpp" "../../src/utility/sequencer.cpp" "../../src/utility/sequential_lock.cpp" @@ -482,6 +482,7 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/utility/string.cpp" "../../src/utility/thread.cpp" "../../src/utility/threadpool.cpp" + "../../src/utility/tiff.cpp" "../../src/utility/work.cpp" "../../src/wallet/bitcoin_uri.cpp" "../../src/wallet/dictionary_en.cpp" @@ -511,7 +512,6 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/wallet/mini_keys.cpp" "../../src/wallet/mnemonic.cpp" "../../src/wallet/payment_address.cpp" - "../../src/wallet/qrcode.cpp" "../../src/wallet/select_outputs.cpp" "../../src/wallet/stealth_address.cpp" "../../src/wallet/stealth_receiver.cpp" @@ -723,12 +723,13 @@ if (with-tests) "../../test/utility/data.cpp" "../../test/utility/endian.cpp" "../../test/utility/neutrino_filter.cpp" - "../../test/utility/png.cpp" "../../test/utility/property_tree.cpp" "../../test/utility/pseudo_random.cpp" + "../../test/utility/qr_code.cpp" "../../test/utility/serializer.cpp" "../../test/utility/stream.cpp" "../../test/utility/thread.cpp" + "../../test/utility/tiff.cpp" "../../test/wallet/bitcoin_uri.cpp" "../../test/wallet/ec_private.cpp" "../../test/wallet/ec_public.cpp" @@ -740,7 +741,6 @@ if (with-tests) "../../test/wallet/mnemonic.cpp" "../../test/wallet/mnemonic.hpp" "../../test/wallet/payment_address.cpp" - "../../test/wallet/qrcode.cpp" "../../test/wallet/select_outputs.cpp" "../../test/wallet/stealth_address.cpp" "../../test/wallet/stealth_receiver.cpp" diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 26a0fd030a..5c6657ff30 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -184,12 +184,13 @@ - + + @@ -200,7 +201,6 @@ - diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters index be04a60fbc..3434820b08 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters @@ -327,15 +327,15 @@ src\utility - - src\utility - src\utility src\utility + + src\utility + src\utility @@ -345,6 +345,9 @@ src\utility + + src\utility + src\wallet @@ -375,9 +378,6 @@ src\wallet - - src\wallet - src\wallet diff --git a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj index dc2810a75c..cb574fdf8b 100644 --- a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj @@ -253,10 +253,10 @@ - + @@ -264,6 +264,7 @@ + @@ -296,7 +297,6 @@ - @@ -475,10 +475,10 @@ - + @@ -491,6 +491,7 @@ + @@ -512,7 +513,6 @@ - diff --git a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters index f09340cd41..3061c7433c 100644 --- a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters +++ b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters @@ -537,9 +537,6 @@ src\utility - - src\utility - src\utility @@ -549,6 +546,9 @@ src\utility + + src\utility + src\utility @@ -570,6 +570,9 @@ src\utility + + src\utility + src\utility @@ -666,9 +669,6 @@ src\wallet - - src\wallet - src\wallet @@ -1199,9 +1199,6 @@ include\bitcoin\system\utility - - include\bitcoin\system\utility - include\bitcoin\system\utility @@ -1211,6 +1208,9 @@ include\bitcoin\system\utility + + include\bitcoin\system\utility + include\bitcoin\system\utility @@ -1247,6 +1247,9 @@ include\bitcoin\system\utility + + include\bitcoin\system\utility + include\bitcoin\system\utility @@ -1310,9 +1313,6 @@ include\bitcoin\system\wallet - - include\bitcoin\system\wallet - include\bitcoin\system\wallet diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 3a6600b98d..a45e62681a 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -184,12 +184,13 @@ - + + @@ -200,7 +201,6 @@ - diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters index be04a60fbc..3434820b08 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters @@ -327,15 +327,15 @@ src\utility - - src\utility - src\utility src\utility + + src\utility + src\utility @@ -345,6 +345,9 @@ src\utility + + src\utility + src\wallet @@ -375,9 +378,6 @@ src\wallet - - src\wallet - src\wallet diff --git a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj index 82247bcd1e..1a9320526c 100644 --- a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj @@ -250,10 +250,10 @@ - + @@ -261,6 +261,7 @@ + @@ -293,7 +294,6 @@ - @@ -472,10 +472,10 @@ - + @@ -488,6 +488,7 @@ + @@ -509,7 +510,6 @@ - diff --git a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters index 7e965d3e09..2dcad40d6b 100644 --- a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters +++ b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters @@ -531,9 +531,6 @@ src\utility - - src\utility - src\utility @@ -543,6 +540,9 @@ src\utility + + src\utility + src\utility @@ -564,6 +564,9 @@ src\utility + + src\utility + src\utility @@ -660,9 +663,6 @@ src\wallet - - src\wallet - src\wallet @@ -1193,9 +1193,6 @@ include\bitcoin\system\utility - - include\bitcoin\system\utility - include\bitcoin\system\utility @@ -1205,6 +1202,9 @@ include\bitcoin\system\utility + + include\bitcoin\system\utility + include\bitcoin\system\utility @@ -1241,6 +1241,9 @@ include\bitcoin\system\utility + + include\bitcoin\system\utility + include\bitcoin\system\utility @@ -1304,9 +1307,6 @@ include\bitcoin\system\wallet - - include\bitcoin\system\wallet - include\bitcoin\system\wallet diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 1af8bd6406..a53509eafc 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -184,12 +184,13 @@ - + + @@ -200,7 +201,6 @@ - diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters index be04a60fbc..3434820b08 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters @@ -327,15 +327,15 @@ src\utility - - src\utility - src\utility src\utility + + src\utility + src\utility @@ -345,6 +345,9 @@ src\utility + + src\utility + src\wallet @@ -375,9 +378,6 @@ src\wallet - - src\wallet - src\wallet diff --git a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj index 2344d784e6..71c176f3c1 100644 --- a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj @@ -250,10 +250,10 @@ - + @@ -261,6 +261,7 @@ + @@ -293,7 +294,6 @@ - @@ -472,10 +472,10 @@ - + @@ -488,6 +488,7 @@ + @@ -509,7 +510,6 @@ - diff --git a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters index 9482a36d6d..3b470c2b6d 100644 --- a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters +++ b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters @@ -531,9 +531,6 @@ src\utility - - src\utility - src\utility @@ -543,6 +540,9 @@ src\utility + + src\utility + src\utility @@ -564,6 +564,9 @@ src\utility + + src\utility + src\utility @@ -660,9 +663,6 @@ src\wallet - - src\wallet - src\wallet @@ -1193,9 +1193,6 @@ include\bitcoin\system\utility - - include\bitcoin\system\utility - include\bitcoin\system\utility @@ -1205,6 +1202,9 @@ include\bitcoin\system\utility + + include\bitcoin\system\utility + include\bitcoin\system\utility @@ -1241,6 +1241,9 @@ include\bitcoin\system\utility + + include\bitcoin\system\utility + include\bitcoin\system\utility @@ -1304,9 +1307,6 @@ include\bitcoin\system\wallet - - include\bitcoin\system\wallet - include\bitcoin\system\wallet diff --git a/include/bitcoin/system.hpp b/include/bitcoin/system.hpp index 435647517e..8991cc957c 100755 --- a/include/bitcoin/system.hpp +++ b/include/bitcoin/system.hpp @@ -184,10 +184,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -200,6 +200,7 @@ #include #include #include +#include #include #include #include @@ -220,7 +221,6 @@ #include #include #include -#include #include #include #include diff --git a/include/bitcoin/system/utility/png.hpp b/include/bitcoin/system/utility/png.hpp deleted file mode 100644 index 5e3d21dc87..0000000000 --- a/include/bitcoin/system/utility/png.hpp +++ /dev/null @@ -1,95 +0,0 @@ -/** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef LIBBITCOIN_SYSTEM_PNG_HPP -#define LIBBITCOIN_SYSTEM_PNG_HPP - -#include -#include -#include -#include -#include -#include - -#ifdef WITH_PNG -#include - -namespace libbitcoin { -namespace system { - -class BC_API png -{ -public: - static BC_CONSTEXPR uint32_t margin = 2; - static BC_CONSTEXPR uint32_t dots_per_inch = 72; - static BC_CONSTEXPR uint32_t inches_per_meter = (100.0 / 2.54); - - static const color get_default_foreground() - { - static BC_CONSTEXPR color default_foreground{ 0, 0, 0, 255 }; - return default_foreground; - } - - static const color get_default_background() - { - static BC_CONSTEXPR color default_background{ 255, 255, 255, 255 }; - return default_background; - } - - /** - * A method that takes encoded qrcode as a data chunk and writes it to - * an output stream in png format with the default parameters. The - * size parameter specifies the number of dots (pixels) per qr code - * modules. - */ - static bool write_png(const data_chunk& data, uint32_t size, - std::ostream& out); - - /** - * A method that takes encoded qrcode data as a data chunk and writes - * it to an output stream in png format with the specified parameters. - */ - static bool write_png(const data_chunk& data, uint32_t size, - uint32_t dots_per_inch, uint32_t margin, uint32_t inches_per_meter, - const color& foreground, const color& background, std::ostream& out); - - /** - * A method that reads encoded qrcode data via an input stream and - * writes it to an output stream in png format with the default - * parameters. The size parameter specifies the number of dots - * (pixels) per qr code modules. - */ - static bool write_png(std::istream& in, uint32_t size, std::ostream& out); - - /** - * A method that reads encoded qrcode data via an input stream and - * writes it to an output stream in png format with the specified - * parameters. - */ - static bool write_png(std::istream& in, uint32_t size, - uint32_t dots_per_inch, const uint32_t margin, - uint32_t inches_per_meter, const color& foreground, - const color& background, std::ostream& out); -}; - -} // namespace system -} // namespace libbitcoin - -#endif // WITH_PNG - -#endif diff --git a/include/bitcoin/system/utility/qr_code.hpp b/include/bitcoin/system/utility/qr_code.hpp new file mode 100644 index 0000000000..df90f3f1d1 --- /dev/null +++ b/include/bitcoin/system/utility/qr_code.hpp @@ -0,0 +1,67 @@ +/** + * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SYSTEM_QR_CODE_HPP +#define LIBBITCOIN_SYSTEM_QR_CODE_HPP + +#include +#include +#include +#include + +namespace libbitcoin { +namespace system { + +class BC_API qr_code +{ +public: + enum class encode_mode + { + numeric = 0, + alpha_numeric, + eight_bit, + kanji, + unused, + eci_mode, + fcn1_1, + fcn1_2 + }; + + enum class recovery_level + { + low = 0, + medium, + high, + highest + }; + + /// Create a TIFF qrcode representing the given string value. + static bool encode(std::ostream& out, const std::string& value, + uint32_t version=0, uint16_t scale=8, uint16_t margin=2, + bool case_sensitive=true, recovery_level level=recovery_level::low, + encode_mode mode=encode_mode::eight_bit); + + /// Convert qr encoded data stream to bit stream with margin and scaling. + static data_chunk to_image_data(const data_chunk& coded, uint16_t scale=8, + uint16_t margin=2); +}; + +} // namespace system +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/system/utility/tiff.hpp b/include/bitcoin/system/utility/tiff.hpp new file mode 100644 index 0000000000..f041e09818 --- /dev/null +++ b/include/bitcoin/system/utility/tiff.hpp @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#ifndef LIBBITCOIN_SYSTEM_TIFF_HPP +#define LIBBITCOIN_SYSTEM_TIFF_HPP + +#include +#include +#include +#include + +namespace libbitcoin { +namespace system { + +/// Convert a data chunk or stream to a square black on white tiff file. +class BC_API tiff +{ +public: + /// The image bit stream is stored at the end of the file. + /// This is the file offset in bytes to the start of the image data. + /// The last image byte may contain padding, image bit size is width^2. + static uint32_t image_offset; + + /// (((2^16) - 1)^2 + 7)/ 8 = 536,854,529 or 0x1fffc001 bytes. + static uint32_t max_image_bytes; + + /// Data size must be (width^2 + 7) / 8. Last byte may be buffered. + static bool to_image(std::ostream& out, const data_chunk& data, + uint16_t width); +}; + +} // namespace system +} // namespace libbitcoin + +#endif diff --git a/include/bitcoin/system/wallet/qrcode.hpp b/include/bitcoin/system/wallet/qrcode.hpp deleted file mode 100644 index 195c9dab7c..0000000000 --- a/include/bitcoin/system/wallet/qrcode.hpp +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef LIBBITCOIN_SYSTEM_QRENCODE_HPP -#define LIBBITCOIN_SYSTEM_QRENCODE_HPP - -#include -#include -#include -#include -#include -#include - -#ifdef WITH_QRENCODE -#include - -namespace libbitcoin { -namespace system { -namespace wallet { - -class BC_API qr -{ -public: - typedef QRencodeMode encode_mode; - typedef QRecLevel error_recovery_level; - - static BC_CONSTEXPR uint32_t version = 0; - static BC_CONSTEXPR bool case_sensitive = true; - static BC_CONSTEXPR encode_mode mode = QR_MODE_8; - static BC_CONSTEXPR error_recovery_level level = QR_ECLEVEL_L; - - /** - * A method that takes an input stream and writes the encoded qr data - * to the specified output stream with default parameter values. - */ - BC_API static bool encode(std::istream& in, std::ostream& out); - - /** - * A method that takes a data chunk and returns the encoded qr data as - * a data_chunk with default parameter values. - */ - BC_API static data_chunk encode(const data_chunk& data); - - /** - * A method that takes a data chunk and returns the encoded qr data as - * a data chunk with the specified parameter values. - */ - BC_API static data_chunk encode(const data_chunk& data, - uint32_t version, const error_recovery_level level, - encode_mode mode, bool case_sensitive); - - /** - * A method that takes an input stream and writes the encoded qr data - * to the output stream with the specified parameter values. - */ - BC_API static bool encode(std::istream& in, uint32_t version, - error_recovery_level level, encode_mode mode, bool case_sensitive, - std::ostream& out); -}; - -} // namespace wallet -} // namespace system -} // namespace libbitcoin - -#endif // WITH_QRENCODE - -#endif diff --git a/src/utility/png.cpp b/src/utility/png.cpp deleted file mode 100644 index 91ede7c16c..0000000000 --- a/src/utility/png.cpp +++ /dev/null @@ -1,206 +0,0 @@ -/** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace libbitcoin { -namespace system { - -#ifdef WITH_PNG - -bool png::write_png(const data_chunk& data, uint32_t size, std::ostream& out) -{ - data_source istream(data); - return png::write_png(istream, size, out); -} - -bool png::write_png(const data_chunk& data, uint32_t size, - uint32_t dots_per_inch, uint32_t margin, uint32_t inches_per_meter, - const color& foreground, const color& background, std::ostream& out) -{ - data_source istream(data); - return png::write_png(istream, size, dots_per_inch, margin, - inches_per_meter, foreground, background, out); -} - -bool png::write_png(std::istream& in, uint32_t size, std::ostream& out) -{ - return png::write_png(in, size, dots_per_inch, margin, inches_per_meter, - get_default_foreground(), get_default_background(), out); -} - -extern "C" void sink_write(png_structp png_ptr, png_bytep data, - png_size_t length) -{ - static_assert(sizeof(length) <= sizeof(size_t), "png_size_t too large"); - const auto size = static_cast(length); - - auto& sink = *reinterpret_cast(png_get_io_ptr(png_ptr)); - sink.write_bytes(reinterpret_cast(data), size); -} - -extern "C" void error_callback(png_structp, png_const_charp error_message) -{ - throw std::runtime_error(error_message); -} - -bool png::write_png(std::istream& in, uint32_t size, uint32_t dots_per_inch, - uint32_t margin, uint32_t inches_per_meter, const color& foreground, - const color& background, std::ostream& out) -{ - if (size == 0) - return false; - - istream_reader source(in); - // Skip version. - source.skip(4); - auto width = source.read_4_bytes_little_endian(); - - if (max_size_t / width < width) - return false; - - const auto area = width * width; - auto data = source.read_bytes(area); - - try - { - static constexpr int32_t bit_depth = 1; - static constexpr int32_t bits_per_byte = 8; - static constexpr uint8_t margin_value = 0xff; - - if ((size == 0) || (margin > max_size_t / size)) - return false; - - if ((width + margin * 2) > max_size_t / size) - return false; - - const auto margin_size = margin * size; - const auto realwidth = (width + margin * 2) * size; - const auto row_size = (realwidth + 7) / bits_per_byte; - - data_chunk row; - row.reserve(row_size); - - auto png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, - nullptr, nullptr); - if (png_ptr == nullptr) - return false; - - auto info_ptr = png_create_info_struct(png_ptr); - if (info_ptr == nullptr) - return false; - - png_color palette[2]; - palette[0].red = foreground.red; - palette[0].green = foreground.green; - palette[0].blue = foreground.blue; - palette[1].red = background.red; - palette[1].green = background.green; - palette[1].blue = background.blue; - - png_byte alpha_values[2]; - alpha_values[0] = foreground.alpha; - alpha_values[1] = background.alpha; - - png_set_PLTE(png_ptr, info_ptr, palette, 2); - png_set_tRNS(png_ptr, info_ptr, alpha_values, 2, nullptr); - - ostream_writer sink(out); - png_set_write_fn(png_ptr, &sink, sink_write, nullptr); - png_set_error_fn(png_ptr, nullptr, error_callback, nullptr); - - png_set_IHDR(png_ptr, info_ptr, realwidth, realwidth, bit_depth, - PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - png_set_pHYs(png_ptr, info_ptr, dots_per_inch * inches_per_meter, - dots_per_inch * inches_per_meter, PNG_RESOLUTION_METER); - - png_write_info(png_ptr, info_ptr); - - // write top margin - row.assign(row_size, margin_value); - for (size_t y = 0; y < margin_size; y++) - png_write_row(png_ptr, row.data()); - - // write data - uint8_t* row_ptr = nullptr; - auto data_ptr = data.data(); - for (size_t y = 0; y < width; y++) - { - // TODO: unguarded overflow conditions. - auto bit = bits_per_byte - 1; - row.assign(row_size, margin_value); - row_ptr = row.data(); - row_ptr += margin_size / bits_per_byte; - bit = (bits_per_byte - 1) - (margin_size % bits_per_byte); - - for (size_t x = 0; x < width; x++) - { - for (size_t xx = 0; xx < size; xx++) - { - *row_ptr ^= (*data_ptr & 1) << bit; - bit--; - if (bit < 0) - { - row_ptr++; - bit = bits_per_byte - 1; - } - } - - data_ptr++; - } - - for (size_t yy = 0; yy < size; yy++) - png_write_row(png_ptr, row.data()); - } - - // write bottom margin - row.assign(row_size, margin_value); - for (size_t y = 0; y < margin_size; y++) - png_write_row(png_ptr, row.data()); - - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - - out.flush(); - } - catch (const std::runtime_error& error) - { - return false; - } - - return true; -} - -#endif - -} // namespace system -} // namespace libbitcoin diff --git a/src/utility/qr_code.cpp b/src/utility/qr_code.cpp new file mode 100644 index 0000000000..c2ee37d1d2 --- /dev/null +++ b/src/utility/qr_code.cpp @@ -0,0 +1,230 @@ +/** + * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include +#include +#include +#include +#ifdef WITH_QRENCODE + #include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace system { + +#ifdef WITH_QRENCODE +static QRecLevel recovery_level_to_qr_recovery_level( + qr_code::recovery_level level) +{ + switch (level) + { + case qr_code::recovery_level::low: + return QR_ECLEVEL_L; + case qr_code::recovery_level::medium: + return QR_ECLEVEL_M; + case qr_code::recovery_level::high: + return QR_ECLEVEL_Q; + default: + return QR_ECLEVEL_H; + } +} + +static QRencodeMode encode_mode_to_qr_encode_mode(qr_code::encode_mode mode) +{ + switch (mode) + { + case qr_code::encode_mode::numeric: + return QR_MODE_NUM; + case qr_code::encode_mode::alpha_numeric: + return QR_MODE_AN; + case qr_code::encode_mode::eight_bit: + return QR_MODE_8; + case qr_code::encode_mode::kanji: + return QR_MODE_KANJI; + case qr_code::encode_mode::eci_mode: + return QR_MODE_ECI; + case qr_code::encode_mode::fcn1_1: + return QR_MODE_FNC1FIRST; + case qr_code::encode_mode::fcn1_2: + return QR_MODE_FNC1SECOND; + default: + return QR_MODE_NUL; + } +} +#endif + +bool qr_code::encode(std::ostream& out, const std::string& value, + uint32_t version, uint16_t scale, uint16_t margin, bool case_sensitive, + recovery_level level, encode_mode mode) +{ +#ifdef WITH_QRENCODE + const auto qrcode = QRcode_encodeString(value.c_str(), version, + recovery_level_to_qr_recovery_level(level), + encode_mode_to_qr_encode_mode(mode), case_sensitive); + + if (qrcode == nullptr) + return false; + + // Any scale increase can potentially cause an overflow. + const auto scaled_width = scale * static_cast(qrcode->width); + + // Guard against scaling overflow. + if (scaled_width > max_uint16) + return false; + + // Limit of bc::tiff conversion maximum size. + const auto width = static_cast(scaled_width); + + // Width is limited to max_uint32, safe in 64 bit space. + const auto area = qrcode->width * static_cast(qrcode->width); + + // Guard against overflow (to_image_data verifies logical size). + if (area > std::numeric_limits::max()) + return false; + + // Map coded data into a data_chunk (must rely on width correctness). + const data_chunk coded(&qrcode->data[0], &qrcode->data[area - 1u]); + + // Convert to scaled image pixel bit stream. + const auto pixels = to_image_data(coded, scale, margin); + + // Convert to TIFF image stream (does not fail as long as sizes match). + return tiff::to_image(out, pixels, width); +#else + return false; +#endif +} + +// Scale may move the image off of a byte-aligned square of pixels in bytes. +// So the dimensions cannot be derived from the result, caller must retain. +// pixel_width = width * scale. +data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, + uint16_t margin) +{ + // For reading the qrcode byte stream. + data_source image_source(coded); + istream_reader image_reader(image_source); + + // Skip over the serialized qrencode version (may not match requested). + image_reader.skip(sizeof(uint32_t)); + + // Read the serialized qrencode width (encoding is one pixel per byte). + const auto width = image_reader.read_4_bytes_little_endian(); + + // Guard against insufficient stream length (invalid width). + if (!image_reader) + return {}; + + // Guard against mismatched sizes from qrencode. + if (coded.size() != width * static_cast(width)) + return {}; + + // Any scale increase can potentially cause an overflow. + const auto scaled_width = scale * static_cast(width); + + // Guard against scaling overflow. + if (scaled_width > max_uint32) + return {}; + + // Pixel is the least significant bit of a qrencode byte. + constexpr auto pixel_mask = uint8_t{ 0x01 }; + constexpr auto pixel_off = false; + + // For readability (image is always square). + const auto height = width; + const auto vertical_margin = margin; + const auto horizontal_margin = margin; + const auto full_row_width = horizontal_margin + width + horizontal_margin; + + // For writing the image bit stream. + data_chunk image_out; + data_sink image_sink(image_out); + ostream_writer image_writer(image_sink); + ostream_bit_writer image_bit_writer(image_writer); + + // Write top margin. + for (size_t row = 0; row < vertical_margin; ++row) + for (size_t column = 0; column < full_row_width; ++column) + image_bit_writer.write_bit(pixel_off); + + // Write each row. + for (size_t row = 0; row < height; ++row) + { + // For repeatedly writing a row buffer. + data_chunk row_out; + data_sink row_sink(row_out); + ostream_writer row_writer(row_sink); + ostream_bit_writer row_bit_writer(row_writer); + + // Buffer left margin. + for (size_t column = 0; column < horizontal_margin; ++column) + row_bit_writer.write_bit(pixel_off); + + // Buffer scaled row pixels. + for (size_t column = 0; column < width; ++column) + { + // Read byte and extract pixel (least significant) bit. + const auto pixel_on = (image_reader.read_byte() & pixel_mask) != 0; + + // Buffer scaled pixel. + for (size_t scaled = 0; scaled < scale; ++scaled) + row_bit_writer.write_bit(pixel_on); + } + + // Buffer right margin. + for (size_t column = 0; column < horizontal_margin; ++column) + row_bit_writer.write_bit(pixel_off); + + // Write row buffer scale times. + for (size_t scaled = 0; scaled < scale; ++scaled) + { + // For repeatedly reading the row buffer. + data_source row_source(row_out); + istream_reader row_reader(row_source); + istream_bit_reader row_bit_reader(row_reader); + + image_bit_writer.write_bit(row_bit_reader.read_bit()); + } + } + + // Write bottom margin. + for (size_t row = 0; row < vertical_margin; ++row) + for (size_t column = 0; column < full_row_width; ++column) + image_bit_writer.write_bit(pixel_off); + + // Guard against writer failure and unexpected stream length. + if (!image_bit_writer || !image_reader || !image_reader.is_exhausted()) + return {}; + + return image_out; +} + +} // namespace system +} // namespace libbitcoin diff --git a/src/utility/tiff.cpp b/src/utility/tiff.cpp new file mode 100644 index 0000000000..2f7e6018f1 --- /dev/null +++ b/src/utility/tiff.cpp @@ -0,0 +1,272 @@ +/** + * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace libbitcoin { +namespace system { + +enum tiff_header : uint16_t +{ + // "II" Intel byte ordering. + little_endian = 0x4949, + + // "MM" Motorola byte ordering. + big_endian = 0x4d4d, + + // An arbitrary but carefully chosen number, always 42. + magic_number = 0x002a +}; + +enum directory_header : uint16_t +{ + // Implement only the ten required entries. + entry_count = 0x000a +}; + +enum libbitcoin_token : uint32_t +{ + // Make the image data easy to visually locate in a hex dump. + arbitrary_data_delimiter = 0xbaadf00d +}; + +enum field_tag : uint16_t +{ + image_width = 0x0100, + image_length = 0x0101, + compression = 0x0103, + photometric_interpretation = 0x0106, + strip_offsets = 0x0111, + rows_per_strip = 0x0116, + strip_byte_counts = 0x0117, + x_resolution = 0x011a, + y_resolution = 0x011b, + resolution_unit = 0x0128 +}; + +enum field_type : uint16_t +{ + half = 3, + full = 4, + ratio = 5 +}; + +enum field_value_count : uint32_t +{ + single = 1 +}; + +enum offset : uint32_t +{ + terminator = 0 +}; + +enum compression_mode : uint16_t +{ + none = 1, + modified_huffman = 2, + pack_bits = 32773 +}; + +enum zero_color : uint16_t +{ + white = 0, + black = 1 +}; + +enum resolution_units : uint16_t +{ + unspecified = 0, + pixels_per_inch = 1, + pixels_per_centimeter = 2 +}; + +enum pad : uint16_t +{ + zero = 0 +}; + +// Offset calculations. +constexpr auto directory0_offset = sizeof(tiff_header::big_endian) + + sizeof(tiff_header::magic_number) + sizeof(offset); +constexpr auto entry0_offset = directory0_offset + + sizeof(directory_header::entry_count); +constexpr auto entry_size = sizeof(field_tag) + sizeof(field_type) + + sizeof(field_value_count) + sizeof(offset); +constexpr auto x_resolution_offset = entry0_offset + + directory_header::entry_count * entry_size + + sizeof(offset::terminator) + sizeof(pad::zero); +constexpr auto y_resolution_offset = x_resolution_offset + sizeof(offset) + + sizeof(offset); +constexpr auto strip0_offset = y_resolution_offset + sizeof(offset) + + sizeof(offset) + sizeof(arbitrary_data_delimiter); + +// Offset values must be on word boundaries. +static_assert(directory0_offset % sizeof(offset) == 0, + "TIFF directory must begin on a word boundary."); +static_assert(x_resolution_offset % sizeof(offset) == 0, + "TIFF offset value must begin on a word boundary (x resolutions)."); +static_assert(y_resolution_offset % sizeof(offset) == 0, + "TIFF offset value must begin on a word boundary (y resolutions)."); +static_assert(strip0_offset % sizeof(offset) == 0, + "TIFF offset value must begin on a word boundary (strip)."); + +// Public symbol used to parse file for image stream. +uint32_t tiff::image_offset = strip0_offset; +uint32_t tiff::max_image_bytes = 0x1fffc001; + +// Data size must be [(width * width + 7u) / 8u] bytes. +// Max achievable data size given 16 bit integer width is 0x1fffc001. +bool tiff::to_image(std::ostream& out, const data_chunk& data, uint16_t width) +{ + // Get pixel area, safe because (2^16 - 1)^2 < (2^32 - 1). + const auto area = width * static_cast(width); + + // Total number of pixels divided into bytes, last byte may be partial. + // Safe: ((2^16) - 1)^2 + 7) / 8 = 536,854,528.125 = 536,854,529 bytes. + const auto size = static_cast((area + 7u) / bc::byte_bits); + + // Guard against mismatched image size. + if (size != data.size()) + return false; + + ostream_writer writer(out); + + // =============== Header =============== + + // These sentinals are symmetrical, so order does not matter. + // But all writes with endianness below must conform to this setting. + writer.write_2_bytes_big_endian(tiff_header::big_endian); + + // An arbitrary delimeter, always 42. + writer.write_2_bytes_big_endian(tiff_header::magic_number); + + // Offset of IFD[0] (size of header). + writer.write_4_bytes_big_endian(directory0_offset); + + // --------------- IFD[0] --------------- + + // Number of IFD[0] entries (fields). + writer.write_2_bytes_big_endian(entry_count); + + // Write all required fields in required order. + // An IFDE is always 12 bytes long (the set is an array). + // ............... IFDE[0] .............. + writer.write_2_bytes_big_endian(field_tag::image_width); + writer.write_2_bytes_big_endian(field_type::full); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_4_bytes_big_endian(width); + + // ............... IFDE[1] .............. + writer.write_2_bytes_big_endian(field_tag::image_length); + writer.write_2_bytes_big_endian(field_type::full); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_4_bytes_big_endian(width); + + // ............... IFDE[2] .............. + writer.write_2_bytes_big_endian(field_tag::compression); + writer.write_2_bytes_big_endian(field_type::half); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_2_bytes_big_endian(compression_mode::none); + writer.write_2_bytes_big_endian(pad::zero); + + // ............... IFDE[3] .............. + writer.write_2_bytes_big_endian(field_tag::photometric_interpretation); + writer.write_2_bytes_big_endian(field_type::half); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_2_bytes_big_endian(zero_color::white); + writer.write_2_bytes_big_endian(pad::zero); + + // ............... IFDE[4] .............. + writer.write_2_bytes_big_endian(field_tag::strip_offsets); + writer.write_2_bytes_big_endian(field_type::full); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_4_bytes_big_endian(strip0_offset); + + // ............... IFDE[5] .............. + writer.write_2_bytes_big_endian(field_tag::rows_per_strip); + writer.write_2_bytes_big_endian(field_type::full); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_4_bytes_big_endian(width); + + // ............... IFDE[6] .............. + writer.write_2_bytes_big_endian(field_tag::strip_byte_counts); + writer.write_2_bytes_big_endian(field_type::full); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_4_bytes_big_endian(size); + + // ............... IFDE[7] .............. + writer.write_2_bytes_big_endian(field_tag::x_resolution); + writer.write_2_bytes_big_endian(field_type::ratio); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_4_bytes_big_endian(x_resolution_offset); + + // ............... IFDE[8] .............. + writer.write_2_bytes_big_endian(field_tag::y_resolution); + writer.write_2_bytes_big_endian(field_type::ratio); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_4_bytes_big_endian(y_resolution_offset); + + // ............... IFDE[9] .............. + writer.write_2_bytes_big_endian(field_tag::resolution_unit); + writer.write_2_bytes_big_endian(field_type::half); + writer.write_4_bytes_big_endian(field_value_count::single); + writer.write_2_bytes_big_endian(resolution_units::pixels_per_inch); + writer.write_2_bytes_big_endian(pad::zero); + + // -------------------------------------- + + // Offset of IFD[1] or null terminator (the set is a linked list). + writer.write_4_bytes_big_endian(offset::terminator); + + // ====================================== + + // Pad to get offsets onto word boundaries. + writer.write_2_bytes_big_endian(pad::zero); + + // x_resolution data [numerator][denominator] + writer.write_4_bytes_big_endian(72); + writer.write_4_bytes_big_endian(1); + + // y_resolution data [numerator][denominator] + writer.write_4_bytes_big_endian(72); + writer.write_4_bytes_big_endian(1); + + // ====================================== + + // Make the image data easy to visually locate in a hex dump. + writer.write_4_bytes_big_endian(arbitrary_data_delimiter); + + // Strip0 (image data). + writer.write_bytes(data); + + out.flush(); + return true; +} + +} // namespace system +} // namespace libbitcoin diff --git a/src/wallet/qrcode.cpp b/src/wallet/qrcode.cpp deleted file mode 100644 index 198b0a3008..0000000000 --- a/src/wallet/qrcode.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef WITH_QRENCODE - -namespace libbitcoin { -namespace system { -namespace wallet { - -data_chunk qr::encode(const data_chunk& data) -{ - return qr::encode(data, version, level, mode, case_sensitive); -} - -data_chunk qr::encode(const data_chunk& data, uint32_t version, - error_recovery_level level, encode_mode mode, bool case_sensitive) -{ - data_chunk out; - data_sink ostream(out); - data_source istream(data); - - if (qr::encode(istream, version, level, mode, case_sensitive, ostream)) - return out; - - return {}; -} - -bool qr::encode(std::istream& in, std::ostream& out) -{ - return qr::encode(in, version, level, mode, case_sensitive, out); -} - -bool qr::encode(std::istream& in, uint32_t version, error_recovery_level level, - encode_mode mode, bool case_sensitive, std::ostream& out) -{ - std::string qr_string; - getline(in, qr_string); - - const auto qrcode = QRcode_encodeString(qr_string.c_str(), version, - level, mode, case_sensitive); - - if (qrcode == nullptr) - return false; - - const auto area = qrcode->width * qrcode->width; - if ((area == 0) || (qrcode->width > max_int32 / qrcode->width)) - return false; - - auto width_ptr = reinterpret_cast(&qrcode->width); - auto version_ptr = reinterpret_cast(&qrcode->version); - - // Write out raw format of QRcode structure (defined in qrencode.h). - // Format written is: - // int version - // int width - // unsigned char* data (of width^2 length) - ostream_writer sink(out); - sink.write_bytes(version_ptr, sizeof(int)); - sink.write_bytes(width_ptr, sizeof(int)); - sink.write_bytes(qrcode->data, area); - out.flush(); - - return true; -} - -} // namespace wallet -} // namespace system -} // namespace libbitcoin - -#endif // WITH_QRENCODE diff --git a/test/utility/png.cpp b/test/utility/png.cpp deleted file mode 100644 index 35d35484bf..0000000000 --- a/test/utility/png.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#include -#include - -#include - -using namespace bc::system; - -BOOST_AUTO_TEST_SUITE(png_tests) - -#ifdef WITH_PNG - -// This test may be sensitive to changes in dependency conversion formatting. -BOOST_AUTO_TEST_CASE(png__write_png__size_one__success) -{ - const data_chunk bitmap - { - 0x03, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, - 0x03, 0x03, 0x03, 0x02, 0x03, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0xc0, 0xc1, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, - 0xc1, 0xc0, 0x84, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x03, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, - 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x03, 0x02, 0x03, - 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0xc0, 0xc1, 0xc0, 0xc1, - 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, - 0x84, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, - 0x03, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, - 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x91, 0x90, - 0x91, 0x90, 0x91, 0x90, 0x91, 0x90, 0x91, 0x90, 0x91, 0x90, 0x91, 0xc0, - 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0x84, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x02, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x91, 0x85, 0x85, 0x03, 0x02, 0x03, - 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x85, 0x84, 0x85, - 0x84, 0x85, 0x84, 0x85, 0x84, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x90, - 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, - 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, - 0x03, 0x02, 0x03, 0x03, 0x91, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, - 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x90, 0x02, 0x03, - 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, 0x03, - 0x02, 0x03, 0x91, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, - 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x90, 0x02, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, - 0x91, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, - 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x03, 0x02, 0x90, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, - 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x91, 0x02, - 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, - 0x03, 0x02, 0x02, 0x90, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, - 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, - 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x91, 0x02, 0x02, 0x02, - 0x03, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, - 0x03, 0x90, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, - 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, - 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x91, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0x02, 0x03, 0x03, 0x02, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0x81, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, 0x03, 0x03, 0x03, 0x03, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0xa1, 0xa0, 0xa1, 0xa0, 0xa1, 0x02, - 0x03, 0x02, 0x02, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x84, - 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0xa1, - 0xa0, 0xa0, 0xa0, 0xa1, 0x02, 0x02, 0x03, 0x03, 0xc1, 0xc0, 0xc1, 0xc1, - 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x03, 0x02, 0x02, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0x03, 0x03, 0x03, - 0x03, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, - 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0xc1, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x02, 0x03, - 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, - 0x02, 0x02, 0x03, 0x02, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, - 0x85, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02 - }; - - const data_chunk expected - { - 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d, - 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, 0x21, - 0x01, 0x03, 0x00, 0x00, 0x00, 0x6d, 0x2a, 0x50, 0x2c, 0x00, 0x00, 0x00, - 0x06, 0x50, 0x4c, 0x54, 0x45, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xa5, - 0xd9, 0x9f, 0xdd, 0x00, 0x00, 0x00, 0x02, 0x74, 0x52, 0x4e, 0x53, 0xff, - 0xff, 0xc8, 0xb5, 0xdf, 0xc7, 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, - 0x73, 0x00, 0x00, 0x0a, 0xf8, 0x00, 0x00, 0x0a, 0xf8, 0x01, 0x66, 0x26, - 0x3c, 0xfd, 0x00, 0x00, 0x00, 0xaf, 0x49, 0x44, 0x41, 0x54, 0x08, 0x99, - 0x63, 0xf8, 0x0f, 0x02, 0x0c, 0x10, 0xf2, 0x40, 0x89, 0x2b, 0xe3, 0x7f, - 0x86, 0xfb, 0xe1, 0x4b, 0x6b, 0xff, 0x33, 0x5c, 0xac, 0xfd, 0xeb, 0x0a, - 0x24, 0x5d, 0x7a, 0x41, 0x64, 0xbe, 0x24, 0x90, 0xbc, 0xef, 0xb1, 0x1d, - 0x28, 0x7e, 0x20, 0x34, 0x14, 0xa8, 0xe6, 0xff, 0xe3, 0xef, 0x40, 0xf5, - 0x07, 0xb9, 0x24, 0x56, 0xff, 0x67, 0xf8, 0x32, 0x25, 0x31, 0xf2, 0x3f, - 0xc3, 0x95, 0xf2, 0xfd, 0xed, 0xff, 0x19, 0x7e, 0xdf, 0x2d, 0x03, 0x8a, - 0x7c, 0x72, 0xd1, 0xbc, 0xfe, 0x9f, 0xe1, 0xe1, 0x39, 0x09, 0x56, 0x20, - 0x69, 0xd0, 0xea, 0xfe, 0x9f, 0xe1, 0x6b, 0xf3, 0x55, 0xfe, 0xff, 0x0c, - 0x1f, 0xa2, 0xe4, 0x37, 0xfe, 0x67, 0xb8, 0xfd, 0x57, 0x20, 0xf0, 0x3f, - 0xc3, 0xf5, 0x72, 0xb9, 0xf3, 0x40, 0x5d, 0x67, 0xcd, 0x34, 0x81, 0xe6, - 0xe7, 0xf8, 0x08, 0x03, 0xcd, 0x3c, 0xce, 0x78, 0x10, 0x68, 0x7e, 0xc0, - 0xc4, 0x70, 0xa0, 0x5d, 0xd5, 0x92, 0x37, 0x81, 0xe2, 0xd1, 0x6b, 0x80, - 0x76, 0x5d, 0xf4, 0x69, 0xbd, 0x08, 0x24, 0xc3, 0xe4, 0x81, 0x6a, 0xee, - 0xc7, 0xcc, 0x9d, 0x0d, 0x72, 0x43, 0xd5, 0x71, 0x98, 0x9b, 0xc1, 0x24, - 0x00, 0x15, 0x36, 0x6f, 0x4e, 0xff, 0x43, 0x64, 0x8e, 0x00, 0x00, 0x00, - 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 - }; - - data_chunk portable; - data_sink stream(portable); - BOOST_REQUIRE(png::write_png(bitmap, 1, stream)); - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(portable), encode_base16(expected)); -} - -#endif // WITH_PNG - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/utility/qr_code.cpp b/test/utility/qr_code.cpp new file mode 100644 index 0000000000..f3f5a68e27 --- /dev/null +++ b/test/utility/qr_code.cpp @@ -0,0 +1,58 @@ +/** + * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include + +using namespace bc::system; + +BOOST_AUTO_TEST_SUITE(qr_code_tests) + +#ifdef WITH_QRENCODE + +// This test may be sensitive to changes in qrencode conversion formatting. +BOOST_AUTO_TEST_CASE(qr_code__encode__always__expected) +{ + ////static const data_chunk expected + ////{ + //// // TODO: generate from qrencode. + ////}; + + ////data_chunk out; + ////data_sink sink(out); + ////BOOST_REQUIRE(!qr_code::encode(sink, "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus")); + ////BOOST_REQUIRE_EQUAL(out.size(), expected.size()); + + ////// Encode as base16 so that failure message is intelligible. + ////BOOST_REQUIRE_EQUAL(encode_base16(out), encode_base16(expected)); + BOOST_REQUIRE(true); +} + +#else + +BOOST_AUTO_TEST_CASE(qr_code__encode__not_implemented__false) +{ + data_chunk out; + data_sink sink(out); + BOOST_REQUIRE(!qr_code::encode(sink, "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus")); +} + +#endif // WITH_QRENCODE + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/utility/tiff.cpp b/test/utility/tiff.cpp new file mode 100644 index 0000000000..a7577345a8 --- /dev/null +++ b/test/utility/tiff.cpp @@ -0,0 +1,190 @@ +/** + * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include +#include + +#include + +using namespace bc::system; + +BOOST_AUTO_TEST_SUITE(tiff_tests) + +BOOST_AUTO_TEST_CASE(tiff__to_image_data__mismatched_image_width__false) +{ + // A square with sides of 5 pixels is [(5^2 + 7) / 8 = 4] bytes (not 42). + static const auto byte_size = 42u; + static const auto pixel_width = 5u; + + data_chunk bitmap(byte_size, 0); + data_chunk tiff; + data_sink stream(tiff); + BOOST_REQUIRE(!tiff::to_image(stream, bitmap, pixel_width)); +} + +BOOST_AUTO_TEST_CASE(tiff__to_image_data__matched_image_width_and_size__true) +{ + // A square with sides of 5 pixels is [(5^2 + 7) / 8 = 4] bytes. + static const auto byte_size = 4u; + static const auto pixel_width = 5u; + + // Set valid byte_size, other data is arbitrary. + data_chunk bitmap(byte_size, 0); + data_chunk tiff; + data_sink stream(tiff); + BOOST_REQUIRE(tiff::to_image(stream, bitmap, pixel_width)); +} + +BOOST_AUTO_TEST_CASE(tiff__to_image_data__zero_area__empty_true) +{ + static const data_chunk bitmap; + data_chunk tiff; + data_sink stream(tiff); + BOOST_REQUIRE(tiff::to_image(stream, bitmap, 0)); + BOOST_REQUIRE_EQUAL(tiff.size(), tiff::image_offset); +} + +BOOST_AUTO_TEST_CASE(tiff__to_image_data__max_width__expected_size_true) +{ + static const auto width = bc::max_uint16; + static const auto expected_image_bytes = tiff::max_image_bytes; + + // 511MB memory allocation here. + data_chunk bitmap(expected_image_bytes, 0); + data_chunk tiff; + data_sink stream(tiff); + BOOST_REQUIRE(tiff::to_image(stream, bitmap, width)); + BOOST_REQUIRE_EQUAL(tiff.size(), tiff::image_offset + expected_image_bytes); +} + +BOOST_AUTO_TEST_CASE(tiff__to_image_data__perfect_square__expected_true) +{ + // A square with sides of 4 pixels is [(4^2 + 7) / 8 = 2] bytes. + static const data_chunk bitmap + { + 0x2a, 0x2b + }; + + // Manually-contructed expectation of tiff encoding. + static const data_chunk expected + { + // Header + 0x4d, 0x4d, // "MM" Motorola encoding (big endian) + 0x00, 0x2a, // magic number (42) + 0x00, 0x00, 0x00, 0x08, // IFD0 offset + + // [Each directory may be anywhere in the file] + + // IFD0, word boundary required. + 0x00, 0x0a, // count of entries + + // IFDE0 + 0x01, 0x00, // image_width + 0x00, 0x04, // long value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, 0x00, 0x04, // side + + // IFDE1 + 0x01, 0x01, // image_length + 0x00, 0x04, // long value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, 0x00, 0x04, // side + + // IFDE2 + 0x01, 0x03, // compression + 0x00, 0x03, // short value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x01, // none + 0x00, 0x00, // pad + + // IFDE3 + 0x01, 0x06, // photometric_interpretation + 0x00, 0x03, // short value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, // zero is white + 0x00, 0x00, // pad + + // IFDE4 + 0x01, 0x11, // strip_offsets + 0x00, 0x04, // long value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, 0x00, 0x9c, // value (not offset) + + // IFDE5 + 0x01, 0x16, // rows_per_strip + 0x00, 0x04, // long value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, 0x00, 0x04, // side + + // IFDE6 + 0x01, 0x17, // strip_byte_counts + 0x00, 0x04, // long value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, 0x00, 0x02, // value (not offset) + + // IFDE7 + 0x01, 0x1a, // x_resolution + 0x00, 0x05, // ratio value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, 0x00, 0x88, // value (offset) + + // IFDE8 + 0x01, 0x1b, // y_resolution + 0x00, 0x05, // ratio value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x00, 0x00, 0x90, // value (offset) + + // IFDE9 + 0x01, 0x28, // resolution_unit + 0x00, 0x03, // short value + 0x00, 0x00, 0x00, 0x01, // count + 0x00, 0x01, // inch + 0x00, 0x00, // pad + + // IFD0 Terminator + 0x00, 0x00, 0x00, 0x00, // null teminated linked list + + // pad + 0x00, 0x00, // pad + + // [Each field value may be anywhere in the file.] + + // Offset field values, word boundaries required. + 0x00, 0x00, 0x00, 0x48, // horizontal resolution numerator + 0x00, 0x00, 0x00, 0x01, // horizontal resolution denominator + 0x00, 0x00, 0x00, 0x48, // vertical resolution numerator + 0x00, 0x00, 0x00, 0x01, // vertical resolution denominator + + // Libbitcoin proprietary data delimiter. + 0xba, 0xad, 0xf0, 0x0d, + + // [Image strips may be anywhere in the file.] + + // Image (strip). + 0x2a, 0x2b + }; + + data_chunk tiff; + data_sink stream(tiff); + BOOST_REQUIRE(tiff::to_image(stream, bitmap, 4)); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(tiff), encode_base16(expected)); +} + +BOOST_AUTO_TEST_SUITE_END() diff --git a/test/wallet/qrcode.cpp b/test/wallet/qrcode.cpp deleted file mode 100644 index ea8e5c1290..0000000000 --- a/test/wallet/qrcode.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#include - -#include - -using namespace bc::system; -using namespace bc::system::wallet; - -BOOST_AUTO_TEST_SUITE(qrcode_tests) - -#ifdef WITH_QRENCODE - -// This test may be sensitive to changes in dependency conversion formatting. -BOOST_AUTO_TEST_CASE(qrcode__construct__always__expected) -{ - static const data_chunk expected - { - 0x03, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc0, 0x84, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, - 0x03, 0x03, 0x03, 0x02, 0x03, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x03, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x03, 0xc0, 0xc1, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, - 0xc1, 0xc0, 0x84, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x03, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, - 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x03, 0x02, 0x03, - 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0xc0, 0xc1, 0xc0, 0xc1, - 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, - 0x84, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, - 0x03, 0xc0, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc1, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, - 0x03, 0x02, 0x02, 0x03, 0x02, 0x02, 0xc0, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x91, 0x90, - 0x91, 0x90, 0x91, 0x90, 0x91, 0x90, 0x91, 0x90, 0x91, 0x90, 0x91, 0xc0, - 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0xc0, 0xc0, 0x84, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x02, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x91, 0x85, 0x85, 0x03, 0x02, 0x03, - 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x85, 0x84, 0x85, - 0x84, 0x85, 0x84, 0x85, 0x84, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x90, - 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, - 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, - 0x03, 0x02, 0x03, 0x03, 0x91, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, - 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x90, 0x02, 0x03, - 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, 0x03, - 0x02, 0x03, 0x91, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, - 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x90, 0x02, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, - 0x91, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, - 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x03, 0x02, 0x90, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, - 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x91, 0x02, - 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, - 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, - 0x03, 0x02, 0x02, 0x90, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, - 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, - 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x91, 0x02, 0x02, 0x02, - 0x03, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, - 0x03, 0x90, 0x02, 0x03, 0x03, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x02, - 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x03, 0x03, - 0x03, 0x02, 0x03, 0x03, 0x03, 0x02, 0x91, 0x02, 0x02, 0x03, 0x02, 0x02, - 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0xa1, 0xa1, 0xa1, 0xa1, - 0xa1, 0x02, 0x03, 0x03, 0x02, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - 0xc0, 0x81, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, - 0x03, 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, 0x03, 0x03, 0x03, 0x03, 0xc1, 0xc1, - 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0xa1, 0xa0, 0xa1, 0xa0, 0xa1, 0x02, - 0x03, 0x02, 0x02, 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x84, - 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02, 0x03, 0xa1, - 0xa0, 0xa0, 0xa0, 0xa1, 0x02, 0x02, 0x03, 0x03, 0xc1, 0xc0, 0xc1, 0xc1, - 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x03, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x03, 0x02, 0x02, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0x03, 0x03, 0x03, - 0x03, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, 0xc0, 0x85, 0x03, 0x02, - 0x02, 0x03, 0x03, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x02, - 0x02, 0x03, 0x02, 0x03, 0x03, 0x03, 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, - 0xc1, 0xc0, 0x85, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x02, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x03, 0x03, 0x02, 0xc1, - 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc0, 0x85, 0x02, 0x02, 0x02, 0x03, - 0x03, 0x02, 0x03, 0x03, 0x02, 0x02, 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, - 0x02, 0x02, 0x03, 0x02, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc0, - 0x85, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x03, - 0x02, 0x03, 0x02, 0x02, 0x03, 0x03, 0x03, 0x02, 0x02 - }; - - const auto bitmap = qr::encode(to_chunk(std::string{ "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus" })); - BOOST_REQUIRE_EQUAL(bitmap.size(), expected.size()); - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(bitmap), encode_base16(expected)); -} - -#endif // WITH_QRENCODE - -BOOST_AUTO_TEST_SUITE_END() From d954f98c2ab398ecf125f12b2f834dfd8e35abf3 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Mar 2021 04:25:27 -0700 Subject: [PATCH 19/44] Style. --- src/formats/base_32.cpp | 53 ++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/src/formats/base_32.cpp b/src/formats/base_32.cpp index e67c117dd8..427acc69bb 100644 --- a/src/formats/base_32.cpp +++ b/src/formats/base_32.cpp @@ -28,11 +28,11 @@ namespace libbitcoin { namespace system { -static constexpr size_t checksum_size = 6; -static constexpr size_t prefix_min_size = 1; -static constexpr size_t combined_max_size = 90; -static constexpr size_t bit_group_size = 5; -static constexpr size_t bit_group_mask = 31; +static constexpr uint8_t checksum_size = 6; +static constexpr uint8_t prefix_min_size = 1; +static constexpr uint8_t combined_max_size = 90; +static constexpr uint8_t bit_group_size = 5; +static constexpr uint8_t bit_group_mask = 31; static constexpr uint8_t null = 255; static constexpr uint8_t separator = '1'; static const char encode_table[] = "qpzry9x8gf2tvdw0s3jn54khce6mua7l"; @@ -56,31 +56,20 @@ static const uint8_t decode_table[] = 6, 4, 2, null, null, null, null, null }; -inline char ascii_to_lowercase(char character) -{ - return character + ('a' - 'A'); -} - // Expand the prefix for checksum computation. data_chunk expand(const std::string& prefix) { - data_chunk result(2 * prefix.size() + 1); + data_chunk result(2u * prefix.size() + 1u, 0x00); auto iterator = result.begin(); for (const auto character: prefix) - { - *iterator = static_cast(character >> bit_group_size); - ++iterator; - } + *iterator++ = static_cast(character) >> bit_group_size; // Current position is initialized to 0x00 so skip it. ++iterator; for (const auto character: prefix) - { - *iterator = static_cast(character & bit_group_mask); - ++iterator; - } + *iterator++ = static_cast(character) & bit_group_mask; return result; } @@ -91,24 +80,22 @@ uint32_t polymod(const data_chunk& values) // Polynomials in the bech32 implementation are represented by // simple integers. Generally 30-bit integers are used, where each // bit corresponds to one coefficient of the polynomial. - // - // bitcoin.stackexchange.com/questions/74573/how-is-bech32-based-on-bch-codes static const uint32_t bech32_generator_polynomials[] = { 0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3 }; // Mask for low 25 bits. - const uint32_t checksum_mask = 0x1ffffff; + static const uint32_t checksum_mask = 0x1ffffff; uint32_t checksum = 1; for (const auto value: values) { - const auto shift = (checksum >> 25); + const auto shift = (checksum >> 25u); checksum = (checksum & checksum_mask) << bit_group_size ^ value; for (size_t index = 0; index < bit_group_size; ++index) - checksum ^= (((shift >> index) & 1) != 0 ? + checksum ^= (((shift >> index) & 1u) != 0 ? bech32_generator_polynomials[index] : 0); } @@ -118,11 +105,7 @@ uint32_t polymod(const data_chunk& values) // Compute the checksum. data_chunk checksum(const base32& value) { - static const data_chunk empty_checksum - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - + static const data_chunk empty_checksum(checksum_size, 0x00); const auto expanded = build_chunk( { expand(value.prefix), @@ -131,7 +114,7 @@ data_chunk checksum(const base32& value) }); data_chunk checksum(checksum_size); - const auto modified = polymod(expanded) ^ 1; + const auto modified = polymod(expanded) ^ 1u; for (size_t index = 0; index < checksum_size; ++index) checksum[index] = (modified >> bit_group_size * (bit_group_size - @@ -153,7 +136,7 @@ static bool normalize(data_chunk& out, const std::string& in) if (character >= 'A' && character <= 'Z') { uppercase = true; - character = ascii_to_lowercase(character); + character += ('a' - 'A'); } else if (character >= 'a' && character <= 'z') { @@ -168,7 +151,7 @@ static bool normalize(data_chunk& out, const std::string& in) } // Must not accept mixed case strings. - return !uppercase || !lowercase; + return !(uppercase && lowercase); } // Split the prefix from the payload and validate sizes. @@ -189,11 +172,11 @@ static bool split(base32& out, const data_chunk& in) return false; // Convert separator iterator from reverse to forward (min distance is 1). - const auto offset = std::distance(reverse, in.rend()) - 1; + const auto offset = std::distance(reverse, in.rend()) - 1u; // Clang 3.4 cannot handle iterator variable here, so this is a bit ugly. out.prefix = { in.begin(), std::next(in.begin(), offset) }; - out.payload = { std::next(in.begin(), offset + 1), in.end() }; + out.payload = { std::next(in.begin(), offset + 1u), in.end() }; return out.prefix.size() >= prefix_min_size && @@ -210,7 +193,7 @@ bool verify(const base32& value) value.payload }); - return polymod(expanded) == 1; + return polymod(expanded) == 1u; } // public From 4e451b674885186158f4945ccd1894cc6973ec43 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Mar 2021 04:25:49 -0700 Subject: [PATCH 20/44] Fix unused var warnings, qr_encode logic, add tests. --- src/utility/qr_code.cpp | 18 ++++++++--- test/utility/qr_code.cpp | 65 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/src/utility/qr_code.cpp b/src/utility/qr_code.cpp index c2ee37d1d2..8d01dc62cc 100644 --- a/src/utility/qr_code.cpp +++ b/src/utility/qr_code.cpp @@ -40,6 +40,7 @@ namespace libbitcoin { namespace system { #ifdef WITH_QRENCODE + static QRecLevel recovery_level_to_qr_recovery_level( qr_code::recovery_level level) { @@ -78,13 +79,11 @@ static QRencodeMode encode_mode_to_qr_encode_mode(qr_code::encode_mode mode) return QR_MODE_NUL; } } -#endif bool qr_code::encode(std::ostream& out, const std::string& value, uint32_t version, uint16_t scale, uint16_t margin, bool case_sensitive, recovery_level level, encode_mode mode) { -#ifdef WITH_QRENCODE const auto qrcode = QRcode_encodeString(value.c_str(), version, recovery_level_to_qr_recovery_level(level), encode_mode_to_qr_encode_mode(mode), case_sensitive); @@ -117,11 +116,18 @@ bool qr_code::encode(std::ostream& out, const std::string& value, // Convert to TIFF image stream (does not fail as long as sizes match). return tiff::to_image(out, pixels, width); +} + #else + +bool qr_code::encode(std::ostream&, const std::string&, uint32_t, uint16_t, + uint16_t, bool, recovery_level, encode_mode) +{ return false; -#endif } +#endif + // Scale may move the image off of a byte-aligned square of pixels in bytes. // So the dimensions cannot be derived from the result, caller must retain. // pixel_width = width * scale. @@ -143,7 +149,8 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, return {}; // Guard against mismatched sizes from qrencode. - if (coded.size() != width * static_cast(width)) + if (coded.size() - sizeof(uint32_t) - sizeof(uint32_t) != width * + static_cast(width)) return {}; // Any scale increase can potentially cause an overflow. @@ -202,6 +209,8 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, for (size_t column = 0; column < horizontal_margin; ++column) row_bit_writer.write_bit(pixel_off); + row_sink.flush(); + // Write row buffer scale times. for (size_t scaled = 0; scaled < scale; ++scaled) { @@ -223,6 +232,7 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, if (!image_bit_writer || !image_reader || !image_reader.is_exhausted()) return {}; + image_sink.flush(); return image_out; } diff --git a/test/utility/qr_code.cpp b/test/utility/qr_code.cpp index f3f5a68e27..d492d5d94c 100644 --- a/test/utility/qr_code.cpp +++ b/test/utility/qr_code.cpp @@ -55,4 +55,69 @@ BOOST_AUTO_TEST_CASE(qr_code__encode__not_implemented__false) #endif // WITH_QRENCODE +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_header__empty) +{ + // Must be at least 8 bytes of data (header). + BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data_chunk(7, 0)), data_chunk{}); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_0_margin_0__empty) +{ + static const data_chunk data + { + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00 + }; + + BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 0, 0), data_chunk{}); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_8_margin_2__expected) +{ + static const data_chunk data + { + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00 + }; + + // A 2 pixel margin on an empty image creates 16 zeroed pixels. + static const data_chunk expected{ 0x00, 0x00 }; + BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 8, 2), expected); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_0_margin_0__empty) +{ + static const data_chunk data + { + 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, + 0xff + }; + + // Scale zero creates an empty image, and there is no margin specified. + BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 0, 0), data_chunk{}); +} + +// TODO: create low-to-high (little endian) and +// high-to-low (big-endian) bit methods for bit reader/writer. +// This requires LE and Golomg coding used BE. +// Also the bit writer requires a flush override for partial bytes. +////BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_1_margin_0__expected) +////{ +//// static const data_chunk data +//// { +//// 0xff, 0xff, 0xff, 0xff, +//// 0x01, 0x00, 0x00, 0x00, +//// +//// // The least significant bit determines the pixel color. +//// 0x01 +//// }; +//// +//// // Scale 1 does not expand. A single pixel image with no margin creates a +//// // one byte image with only the least significant bit set to 1. +//// static const data_chunk expected{ 0x01 }; +//// BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 1, 0), expected); +////} + + BOOST_AUTO_TEST_SUITE_END() From 3eda1702e2c126e9885284987065290954276e3a Mon Sep 17 00:00:00 2001 From: evoskuil Date: Mon, 15 Mar 2021 21:07:44 -0700 Subject: [PATCH 21/44] Add tests and fix bugs in qr_code image conversion. --- .../libbitcoin-system-test.vcxproj | 7 +- .../system/utility/ostream_bit_writer.hpp | 4 +- src/utility/ostream_bit_writer.cpp | 2 +- src/utility/qr_code.cpp | 25 +++- test/utility/qr_code.cpp | 123 ++++++++++++++---- 5 files changed, 124 insertions(+), 37 deletions(-) diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj index a53509eafc..a7a87a0766 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -259,9 +259,14 @@ + + + "$(TargetPath)" --run_test=qr_code_tests --show_progress=no --result_code=no --detect_memory_leak=0 --report_level=no --build_info=yes + + {39F60708-FF48-4C22-952D-43470866F684} - + \ No newline at end of file diff --git a/include/bitcoin/system/utility/ostream_bit_writer.hpp b/include/bitcoin/system/utility/ostream_bit_writer.hpp index 389d95deb8..6fc20a7d4f 100644 --- a/include/bitcoin/system/utility/ostream_bit_writer.hpp +++ b/include/bitcoin/system/utility/ostream_bit_writer.hpp @@ -101,8 +101,10 @@ class BC_API ostream_bit_writer /// Advance iterator without writing. void skip(size_t size); -protected: + /// Flush the buffer on a zero-padded byte boundary. void flush(); + +protected: void buffered_write(data_chunk& data); private: diff --git a/src/utility/ostream_bit_writer.cpp b/src/utility/ostream_bit_writer.cpp index 3cc6b04283..7ee3da8835 100644 --- a/src/utility/ostream_bit_writer.cpp +++ b/src/utility/ostream_bit_writer.cpp @@ -236,7 +236,7 @@ void ostream_bit_writer::write_bit(bool value) buffer_ |= (byte_value >> offset_); offset_++; - if (offset_ >= byte_bits) + if (offset_ == byte_bits) flush(); } diff --git a/src/utility/qr_code.cpp b/src/utility/qr_code.cpp index 8d01dc62cc..63d5c208f2 100644 --- a/src/utility/qr_code.cpp +++ b/src/utility/qr_code.cpp @@ -148,16 +148,21 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, if (!image_reader) return {}; + // Bounds: (2^32 - 1)^2 < (2^64 - 1). // Guard against mismatched sizes from qrencode. if (coded.size() - sizeof(uint32_t) - sizeof(uint32_t) != width * static_cast(width)) return {}; - // Any scale increase can potentially cause an overflow. + // Bounds: 2^16 * 2^32 < 2^48 < 2^64. const auto scaled_width = scale * static_cast(width); - // Guard against scaling overflow. - if (scaled_width > max_uint32) + // Bounds: 2^48 + 2 * 2^16 < 2^48 + 2^17 < 2 * 2^48 < 2^64. + const auto full_width = margin + scaled_width + margin; + + // TODO: test. + // Guard against index overflows (all below limited to size_t). + if (full_width > 0u && max_size_t / full_width < full_width) return {}; // Pixel is the least significant bit of a qrencode byte. @@ -168,7 +173,6 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, const auto height = width; const auto vertical_margin = margin; const auto horizontal_margin = margin; - const auto full_row_width = horizontal_margin + width + horizontal_margin; // For writing the image bit stream. data_chunk image_out; @@ -178,7 +182,7 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, // Write top margin. for (size_t row = 0; row < vertical_margin; ++row) - for (size_t column = 0; column < full_row_width; ++column) + for (size_t column = 0; column < full_width; ++column) image_bit_writer.write_bit(pixel_off); // Write each row. @@ -209,6 +213,8 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, for (size_t column = 0; column < horizontal_margin; ++column) row_bit_writer.write_bit(pixel_off); + // Flush any partial byte and then flush bytes to data_chunk. + row_bit_writer.flush(); row_sink.flush(); // Write row buffer scale times. @@ -219,20 +225,25 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, istream_reader row_reader(row_source); istream_bit_reader row_bit_reader(row_reader); - image_bit_writer.write_bit(row_bit_reader.read_bit()); + // Copy each bit in the row buffer to the output buffer. + for (size_t column = 0; column < full_width; ++column) + image_bit_writer.write_bit(row_bit_reader.read_bit()); } } // Write bottom margin. for (size_t row = 0; row < vertical_margin; ++row) - for (size_t column = 0; column < full_row_width; ++column) + for (size_t column = 0; column < full_width; ++column) image_bit_writer.write_bit(pixel_off); // Guard against writer failure and unexpected stream length. if (!image_bit_writer || !image_reader || !image_reader.is_exhausted()) return {}; + // Flush any partial byte and then flush bytes to data_chunk. + image_bit_writer.flush(); image_sink.flush(); + return image_out; } diff --git a/test/utility/qr_code.cpp b/test/utility/qr_code.cpp index d492d5d94c..d73427e457 100644 --- a/test/utility/qr_code.cpp +++ b/test/utility/qr_code.cpp @@ -55,10 +55,19 @@ BOOST_AUTO_TEST_CASE(qr_code__encode__not_implemented__false) #endif // WITH_QRENCODE -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_header__empty) +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__partial_header__empty) { - // Must be at least 8 bytes of data (header). - BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data_chunk(7, 0)), data_chunk{}); + static const data_chunk data + { + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00 + }; + + // Must be at least 8 bytes of data (header), so empty result (failure). + static const data_chunk expected{}; + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data)), encode_base16(expected)); } BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_0_margin_0__empty) @@ -69,7 +78,11 @@ BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_0_margin_0__empty) 0x00, 0x00, 0x00, 0x00 }; - BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 0, 0), data_chunk{}); + // Empty image with no margin creates empty result (success). + static const data_chunk expected{}; + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 0, 0)), encode_base16(expected)); } BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_8_margin_2__expected) @@ -82,7 +95,9 @@ BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_8_margin_2__expected // A 2 pixel margin on an empty image creates 16 zeroed pixels. static const data_chunk expected{ 0x00, 0x00 }; - BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 8, 2), expected); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 8, 2)), encode_base16(expected)); } BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_0_margin_0__empty) @@ -94,30 +109,84 @@ BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_0_margin_0__empty) 0xff }; - // Scale zero creates an empty image, and there is no margin specified. - BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 0, 0), data_chunk{}); + // Scale zero creates an empty image if there is no margin specified. + static const data_chunk expected{}; + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 0, 0)), encode_base16(expected)); } -// TODO: create low-to-high (little endian) and -// high-to-low (big-endian) bit methods for bit reader/writer. -// This requires LE and Golomg coding used BE. -// Also the bit writer requires a flush override for partial bytes. -////BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_1_margin_0__expected) -////{ -//// static const data_chunk data -//// { -//// 0xff, 0xff, 0xff, 0xff, -//// 0x01, 0x00, 0x00, 0x00, -//// -//// // The least significant bit determines the pixel color. -//// 0x01 -//// }; -//// -//// // Scale 1 does not expand. A single pixel image with no margin creates a -//// // one byte image with only the least significant bit set to 1. -//// static const data_chunk expected{ 0x01 }; -//// BOOST_REQUIRE_EQUAL(qr_code::to_image_data(data, 1, 0), expected); -////} +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_1_margin_0__expected) +{ + static const data_chunk data + { + 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, + + // // This pixel state is true. + 0x01 + }; + + // Scale 1 does not expand. A single pixel image with no margin creates a + // one byte image with only the most significant bit set to 1. + static const data_chunk expected{ 0x80 }; + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 1, 0)), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_1_margin_1__expected) +{ + static const data_chunk data + { + 0xff, 0xff, 0xff, 0xff, + 0x01, 0x00, 0x00, 0x00, + + // This pixel state is true. + 0x01 + }; + + // Scale 1 does not expand. A single pixel image with single pixel margin + // creates a 9 pixel image with the 5th most significant bit set. + static const data_chunk expected{ 0x08, 0x00 }; + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 1, 1)), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_image_data__four_pixel_scale_2_margin_2__expected) +{ + static const data_chunk data + { + 0xff, 0xff, 0xff, 0xff, + 0x02, 0x00, 0x00, 0x00, + + // The pixel states are true, true, false, false. + 0x01, 0xff, + 0xfe, 0xfe + }; + + // Area is 2x2px so image is scaled to 4x4px and 2px margin makes it 8x8px. + static const data_chunk expected + { + // byte pixel + 0x00, // 00 0000 00 + 0x00, // 00 0000 00 + + 0x3c, // 00 1111 00 + 0x3c, // 00 1111 00 + + 0x00, // 00 0000 00 + 0x00, // 00 0000 00 + + 0x00, // 00 0000 00 + 0x00 // 00 0000 00 + }; + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 2, 2)), encode_base16(expected)); +} +// TODO: determine if TIFF encoding renders bits high-to-low => left-to-right. BOOST_AUTO_TEST_SUITE_END() From cfd125b4a1142c5b06b009a65267e15e6767a02c Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 17 Mar 2021 15:57:27 -0700 Subject: [PATCH 22/44] Qrencode WIP. --- Makefile.am | 27 +- builds/cmake/CMakeLists.txt | 25 +- .../libbitcoin-system-test.vcxproj | 2 +- .../libbitcoin-system-test.vcxproj.filters | 6 +- .../libbitcoin-system.vcxproj | 23 +- .../libbitcoin-system.vcxproj.filters | 118 +- .../libbitcoin-system-test.vcxproj | 2 +- .../libbitcoin-system-test.vcxproj.filters | 6 +- .../libbitcoin-system.vcxproj | 23 +- .../libbitcoin-system.vcxproj.filters | 116 +- .../libbitcoin-system-test.vcxproj | 2 +- .../libbitcoin-system-test.vcxproj.filters | 6 +- .../libbitcoin-system.vcxproj | 23 +- .../libbitcoin-system.vcxproj.filters | 116 +- include/bitcoin/system.hpp | 2 +- .../system/{utility => wallet}/qr_code.hpp | 24 +- src/{utility => wallet}/qr_code.cpp | 156 +- src/wallet/qrencode/bitstream.c | 231 +++ src/wallet/qrencode/bitstream.h | 43 + src/wallet/qrencode/mask.c | 357 ++++ src/wallet/qrencode/mask.h | 38 + src/wallet/qrencode/mmask.c | 177 ++ src/wallet/qrencode/mmask.h | 34 + src/wallet/qrencode/mqrspec.c | 232 +++ src/wallet/qrencode/mqrspec.h | 150 ++ src/wallet/qrencode/qrencode.c | 940 ++++++++++ src/wallet/qrencode/qrencode.h | 572 ++++++ src/wallet/qrencode/qrencode_inner.h | 88 + src/wallet/qrencode/qrinput.c | 1639 +++++++++++++++++ src/wallet/qrencode/qrinput.h | 124 ++ src/wallet/qrencode/qrspec.c | 514 ++++++ src/wallet/qrencode/qrspec.h | 174 ++ src/wallet/qrencode/rsecc.c | 149 ++ src/wallet/qrencode/rsecc.h | 31 + src/wallet/qrencode/split.c | 325 ++++ src/wallet/qrencode/split.h | 47 + test/utility/qr_code.cpp | 192 -- test/wallet/qr_code.cpp | 269 +++ 38 files changed, 6614 insertions(+), 389 deletions(-) rename include/bitcoin/system/{utility => wallet}/qr_code.hpp (69%) rename src/{utility => wallet}/qr_code.cpp (60%) create mode 100644 src/wallet/qrencode/bitstream.c create mode 100644 src/wallet/qrencode/bitstream.h create mode 100644 src/wallet/qrencode/mask.c create mode 100644 src/wallet/qrencode/mask.h create mode 100644 src/wallet/qrencode/mmask.c create mode 100644 src/wallet/qrencode/mmask.h create mode 100644 src/wallet/qrencode/mqrspec.c create mode 100644 src/wallet/qrencode/mqrspec.h create mode 100644 src/wallet/qrencode/qrencode.c create mode 100644 src/wallet/qrencode/qrencode.h create mode 100644 src/wallet/qrencode/qrencode_inner.h create mode 100644 src/wallet/qrencode/qrinput.c create mode 100644 src/wallet/qrencode/qrinput.h create mode 100644 src/wallet/qrencode/qrspec.c create mode 100644 src/wallet/qrencode/qrspec.h create mode 100644 src/wallet/qrencode/rsecc.c create mode 100644 src/wallet/qrencode/rsecc.h create mode 100644 src/wallet/qrencode/split.c create mode 100644 src/wallet/qrencode/split.h delete mode 100644 test/utility/qr_code.cpp create mode 100644 test/wallet/qr_code.cpp diff --git a/Makefile.am b/Makefile.am index 73fffa8bf0..50abdd849c 100755 --- a/Makefile.am +++ b/Makefile.am @@ -191,7 +191,6 @@ src_libbitcoin_system_la_SOURCES = \ src/utility/prioritized_mutex.cpp \ src/utility/property_tree.cpp \ src/utility/pseudo_random.cpp \ - src/utility/qr_code.cpp \ src/utility/scope_lock.cpp \ src/utility/sequencer.cpp \ src/utility/sequential_lock.cpp \ @@ -229,6 +228,7 @@ src_libbitcoin_system_la_SOURCES = \ src/wallet/mini_keys.cpp \ src/wallet/mnemonic.cpp \ src/wallet/payment_address.cpp \ + src/wallet/qr_code.cpp \ src/wallet/select_outputs.cpp \ src/wallet/stealth_address.cpp \ src/wallet/stealth_receiver.cpp \ @@ -244,7 +244,26 @@ src_libbitcoin_system_la_SOURCES = \ src/wallet/parse_encrypted_keys/parse_encrypted_public.cpp \ src/wallet/parse_encrypted_keys/parse_encrypted_public.hpp \ src/wallet/parse_encrypted_keys/parse_encrypted_token.cpp \ - src/wallet/parse_encrypted_keys/parse_encrypted_token.hpp + src/wallet/parse_encrypted_keys/parse_encrypted_token.hpp \ + src/wallet/qrencode/bitstream.c \ + src/wallet/qrencode/bitstream.h \ + src/wallet/qrencode/mask.c \ + src/wallet/qrencode/mask.h \ + src/wallet/qrencode/mmask.c \ + src/wallet/qrencode/mmask.h \ + src/wallet/qrencode/mqrspec.c \ + src/wallet/qrencode/mqrspec.h \ + src/wallet/qrencode/qrencode.c \ + src/wallet/qrencode/qrencode.h \ + src/wallet/qrencode/qrencode_inner.h \ + src/wallet/qrencode/qrinput.c \ + src/wallet/qrencode/qrinput.h \ + src/wallet/qrencode/qrspec.c \ + src/wallet/qrencode/qrspec.h \ + src/wallet/qrencode/rsecc.c \ + src/wallet/qrencode/rsecc.h \ + src/wallet/qrencode/split.c \ + src/wallet/qrencode/split.h # local: examples/libbitcoin-system-examples #------------------------------------------------------------------------------ @@ -373,7 +392,6 @@ test_libbitcoin_system_test_SOURCES = \ test/utility/neutrino_filter.cpp \ test/utility/property_tree.cpp \ test/utility/pseudo_random.cpp \ - test/utility/qr_code.cpp \ test/utility/serializer.cpp \ test/utility/stream.cpp \ test/utility/thread.cpp \ @@ -389,6 +407,7 @@ test_libbitcoin_system_test_SOURCES = \ test/wallet/mnemonic.cpp \ test/wallet/mnemonic.hpp \ test/wallet/payment_address.cpp \ + test/wallet/qr_code.cpp \ test/wallet/select_outputs.cpp \ test/wallet/stealth_address.cpp \ test/wallet/stealth_receiver.cpp \ @@ -654,7 +673,6 @@ include_bitcoin_system_utility_HEADERS = \ include/bitcoin/system/utility/prioritized_mutex.hpp \ include/bitcoin/system/utility/property_tree.hpp \ include/bitcoin/system/utility/pseudo_random.hpp \ - include/bitcoin/system/utility/qr_code.hpp \ include/bitcoin/system/utility/reader.hpp \ include/bitcoin/system/utility/resubscriber.hpp \ include/bitcoin/system/utility/scope_lock.hpp \ @@ -691,6 +709,7 @@ include_bitcoin_system_wallet_HEADERS = \ include/bitcoin/system/wallet/mini_keys.hpp \ include/bitcoin/system/wallet/mnemonic.hpp \ include/bitcoin/system/wallet/payment_address.hpp \ + include/bitcoin/system/wallet/qr_code.hpp \ include/bitcoin/system/wallet/select_outputs.hpp \ include/bitcoin/system/wallet/stealth_address.hpp \ include/bitcoin/system/wallet/stealth_receiver.hpp \ diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index a88a1f7566..ce96f31872 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -474,7 +474,6 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/utility/prioritized_mutex.cpp" "../../src/utility/property_tree.cpp" "../../src/utility/pseudo_random.cpp" - "../../src/utility/qr_code.cpp" "../../src/utility/scope_lock.cpp" "../../src/utility/sequencer.cpp" "../../src/utility/sequential_lock.cpp" @@ -512,6 +511,7 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/wallet/mini_keys.cpp" "../../src/wallet/mnemonic.cpp" "../../src/wallet/payment_address.cpp" + "../../src/wallet/qr_code.cpp" "../../src/wallet/select_outputs.cpp" "../../src/wallet/stealth_address.cpp" "../../src/wallet/stealth_receiver.cpp" @@ -527,7 +527,26 @@ add_library( ${CANONICAL_LIB_NAME} "../../src/wallet/parse_encrypted_keys/parse_encrypted_public.cpp" "../../src/wallet/parse_encrypted_keys/parse_encrypted_public.hpp" "../../src/wallet/parse_encrypted_keys/parse_encrypted_token.cpp" - "../../src/wallet/parse_encrypted_keys/parse_encrypted_token.hpp" ) + "../../src/wallet/parse_encrypted_keys/parse_encrypted_token.hpp" + "../../src/wallet/qrencode/bitstream.c" + "../../src/wallet/qrencode/bitstream.h" + "../../src/wallet/qrencode/mask.c" + "../../src/wallet/qrencode/mask.h" + "../../src/wallet/qrencode/mmask.c" + "../../src/wallet/qrencode/mmask.h" + "../../src/wallet/qrencode/mqrspec.c" + "../../src/wallet/qrencode/mqrspec.h" + "../../src/wallet/qrencode/qrencode.c" + "../../src/wallet/qrencode/qrencode.h" + "../../src/wallet/qrencode/qrencode_inner.h" + "../../src/wallet/qrencode/qrinput.c" + "../../src/wallet/qrencode/qrinput.h" + "../../src/wallet/qrencode/qrspec.c" + "../../src/wallet/qrencode/qrspec.h" + "../../src/wallet/qrencode/rsecc.c" + "../../src/wallet/qrencode/rsecc.h" + "../../src/wallet/qrencode/split.c" + "../../src/wallet/qrencode/split.h" ) # ${CANONICAL_LIB_NAME} project specific include directories. #------------------------------------------------------------------------------ @@ -725,7 +744,6 @@ if (with-tests) "../../test/utility/neutrino_filter.cpp" "../../test/utility/property_tree.cpp" "../../test/utility/pseudo_random.cpp" - "../../test/utility/qr_code.cpp" "../../test/utility/serializer.cpp" "../../test/utility/stream.cpp" "../../test/utility/thread.cpp" @@ -741,6 +759,7 @@ if (with-tests) "../../test/wallet/mnemonic.cpp" "../../test/wallet/mnemonic.hpp" "../../test/wallet/payment_address.cpp" + "../../test/wallet/qr_code.cpp" "../../test/wallet/select_outputs.cpp" "../../test/wallet/stealth_address.cpp" "../../test/wallet/stealth_receiver.cpp" diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj index 5c6657ff30..a59f1c6807 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -186,7 +186,6 @@ - @@ -201,6 +200,7 @@ + diff --git a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters index 3434820b08..fc5e9cd7b9 100644 --- a/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters +++ b/builds/msvc/vs2013/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters @@ -333,9 +333,6 @@ src\utility - - src\utility - src\utility @@ -378,6 +375,9 @@ src\wallet + + src\wallet + src\wallet diff --git a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj index cb574fdf8b..bcf3887218 100644 --- a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj @@ -256,7 +256,6 @@ - @@ -297,6 +296,16 @@ + + + + + + + + + + @@ -478,7 +487,6 @@ - @@ -513,6 +521,7 @@ + @@ -538,6 +547,16 @@ + + + + + + + + + + diff --git a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters index 3061c7433c..ef9b5aae7d 100644 --- a/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters +++ b/builds/msvc/vs2013/libbitcoin-system/libbitcoin-system.vcxproj.filters @@ -8,76 +8,76 @@ - {39F60708-FF48-4C22-0000-00000000000D} + {39F60708-FF48-4C22-0000-00000000000E} - {39F60708-FF48-4C22-0000-00000000000E} + {39F60708-FF48-4C22-0000-00000000000F} - {39F60708-FF48-4C22-0000-00000000000F} + {39F60708-FF48-4C22-0000-000000000001} - {39F60708-FF48-4C22-0000-000000000001} + {39F60708-FF48-4C22-0000-000000000002} - {39F60708-FF48-4C22-0000-000000000002} + {39F60708-FF48-4C22-0000-000000000003} - {39F60708-FF48-4C22-0000-000000000003} + {39F60708-FF48-4C22-0000-000000000004} - {39F60708-FF48-4C22-0000-000000000004} + {39F60708-FF48-4C22-0000-000000000005} - {39F60708-FF48-4C22-0000-0000000000B1} + {39F60708-FF48-4C22-0000-0000000000C1} - {39F60708-FF48-4C22-0000-0000000000C1} + {39F60708-FF48-4C22-0000-0000000000D1} - {39F60708-FF48-4C22-0000-000000000002} + {39F60708-FF48-4C22-0000-000000000003} - {39F60708-FF48-4C22-0000-0000000000D1} + {39F60708-FF48-4C22-0000-0000000000E1} - {39F60708-FF48-4C22-0000-0000000000E1} + {39F60708-FF48-4C22-0000-0000000000F1} - {39F60708-FF48-4C22-0000-0000000000F1} + {39F60708-FF48-4C22-0000-000000000002} - {39F60708-FF48-4C22-0000-000000000005} + {39F60708-FF48-4C22-0000-000000000006} - {39F60708-FF48-4C22-0000-000000000003} + {39F60708-FF48-4C22-0000-000000000004} - {39F60708-FF48-4C22-0000-000000000006} + {39F60708-FF48-4C22-0000-000000000007} - {39F60708-FF48-4C22-0000-000000000007} + {39F60708-FF48-4C22-0000-000000000008} - {39F60708-FF48-4C22-0000-000000000008} + {39F60708-FF48-4C22-0000-000000000009} - {39F60708-FF48-4C22-0000-000000000009} + {39F60708-FF48-4C22-0000-000000000010} - {39F60708-FF48-4C22-0000-000000000010} + {39F60708-FF48-4C22-0000-0000000000A1} - {39F60708-FF48-4C22-0000-0000000000A1} + {39F60708-FF48-4C22-0000-0000000000B1} - {39F60708-FF48-4C22-0000-000000000004} + {39F60708-FF48-4C22-0000-000000000005} {39F60708-FF48-4C22-0000-000000000000} - {39F60708-FF48-4C22-0000-000000000005} + {39F60708-FF48-4C22-0000-000000000006} {39F60708-FF48-4C22-0000-000000000001} @@ -115,6 +115,9 @@ {39F60708-FF48-4C22-0000-00000000000C} + + {39F60708-FF48-4C22-0000-00000000000D} + @@ -546,9 +549,6 @@ src\utility - - src\utility - src\utility @@ -669,6 +669,36 @@ src\wallet + + src\wallet + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + src\wallet @@ -1208,9 +1238,6 @@ include\bitcoin\system\utility - - include\bitcoin\system\utility - include\bitcoin\system\utility @@ -1313,6 +1340,9 @@ include\bitcoin\system\wallet + + include\bitcoin\system\wallet + include\bitcoin\system\wallet @@ -1388,6 +1418,36 @@ src\wallet\parse_encrypted_keys + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + resource diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj index a45e62681a..35f38ddeec 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -186,7 +186,6 @@ - @@ -201,6 +200,7 @@ + diff --git a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters index 3434820b08..fc5e9cd7b9 100644 --- a/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters +++ b/builds/msvc/vs2015/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters @@ -333,9 +333,6 @@ src\utility - - src\utility - src\utility @@ -378,6 +375,9 @@ src\wallet + + src\wallet + src\wallet diff --git a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj index 1a9320526c..fad75ab737 100644 --- a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj @@ -253,7 +253,6 @@ - @@ -294,6 +293,16 @@ + + + + + + + + + + @@ -475,7 +484,6 @@ - @@ -510,6 +518,7 @@ + @@ -535,6 +544,16 @@ + + + + + + + + + + diff --git a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters index 2dcad40d6b..345e86fc8b 100644 --- a/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters +++ b/builds/msvc/vs2015/libbitcoin-system/libbitcoin-system.vcxproj.filters @@ -8,70 +8,70 @@ - {39F60708-FF48-4C22-0000-00000000000D} + {39F60708-FF48-4C22-0000-00000000000E} - {39F60708-FF48-4C22-0000-00000000000E} + {39F60708-FF48-4C22-0000-00000000000F} - {39F60708-FF48-4C22-0000-00000000000F} + {39F60708-FF48-4C22-0000-000000000001} - {39F60708-FF48-4C22-0000-000000000001} + {39F60708-FF48-4C22-0000-000000000002} - {39F60708-FF48-4C22-0000-000000000002} + {39F60708-FF48-4C22-0000-000000000003} - {39F60708-FF48-4C22-0000-000000000003} + {39F60708-FF48-4C22-0000-000000000004} - {39F60708-FF48-4C22-0000-000000000004} + {39F60708-FF48-4C22-0000-000000000005} - {39F60708-FF48-4C22-0000-0000000000B1} + {39F60708-FF48-4C22-0000-0000000000C1} - {39F60708-FF48-4C22-0000-0000000000C1} + {39F60708-FF48-4C22-0000-0000000000D1} - {39F60708-FF48-4C22-0000-000000000002} + {39F60708-FF48-4C22-0000-000000000003} - {39F60708-FF48-4C22-0000-0000000000D1} + {39F60708-FF48-4C22-0000-0000000000E1} - {39F60708-FF48-4C22-0000-0000000000E1} + {39F60708-FF48-4C22-0000-0000000000F1} - {39F60708-FF48-4C22-0000-0000000000F1} + {39F60708-FF48-4C22-0000-000000000002} - {39F60708-FF48-4C22-0000-000000000005} + {39F60708-FF48-4C22-0000-000000000006} - {39F60708-FF48-4C22-0000-000000000003} + {39F60708-FF48-4C22-0000-000000000004} - {39F60708-FF48-4C22-0000-000000000006} + {39F60708-FF48-4C22-0000-000000000007} - {39F60708-FF48-4C22-0000-000000000007} + {39F60708-FF48-4C22-0000-000000000008} - {39F60708-FF48-4C22-0000-000000000008} + {39F60708-FF48-4C22-0000-000000000009} - {39F60708-FF48-4C22-0000-000000000009} + {39F60708-FF48-4C22-0000-000000000010} - {39F60708-FF48-4C22-0000-000000000010} + {39F60708-FF48-4C22-0000-0000000000A1} - {39F60708-FF48-4C22-0000-0000000000A1} + {39F60708-FF48-4C22-0000-0000000000B1} - {39F60708-FF48-4C22-0000-000000000004} + {39F60708-FF48-4C22-0000-000000000005} {39F60708-FF48-4C22-0000-000000000000} @@ -112,6 +112,9 @@ {39F60708-FF48-4C22-0000-00000000000C} + + {39F60708-FF48-4C22-0000-00000000000D} + @@ -540,9 +543,6 @@ src\utility - - src\utility - src\utility @@ -663,6 +663,36 @@ src\wallet + + src\wallet + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + src\wallet @@ -1202,9 +1232,6 @@ include\bitcoin\system\utility - - include\bitcoin\system\utility - include\bitcoin\system\utility @@ -1307,6 +1334,9 @@ include\bitcoin\system\wallet + + include\bitcoin\system\wallet + include\bitcoin\system\wallet @@ -1382,6 +1412,36 @@ src\wallet\parse_encrypted_keys + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + resource diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj index a7a87a0766..3047683a60 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj @@ -186,7 +186,6 @@ - @@ -201,6 +200,7 @@ + diff --git a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters index 3434820b08..fc5e9cd7b9 100644 --- a/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters +++ b/builds/msvc/vs2017/libbitcoin-system-test/libbitcoin-system-test.vcxproj.filters @@ -333,9 +333,6 @@ src\utility - - src\utility - src\utility @@ -378,6 +375,9 @@ src\wallet + + src\wallet + src\wallet diff --git a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj index 71c176f3c1..abeeb9d824 100644 --- a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj +++ b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj @@ -253,7 +253,6 @@ - @@ -294,6 +293,16 @@ + + + + + + + + + + @@ -475,7 +484,6 @@ - @@ -510,6 +518,7 @@ + @@ -535,6 +544,16 @@ + + + + + + + + + + diff --git a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters index 3b470c2b6d..41c7091f69 100644 --- a/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters +++ b/builds/msvc/vs2017/libbitcoin-system/libbitcoin-system.vcxproj.filters @@ -8,70 +8,70 @@ - {39F60708-FF48-4C22-0000-00000000000D} + {39F60708-FF48-4C22-0000-00000000000E} - {39F60708-FF48-4C22-0000-00000000000E} + {39F60708-FF48-4C22-0000-00000000000F} - {39F60708-FF48-4C22-0000-00000000000F} + {39F60708-FF48-4C22-0000-000000000001} - {39F60708-FF48-4C22-0000-000000000001} + {39F60708-FF48-4C22-0000-000000000002} - {39F60708-FF48-4C22-0000-000000000002} + {39F60708-FF48-4C22-0000-000000000003} - {39F60708-FF48-4C22-0000-000000000003} + {39F60708-FF48-4C22-0000-000000000004} - {39F60708-FF48-4C22-0000-000000000004} + {39F60708-FF48-4C22-0000-000000000005} - {39F60708-FF48-4C22-0000-0000000000B1} + {39F60708-FF48-4C22-0000-0000000000C1} - {39F60708-FF48-4C22-0000-0000000000C1} + {39F60708-FF48-4C22-0000-0000000000D1} - {39F60708-FF48-4C22-0000-000000000002} + {39F60708-FF48-4C22-0000-000000000003} - {39F60708-FF48-4C22-0000-0000000000D1} + {39F60708-FF48-4C22-0000-0000000000E1} - {39F60708-FF48-4C22-0000-0000000000E1} + {39F60708-FF48-4C22-0000-0000000000F1} - {39F60708-FF48-4C22-0000-0000000000F1} + {39F60708-FF48-4C22-0000-000000000002} - {39F60708-FF48-4C22-0000-000000000005} + {39F60708-FF48-4C22-0000-000000000006} - {39F60708-FF48-4C22-0000-000000000003} + {39F60708-FF48-4C22-0000-000000000004} - {39F60708-FF48-4C22-0000-000000000006} + {39F60708-FF48-4C22-0000-000000000007} - {39F60708-FF48-4C22-0000-000000000007} + {39F60708-FF48-4C22-0000-000000000008} - {39F60708-FF48-4C22-0000-000000000008} + {39F60708-FF48-4C22-0000-000000000009} - {39F60708-FF48-4C22-0000-000000000009} + {39F60708-FF48-4C22-0000-000000000010} - {39F60708-FF48-4C22-0000-000000000010} + {39F60708-FF48-4C22-0000-0000000000A1} - {39F60708-FF48-4C22-0000-0000000000A1} + {39F60708-FF48-4C22-0000-0000000000B1} - {39F60708-FF48-4C22-0000-000000000004} + {39F60708-FF48-4C22-0000-000000000005} {39F60708-FF48-4C22-0000-000000000000} @@ -112,6 +112,9 @@ {39F60708-FF48-4C22-0000-00000000000C} + + {39F60708-FF48-4C22-0000-00000000000D} + @@ -540,9 +543,6 @@ src\utility - - src\utility - src\utility @@ -663,6 +663,36 @@ src\wallet + + src\wallet + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + src\wallet @@ -1202,9 +1232,6 @@ include\bitcoin\system\utility - - include\bitcoin\system\utility - include\bitcoin\system\utility @@ -1307,6 +1334,9 @@ include\bitcoin\system\wallet + + include\bitcoin\system\wallet + include\bitcoin\system\wallet @@ -1382,6 +1412,36 @@ src\wallet\parse_encrypted_keys + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + + + src\wallet\qrencode + resource diff --git a/include/bitcoin/system.hpp b/include/bitcoin/system.hpp index 8991cc957c..f248193e13 100755 --- a/include/bitcoin/system.hpp +++ b/include/bitcoin/system.hpp @@ -187,7 +187,6 @@ #include #include #include -#include #include #include #include @@ -221,6 +220,7 @@ #include #include #include +#include #include #include #include diff --git a/include/bitcoin/system/utility/qr_code.hpp b/include/bitcoin/system/wallet/qr_code.hpp similarity index 69% rename from include/bitcoin/system/utility/qr_code.hpp rename to include/bitcoin/system/wallet/qr_code.hpp index df90f3f1d1..71afd06906 100644 --- a/include/bitcoin/system/utility/qr_code.hpp +++ b/include/bitcoin/system/wallet/qr_code.hpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * Copyright (c) 2011-2021 libbitcoin developers (see AUTHORS) * * This file is part of libbitcoin. * @@ -16,16 +16,18 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#ifndef LIBBITCOIN_SYSTEM_QR_CODE_HPP -#define LIBBITCOIN_SYSTEM_QR_CODE_HPP +#ifndef LIBBITCOIN_SYSTEM_QRENCODE_HPP +#define LIBBITCOIN_SYSTEM_QRENCODE_HPP #include #include +#include #include #include namespace libbitcoin { namespace system { +namespace wallet { class BC_API qr_code { @@ -50,17 +52,21 @@ class BC_API qr_code highest }; - /// Create a TIFF qrcode representing the given string value. + static uint8_t maximum_version; + + /// Create a TIFF formatter QR code representing the given string value. static bool encode(std::ostream& out, const std::string& value, - uint32_t version=0, uint16_t scale=8, uint16_t margin=2, - bool case_sensitive=true, recovery_level level=recovery_level::low, + uint8_t version=0, uint16_t scale=8, uint16_t margin=2, + recovery_level level=recovery_level::low, encode_mode mode=encode_mode::eight_bit); - /// Convert qr encoded data stream to bit stream with margin and scaling. - static data_chunk to_image_data(const data_chunk& coded, uint16_t scale=8, - uint16_t margin=2); +protected: + /// Convert QR encoded data stream to bit stream with margin and scaling. + static data_chunk to_pixels(const data_chunk& coded, uint32_t coded_width, + uint16_t scale=8, uint16_t margin=2); }; +} // namespace wallet } // namespace system } // namespace libbitcoin diff --git a/src/utility/qr_code.cpp b/src/wallet/qr_code.cpp similarity index 60% rename from src/utility/qr_code.cpp rename to src/wallet/qr_code.cpp index 63d5c208f2..a961b0e50e 100644 --- a/src/utility/qr_code.cpp +++ b/src/wallet/qr_code.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * Copyright (c) 2011-2021 libbitcoin developers (see AUTHORS) * * This file is part of libbitcoin. * @@ -16,15 +16,11 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -#include +#include #include #include -#include #include -#ifdef WITH_QRENCODE - #include -#endif #include #include #include @@ -35,12 +31,14 @@ #include #include #include +#include +#include "qrencode/qrencode.h" namespace libbitcoin { namespace system { +namespace wallet { -#ifdef WITH_QRENCODE - +// External (embedded) qrencode library types. static QRecLevel recovery_level_to_qr_recovery_level( qr_code::recovery_level level) { @@ -57,6 +55,7 @@ static QRecLevel recovery_level_to_qr_recovery_level( } } +// External (embedded) qrencode library types. static QRencodeMode encode_mode_to_qr_encode_mode(qr_code::encode_mode mode) { switch (mode) @@ -80,89 +79,89 @@ static QRencodeMode encode_mode_to_qr_encode_mode(qr_code::encode_mode mode) } } +// The maximum version is 40. +uint8_t qr_code::maximum_version = QRSPEC_VERSION_MAX; + +// Free qrcode->data allocated memory and return specified result. +static bool free_and_return(QRcode* qrcode, bool result) +{ + // External (embedded) qrencode library function. + QRcode_free(qrcode); + return result; +} + bool qr_code::encode(std::ostream& out, const std::string& value, - uint32_t version, uint16_t scale, uint16_t margin, bool case_sensitive, - recovery_level level, encode_mode mode) + uint8_t version, uint16_t scale, uint16_t margin, recovery_level level, + encode_mode mode) { - const auto qrcode = QRcode_encodeString(value.c_str(), version, - recovery_level_to_qr_recovery_level(level), - encode_mode_to_qr_encode_mode(mode), case_sensitive); + // Bitcoin URLs are always case sensitive. + static const int case_sensitive = 1; - if (qrcode == nullptr) + // Guard integer conversion, encode would return null pointer. + if (version > maximum_version) return false; - // Any scale increase can potentially cause an overflow. - const auto scaled_width = scale * static_cast(qrcode->width); + // Make otherwise safe sign cast explicit. + const auto signed_version = static_cast(version); + + // External (embedded) qrencode library function. + const auto qrcode = QRcode_encodeString(value.c_str(), signed_version, + recovery_level_to_qr_recovery_level(level), + encode_mode_to_qr_encode_mode(mode), case_sensitive); - // Guard against scaling overflow. - if (scaled_width > max_uint16) + // Empty or excessive value returns null pointer. + if (qrcode == nullptr) return false; - // Limit of bc::tiff conversion maximum size. - const auto width = static_cast(scaled_width); + // Bound: 2^1 * 2^16 + 2^32 < 2^64. + const auto pixel_width = uint64_t{ 2u } * margin + scale * qrcode->width; - // Width is limited to max_uint32, safe in 64 bit space. - const auto area = qrcode->width * static_cast(qrcode->width); + // Guard against TIFF overflow. + if (pixel_width > max_uint16) + return free_and_return(qrcode, false); - // Guard against overflow (to_image_data verifies logical size). - if (area > std::numeric_limits::max()) - return false; + // Bound: (2^32 - 1)^2 < (2^64 - 1). + const auto data_area = qrcode->width * static_cast(qrcode->width); - // Map coded data into a data_chunk (must rely on width correctness). - const data_chunk coded(&qrcode->data[0], &qrcode->data[area - 1u]); + // Guard against data_chunk overflow (it may not be possible to hit this). + if (data_area > max_size_t) + return free_and_return(qrcode, false); - // Convert to scaled image pixel bit stream. - const auto pixels = to_image_data(coded, scale, margin); + data_chunk data; - // Convert to TIFF image stream (does not fail as long as sizes match). - return tiff::to_image(out, pixels, width); -} + // Copy coded data into a data_chunk (it may not be possible to get zero). + if (data_area > 0u) + data.assign(qrcode->data, qrcode->data + data_area); -#else + // Convert to scaled and margined image pixel bit stream. + const auto pixels = to_pixels(data, qrcode->width, scale, margin); -bool qr_code::encode(std::ostream&, const std::string&, uint32_t, uint16_t, - uint16_t, bool, recovery_level, encode_mode) -{ - return false; + // Convert to TIFF image stream. + return free_and_return(qrcode, tiff::to_image(out, pixels, + static_cast(pixel_width))); } -#endif - // Scale may move the image off of a byte-aligned square of pixels in bytes. // So the dimensions cannot be derived from the result, caller must retain. -// pixel_width = width * scale. -data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, - uint16_t margin) +// pixel_width = 2 * margin + scale * coded_width. +// The result may be up to max_size_t, which exceeds the TIFF limit of 2^32 +// when size_t is 2^64. Caller can optimize a failure by guarding pixel_width. +data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t coded_width, + uint16_t scale, uint16_t margin) { - // For reading the qrcode byte stream. - data_source image_source(coded); - istream_reader image_reader(image_source); - - // Skip over the serialized qrencode version (may not match requested). - image_reader.skip(sizeof(uint32_t)); - - // Read the serialized qrencode width (encoding is one pixel per byte). - const auto width = image_reader.read_4_bytes_little_endian(); - - // Guard against insufficient stream length (invalid width). - if (!image_reader) - return {}; - - // Bounds: (2^32 - 1)^2 < (2^64 - 1). + // Bound: (2^32 - 1)^2 < (2^64 - 1). // Guard against mismatched sizes from qrencode. - if (coded.size() - sizeof(uint32_t) - sizeof(uint32_t) != width * - static_cast(width)) + if (coded.size() != coded_width * static_cast(coded_width)) return {}; - // Bounds: 2^16 * 2^32 < 2^48 < 2^64. - const auto scaled_width = scale * static_cast(width); + // Bound: 2^16 * 2^32 < 2^48 < 2^64. + const auto scaled_width = scale * static_cast(coded_width); - // Bounds: 2^48 + 2 * 2^16 < 2^48 + 2^17 < 2 * 2^48 < 2^64. - const auto full_width = margin + scaled_width + margin; + // Bound: 2^48 + 2 * 2^16 < 2^48 + 2^17 < 2 * 2^48 < 2^64. + const auto pixel_width = margin + scaled_width + margin; - // TODO: test. // Guard against index overflows (all below limited to size_t). - if (full_width > 0u && max_size_t / full_width < full_width) + if (pixel_width > 0u && max_size_t / pixel_width < pixel_width) return {}; // Pixel is the least significant bit of a qrencode byte. @@ -170,9 +169,11 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, constexpr auto pixel_off = false; // For readability (image is always square). - const auto height = width; - const auto vertical_margin = margin; - const auto horizontal_margin = margin; + const auto coded_height = coded_width; + + // For reading the qrcode byte stream. + data_source image_source(coded); + istream_reader image_reader(image_source); // For writing the image bit stream. data_chunk image_out; @@ -181,12 +182,12 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, ostream_bit_writer image_bit_writer(image_writer); // Write top margin. - for (size_t row = 0; row < vertical_margin; ++row) - for (size_t column = 0; column < full_width; ++column) + for (size_t row = 0; row < margin; ++row) + for (size_t column = 0; column < pixel_width; ++column) image_bit_writer.write_bit(pixel_off); // Write each row. - for (size_t row = 0; row < height; ++row) + for (size_t row = 0; row < coded_height; ++row) { // For repeatedly writing a row buffer. data_chunk row_out; @@ -195,11 +196,11 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, ostream_bit_writer row_bit_writer(row_writer); // Buffer left margin. - for (size_t column = 0; column < horizontal_margin; ++column) + for (size_t column = 0; column < margin; ++column) row_bit_writer.write_bit(pixel_off); // Buffer scaled row pixels. - for (size_t column = 0; column < width; ++column) + for (size_t column = 0; column < coded_width; ++column) { // Read byte and extract pixel (least significant) bit. const auto pixel_on = (image_reader.read_byte() & pixel_mask) != 0; @@ -210,7 +211,7 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, } // Buffer right margin. - for (size_t column = 0; column < horizontal_margin; ++column) + for (size_t column = 0; column < margin; ++column) row_bit_writer.write_bit(pixel_off); // Flush any partial byte and then flush bytes to data_chunk. @@ -226,14 +227,14 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, istream_bit_reader row_bit_reader(row_reader); // Copy each bit in the row buffer to the output buffer. - for (size_t column = 0; column < full_width; ++column) + for (size_t column = 0; column < pixel_width; ++column) image_bit_writer.write_bit(row_bit_reader.read_bit()); } } // Write bottom margin. - for (size_t row = 0; row < vertical_margin; ++row) - for (size_t column = 0; column < full_width; ++column) + for (size_t row = 0; row < margin; ++row) + for (size_t column = 0; column < pixel_width; ++column) image_bit_writer.write_bit(pixel_off); // Guard against writer failure and unexpected stream length. @@ -247,5 +248,6 @@ data_chunk qr_code::to_image_data(const data_chunk& coded, uint16_t scale, return image_out; } +} // namespace wallet } // namespace system } // namespace libbitcoin diff --git a/src/wallet/qrencode/bitstream.c b/src/wallet/qrencode/bitstream.c new file mode 100644 index 0000000000..f620050dc6 --- /dev/null +++ b/src/wallet/qrencode/bitstream.c @@ -0,0 +1,231 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include + +#include "bitstream.h" + +#define DEFAULT_BUFSIZE (128) + +BitStream *BitStream_new(void) +{ + BitStream *bstream; + + bstream = (BitStream *)malloc(sizeof(BitStream)); + if(bstream == NULL) return NULL; + + bstream->length = 0; + bstream->data = (unsigned char *)malloc(DEFAULT_BUFSIZE); + if(bstream->data == NULL) { + free(bstream); + return NULL; + } + bstream->datasize = DEFAULT_BUFSIZE; + + return bstream; +} + +#ifdef WITH_TESTS +BitStream *BitStream_newWithBits(size_t size, unsigned char *bits) +{ + BitStream *bstream; + + if(size == 0) return BitStream_new(); + + bstream = (BitStream *)malloc(sizeof(BitStream)); + if(bstream == NULL) return NULL; + + bstream->data = (unsigned char *)malloc(size); + if(bstream->data == NULL) { + free(bstream); + return NULL; + } + + bstream->length = size; + bstream->datasize = size; + memcpy(bstream->data, bits, size); + + return bstream; +} +#endif + +static int BitStream_expand(BitStream *bstream) +{ + unsigned char *data; + + data = (unsigned char *)realloc(bstream->data, bstream->datasize * 2); + if(data == NULL) { + return -1; + } + + bstream->data = data; + bstream->datasize *= 2; + + return 0; +} + +static void BitStream_writeNum(unsigned char *dest, size_t bits, unsigned int num) +{ + unsigned int mask; + size_t i; + unsigned char *p; + + p = dest; + mask = 1U << (bits - 1); + for(i = 0; i < bits; i++) { + if(num & mask) { + *p = 1; + } else { + *p = 0; + } + p++; + mask = mask >> 1; + } +} + +static void BitStream_writeBytes(unsigned char *dest, size_t size, unsigned char *data) +{ + unsigned char mask; + size_t i, j; + unsigned char *p; + + p = dest; + for(i = 0; i < size; i++) { + mask = 0x80; + for(j = 0; j < 8; j++) { + if(data[i] & mask) { + *p = 1; + } else { + *p = 0; + } + p++; + mask = mask >> 1; + } + } +} + +int BitStream_append(BitStream *bstream, BitStream *arg) +{ + int ret; + + if(arg == NULL) { + return -1; + } + if(arg->length == 0) { + return 0; + } + + while(bstream->length + arg->length > bstream->datasize) { + ret = BitStream_expand(bstream); + if(ret < 0) return ret; + } + + memcpy(bstream->data + bstream->length, arg->data, arg->length); + bstream->length += arg->length; + + return 0; +} + +int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num) +{ + int ret; + + if(bits == 0) return 0; + + while(bstream->datasize - bstream->length < bits) { + ret = BitStream_expand(bstream); + if(ret < 0) return ret; + } + BitStream_writeNum(bstream->data + bstream->length, bits, num); + bstream->length += bits; + + return 0; +} + +int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data) +{ + int ret; + + if(size == 0) return 0; + + while(bstream->datasize - bstream->length < size * 8) { + ret = BitStream_expand(bstream); + if(ret < 0) return ret; + } + BitStream_writeBytes(bstream->data + bstream->length, size, data); + bstream->length += size * 8; + + return 0; +} + +unsigned char *BitStream_toByte(BitStream *bstream) +{ + size_t i, j, size, bytes, oddbits; + unsigned char *data, v; + unsigned char *p; + + size = BitStream_size(bstream); + if(size == 0) { + return NULL; + } + data = (unsigned char *)malloc((size + 7) / 8); + if(data == NULL) { + return NULL; + } + + bytes = size / 8; + + p = bstream->data; + for(i = 0; i < bytes; i++) { + v = 0; + for(j = 0; j < 8; j++) { + v = (unsigned char)(v << 1); + v |= *p; + p++; + } + data[i] = v; + } + oddbits = size & 7; + if(oddbits > 0) { + v = 0; + for(j = 0; j < oddbits; j++) { + v = (unsigned char)(v << 1); + v |= *p; + p++; + } + data[bytes] = (unsigned char)(v << (8 - oddbits)); + } + + return data; +} + +void BitStream_free(BitStream *bstream) +{ + if(bstream != NULL) { + free(bstream->data); + free(bstream); + } +} diff --git a/src/wallet/qrencode/bitstream.h b/src/wallet/qrencode/bitstream.h new file mode 100644 index 0000000000..70f3e1dfc5 --- /dev/null +++ b/src/wallet/qrencode/bitstream.h @@ -0,0 +1,43 @@ +/* + * qrencode - QR Code encoder + * + * Binary sequence class. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BITSTREAM_H +#define BITSTREAM_H + +typedef struct { + size_t length; + size_t datasize; + unsigned char *data; +} BitStream; + +extern BitStream *BitStream_new(void); +#ifdef WITH_TESTS +extern BitStream *BitStream_newWithBits(size_t size, unsigned char *bits); +#endif +extern int BitStream_append(BitStream *bstream, BitStream *arg); +extern int BitStream_appendNum(BitStream *bstream, size_t bits, unsigned int num); +extern int BitStream_appendBytes(BitStream *bstream, size_t size, unsigned char *data); +#define BitStream_size(__bstream__) (__bstream__->length) +#define BitStream_reset(__bstream__) (__bstream__->length = 0) +extern unsigned char *BitStream_toByte(BitStream *bstream); +extern void BitStream_free(BitStream *bstream); + +#endif /* BITSTREAM_H */ diff --git a/src/wallet/qrencode/mask.c b/src/wallet/qrencode/mask.c new file mode 100644 index 0000000000..4bf2371765 --- /dev/null +++ b/src/wallet/qrencode/mask.c @@ -0,0 +1,357 @@ +/* + * qrencode - QR Code encoder + * + * Masking. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mask.h" + +STATIC_IN_RELEASE int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned int format; + unsigned char v; + int i; + int blacks = 0; + + format = QRspec_getFormatInfo(mask, level); + + for(i = 0; i < 8; i++) { + if(format & 1) { + blacks += 2; + v = 0x85; + } else { + v = 0x84; + } + frame[width * 8 + width - 1 - i] = v; + if(i < 6) { + frame[width * i + 8] = v; + } else { + frame[width * (i + 1) + 8] = v; + } + format= format >> 1; + } + for(i = 0; i < 7; i++) { + if(format & 1) { + blacks += 2; + v = 0x85; + } else { + v = 0x84; + } + frame[width * (width - 7 + i) + 8] = v; + if(i == 0) { + frame[width * 8 + 7] = v; + } else { + frame[width * 8 + 6 - i] = v; + } + format= format >> 1; + } + + return blacks; +} + +/** + * Demerit coefficients. + * See Section 8.8.2, pp.45, JIS X0510:2004. + */ +#define N1 (3) +#define N2 (3) +#define N3 (40) +#define N4 (10) + +#define MASKMAKER(__exp__) \ + int x, y;\ + int b = 0;\ +\ + for(y = 0; y < width; y++) {\ + for(x = 0; x < width; x++) {\ + if(*s & 0x80) {\ + *d = *s;\ + } else {\ + *d = *s ^ ((__exp__) == 0);\ + }\ + b += (int)(*d & 1);\ + s++; d++;\ + }\ + }\ + return b; + +static int Mask_mask0(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((x+y)&1) +} + +static int Mask_mask1(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(y&1) +} + +static int Mask_mask2(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(x%3) +} + +static int Mask_mask3(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((x+y)%3) +} + +static int Mask_mask4(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(((y/2)+(x/3))&1) +} + +static int Mask_mask5(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(((x*y)&1)+(x*y)%3) +} + +static int Mask_mask6(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((((x*y)&1)+(x*y)%3)&1) +} + +static int Mask_mask7(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((((x*y)%3)+((x+y)&1))&1) +} + +#define maskNum (8) +typedef int MaskMaker(int, const unsigned char *, unsigned char *); +static MaskMaker *maskMakers[maskNum] = { + Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3, + Mask_mask4, Mask_mask5, Mask_mask6, Mask_mask7 +}; + +#ifdef WITH_TESTS +unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask) +{ + unsigned char *masked; + + masked = (unsigned char *)malloc((size_t)(width * width)); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + + return masked; +} +#endif + +unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned char *masked; + + if(mask < 0 || mask >= maskNum) { + errno = EINVAL; + return NULL; + } + + masked = (unsigned char *)malloc((size_t)(width * width)); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + Mask_writeFormatInformation(width, masked, mask, level); + + return masked; +} + + +//static int n1; +//static int n2; +//static int n3; +//static int n4; + +STATIC_IN_RELEASE int Mask_calcN1N3(int length, int *runLength) +{ + int i; + int demerit = 0; + int fact; + + for(i = 0; i < length; i++) { + if(runLength[i] >= 5) { + demerit += N1 + (runLength[i] - 5); + //n1 += N1 + (runLength[i] - 5); + } + if((i & 1)) { + if(i >= 3 && i < length-2 && (runLength[i] % 3) == 0) { + fact = runLength[i] / 3; + if(runLength[i-2] == fact && + runLength[i-1] == fact && + runLength[i+1] == fact && + runLength[i+2] == fact) { + if(i == 3 || runLength[i-3] >= 4 * fact) { + demerit += N3; + //n3 += N3; + } else if(i+4 >= length || runLength[i+3] >= 4 * fact) { + demerit += N3; + //n3 += N3; + } + } + } + } + } + + return demerit; +} + +STATIC_IN_RELEASE int Mask_calcN2(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + unsigned char b22, w22; + int demerit = 0; + + p = frame + width + 1; + for(y = 1; y < width; y++) { + for(x = 1; x < width; x++) { + b22 = p[0] & p[-1] & p[-width] & p [-width-1]; + w22 = p[0] | p[-1] | p[-width] | p [-width-1]; + if((b22 | (w22 ^ 1))&1) { + demerit += N2; + } + p++; + } + p++; + } + + return demerit; +} + +STATIC_IN_RELEASE int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength) +{ + int head; + int i; + unsigned char prev; + + if(frame[0] & 1) { + runLength[0] = -1; + head = 1; + } else { + head = 0; + } + runLength[head] = 1; + prev = frame[0]; + + for(i = 1; i < width; i++) { + if((frame[i] ^ prev) & 1) { + head++; + runLength[head] = 1; + prev = frame[i]; + } else { + runLength[head]++; + } + } + + return head + 1; +} + +STATIC_IN_RELEASE int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength) +{ + int head; + int i; + unsigned char prev; + + if(frame[0] & 1) { + runLength[0] = -1; + head = 1; + } else { + head = 0; + } + runLength[head] = 1; + prev = frame[0]; + + for(i = 1; i < width; i++) { + if((frame[i * width] ^ prev) & 1) { + head++; + runLength[head] = 1; + prev = frame[i * width]; + } else { + runLength[head]++; + } + } + + return head + 1; +} + +STATIC_IN_RELEASE int Mask_evaluateSymbol(int width, unsigned char *frame) +{ + int x, y; + int demerit = 0; + int runLength[QRSPEC_WIDTH_MAX + 1]; + int length; + + demerit += Mask_calcN2(width, frame); + + for(y = 0; y < width; y++) { + length = Mask_calcRunLengthH(width, frame + y * width, runLength); + demerit += Mask_calcN1N3(length, runLength); + } + + for(x = 0; x < width; x++) { + length = Mask_calcRunLengthV(width, frame + x, runLength); + demerit += Mask_calcN1N3(length, runLength); + } + + return demerit; +} + +unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level) +{ + int i; + unsigned char *mask, *bestMask; + int minDemerit = INT_MAX; + int blacks; + int bratio; + int demerit; + int w2 = width * width; + + mask = (unsigned char *)malloc((size_t)w2); + if(mask == NULL) return NULL; + bestMask = (unsigned char *)malloc((size_t)w2); + if(bestMask == NULL) { + free(mask); + return NULL; + } + + for(i = 0; i < maskNum; i++) { +// n1 = n2 = n3 = n4 = 0; + demerit = 0; + blacks = maskMakers[i](width, frame, mask); + blacks += Mask_writeFormatInformation(width, mask, i, level); + bratio = (200 * blacks + w2) / w2 / 2; /* (int)(100*blacks/w2+0.5) */ + demerit = (abs(bratio - 50) / 5) * N4; +// n4 = demerit; + demerit += Mask_evaluateSymbol(width, mask); +// printf("(%d,%d,%d,%d)=%d\n", n1, n2, n3 ,n4, demerit); + if(demerit < minDemerit) { + minDemerit = demerit; + memcpy(bestMask, mask, (size_t)w2); + } + } + free(mask); + return bestMask; +} diff --git a/src/wallet/qrencode/mask.h b/src/wallet/qrencode/mask.h new file mode 100644 index 0000000000..169e64b2bb --- /dev/null +++ b/src/wallet/qrencode/mask.h @@ -0,0 +1,38 @@ +/* + * qrencode - QR Code encoder + * + * Masking. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MASK_H +#define MASK_H + +extern unsigned char *Mask_makeMask(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_mask(int width, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int Mask_calcN2(int width, unsigned char *frame); +extern int Mask_calcN1N3(int length, int *runLength); +extern int Mask_calcRunLengthH(int width, unsigned char *frame, int *runLength); +extern int Mask_calcRunLengthV(int width, unsigned char *frame, int *runLength); +extern int Mask_evaluateSymbol(int width, unsigned char *frame); +extern int Mask_writeFormatInformation(int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *Mask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif + +#endif /* MASK_H */ diff --git a/src/wallet/qrencode/mmask.c b/src/wallet/qrencode/mmask.c new file mode 100644 index 0000000000..5f09a1e981 --- /dev/null +++ b/src/wallet/qrencode/mmask.c @@ -0,0 +1,177 @@ +/* + * qrencode - QR Code encoder + * + * Masking for Micro QR Code. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "mqrspec.h" +#include "mmask.h" + +STATIC_IN_RELEASE void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned int format; + unsigned char v; + int i; + + format = MQRspec_getFormatInfo(mask, version, level); + + for(i = 0; i < 8; i++) { + v = 0x84 | (format & 1); + frame[width * (i + 1) + 8] = v; + format = format >> 1; + } + for(i = 0; i < 7; i++) { + v = 0x84 | (format & 1); + frame[width * 8 + 7 - i] = v; + format = format >> 1; + } +} + +#define MASKMAKER(__exp__) \ + int x, y;\ +\ + for(y = 0; y < width; y++) {\ + for(x = 0; x < width; x++) {\ + if(*s & 0x80) {\ + *d = *s;\ + } else {\ + *d = *s ^ ((__exp__) == 0);\ + }\ + s++; d++;\ + }\ + } + +static void Mask_mask0(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(y&1) +} + +static void Mask_mask1(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER(((y/2)+(x/3))&1) +} + +static void Mask_mask2(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((((x*y)&1)+(x*y)%3)&1) +} + +static void Mask_mask3(int width, const unsigned char *s, unsigned char *d) +{ + MASKMAKER((((x+y)&1)+((x*y)%3))&1) +} + +#define maskNum (4) +typedef void MaskMaker(int, const unsigned char *, unsigned char *); +static MaskMaker *maskMakers[maskNum] = { + Mask_mask0, Mask_mask1, Mask_mask2, Mask_mask3 +}; + +#ifdef WITH_TESTS +unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask) +{ + unsigned char *masked; + + masked = (unsigned char *)malloc((size_t)(width * width)); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + + return masked; +} +#endif + +unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level) +{ + unsigned char *masked; + int width; + + if(mask < 0 || mask >= maskNum) { + errno = EINVAL; + return NULL; + } + + width = MQRspec_getWidth(version); + masked = (unsigned char *)malloc((size_t)(width * width)); + if(masked == NULL) return NULL; + + maskMakers[mask](width, frame, masked); + MMask_writeFormatInformation(version, width, masked, mask, level); + + return masked; +} + +STATIC_IN_RELEASE int MMask_evaluateSymbol(int width, unsigned char *frame) +{ + int x, y; + unsigned char *p; + int sum1 = 0, sum2 = 0; + + p = frame + width * (width - 1); + for(x = 1; x < width; x++) { + sum1 += (p[x] & 1); + } + + p = frame + width * 2 - 1; + for(y = 1; y < width; y++) { + sum2 += (*p & 1); + p += width; + } + + return (sum1 <= sum2)?(sum1 * 16 + sum2):(sum2 * 16 + sum1); +} + +unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level) +{ + int i; + unsigned char *mask, *bestMask; + int maxScore = 0; + int score; + int width; + + width = MQRspec_getWidth(version); + + mask = (unsigned char *)malloc((size_t)(width * width)); + if(mask == NULL) return NULL; + bestMask = NULL; + + for(i = 0; i < maskNum; i++) { + score = 0; + maskMakers[i](width, frame, mask); + MMask_writeFormatInformation(version, width, mask, i, level); + score = MMask_evaluateSymbol(width, mask); + if(score > maxScore) { + maxScore = score; + free(bestMask); + bestMask = mask; + mask = (unsigned char *)malloc((size_t)(width * width)); + if(mask == NULL) break; + } + } + free(mask); + return bestMask; +} diff --git a/src/wallet/qrencode/mmask.h b/src/wallet/qrencode/mmask.h new file mode 100644 index 0000000000..56a58cd2d7 --- /dev/null +++ b/src/wallet/qrencode/mmask.h @@ -0,0 +1,34 @@ +/* + * qrencode - QR Code encoder + * + * Masking for Micro QR Code. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MMASK_H +#define MMASK_H + +extern unsigned char *MMask_makeMask(int version, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_mask(int version, unsigned char *frame, QRecLevel level); + +#ifdef WITH_TESTS +extern int MMask_evaluateSymbol(int width, unsigned char *frame); +extern void MMask_writeFormatInformation(int version, int width, unsigned char *frame, int mask, QRecLevel level); +extern unsigned char *MMask_makeMaskedFrame(int width, unsigned char *frame, int mask); +#endif + +#endif /* MMASK_H */ diff --git a/src/wallet/qrencode/mqrspec.c b/src/wallet/qrencode/mqrspec.c new file mode 100644 index 0000000000..87205fe970 --- /dev/null +++ b/src/wallet/qrencode/mqrspec.c @@ -0,0 +1,232 @@ +/* + * qrencode - QR Code encoder + * + * Micro QR Code specification in convenient format. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "mqrspec.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; ///< Edge length of the symbol + int ec[4]; ///< Number of ECC code (bytes) +} MQRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.106) and Table 8 (pp.113) of Appendix 1, JIS X0510:2004. + */ +static const MQRspec_Capacity mqrspecCapacity[MQRSPEC_VERSION_MAX + 1] = { + { 0, {0, 0, 0, 0}}, + { 11, {2, 0, 0, 0}}, + { 13, {5, 6, 0, 0}}, + { 15, {6, 8, 0, 0}}, + { 17, {8, 10, 14, 0}} +}; + +int MQRspec_getDataLengthBit(int version, QRecLevel level) +{ + int w; + int ecc; + + w = mqrspecCapacity[version].width - 1; + ecc = mqrspecCapacity[version].ec[level]; + if(ecc == 0) return 0; + return w * w - 64 - ecc * 8; +} + +int MQRspec_getDataLength(int version, QRecLevel level) +{ + return (MQRspec_getDataLengthBit(version, level) + 4) / 8; +} + +int MQRspec_getECCLength(int version, QRecLevel level) +{ + return mqrspecCapacity[version].ec[level]; +} + +int MQRspec_getWidth(int version) +{ + return mqrspecCapacity[version].width; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * See Table 3 (pp.107) of Appendix 1, JIS X0510:2004. + */ +static const int lengthTableBits[4][4] = { + { 3, 4, 5, 6}, + { 0, 3, 4, 5}, + { 0, 0, 4, 5}, + { 0, 0, 3, 4} +}; + +int MQRspec_lengthIndicator(QRencodeMode mode, int version) +{ + return lengthTableBits[mode][version - 1]; +} + +int MQRspec_maximumWords(QRencodeMode mode, int version) +{ + int bits; + int words; + + bits = lengthTableBits[mode][version - 1]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_mqrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x4445, 0x55ae, 0x6793, 0x7678, 0x06de, 0x1735, 0x2508, 0x34e3}, + {0x4172, 0x5099, 0x62a4, 0x734f, 0x03e9, 0x1202, 0x203f, 0x31d4}, + {0x4e2b, 0x5fc0, 0x6dfd, 0x7c16, 0x0cb0, 0x1d5b, 0x2f66, 0x3e8d}, + {0x4b1c, 0x5af7, 0x68ca, 0x7921, 0x0987, 0x186c, 0x2a51, 0x3bba} +}; + +/* See Table 10 of Appendix 1. (pp.115) */ +static const int typeTable[MQRSPEC_VERSION_MAX + 1][3] = { + {-1, -1, -1}, + { 0, -1, -1}, + { 1, 2, -1}, + { 3, 4, -1}, + { 5, 6, 7} +}; + +unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level) +{ + int type; + + if(mask < 0 || mask > 3) return 0; + if(version <= 0 || version > MQRSPEC_VERSION_MAX) return 0; + if(level == QR_ECLEVEL_H) return 0; + type = typeTable[version][level]; + if(type < 0) return 0; + + return formatInfo[mask][type]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y = 0; y < 7; y++) { + for(x = 0; x < 7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + +static unsigned char *MQRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + + width = mqrspecCapacity[version].width; + frame = (unsigned char *)malloc((size_t)(width * width)); + if(frame == NULL) return NULL; + + memset(frame, 0, (size_t)(width * width)); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + /* Separator */ + p = frame; + for(y = 0; y < 7; y++) { + p[7] = 0xc0; + p += width; + } + memset(frame + width * 7, 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8 + 1, 0x84, 8); + p = frame + width + 8; + for(y = 0; y < 7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + 8; + q = frame + width * 8; + for(x = 1; x < width-7; x++) { + *p = 0x90 | (x & 1); + *q = 0x90 | (x & 1); + p++; + q += width; + } + + return frame; +} + +unsigned char *MQRspec_newFrame(int version) +{ + if(version < 1 || version > MQRSPEC_VERSION_MAX) return NULL; + + return MQRspec_createFrame(version); +} diff --git a/src/wallet/qrencode/mqrspec.h b/src/wallet/qrencode/mqrspec.h new file mode 100644 index 0000000000..0eaa4907f5 --- /dev/null +++ b/src/wallet/qrencode/mqrspec.h @@ -0,0 +1,150 @@ +/* + * qrencode - QR Code encoder + * + * Micro QR Code specification in convenient format. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef MQRSPEC_H +#define MQRSPEC_H + +#include "qrencode.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define MQRSPEC_WIDTH_MAX 17 + +/** + * Return maximum data code length (bits) for the version. + * @param version version of the symbol + * @param level error correction level + * @return maximum size (bits) + */ +extern int MQRspec_getDataLengthBit(int version, QRecLevel level); + +/** + * Return maximum data code length (bytes) for the version. + * @param version version of the symbol + * @param level error correction level + * @return maximum size (bytes) + */ +extern int MQRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version version of the symbol + * @param level error correction level + * @return ECC size (bytes) + */ +extern int MQRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level error correction level + * @return version number + */ +extern int MQRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version version of the symbol + * @return width + */ +extern int MQRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version version of the symbol + * @return number of remainder bits + */ +extern int MQRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of length indicator for the mode and version. + * @param mode encode mode + * @param version vesion of the symbol + * @return the size of the appropriate length indicator (bits). + */ +extern int MQRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode encode mode + * @param version vesion of the symbol + * @return the maximum length (bytes) + */ +extern int MQRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version vesion of the symbol + * @return BCH encoded version information pattern + */ +extern unsigned int MQRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask mask number + * @param version version of the symbol + * @param level error correction level + * @return BCH encoded format information pattern + */ +extern unsigned int MQRspec_getFormatInfo(int mask, int version, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * @param version version of the symbol + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *MQRspec_newFrame(int version); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 in Appendix 1 of JIS X0510:2004, pp.107. + */ +#define MQRSPEC_MODEID_NUM 0 +#define MQRSPEC_MODEID_AN 1 +#define MQRSPEC_MODEID_8 2 +#define MQRSPEC_MODEID_KANJI 3 + +#endif /* MQRSPEC_H */ diff --git a/src/wallet/qrencode/qrencode.c b/src/wallet/qrencode/qrencode.c new file mode 100644 index 0000000000..240a8ade7b --- /dev/null +++ b/src/wallet/qrencode/qrencode.c @@ -0,0 +1,940 @@ +/* + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" +#include "rsecc.h" +#include "split.h" +#include "mask.h" +#include "mmask.h" + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + int eccLength; + unsigned char *data; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +static void RSblock_initBlock(RSblock *block, int dl, unsigned char *data, int el, unsigned char *ecc) +{ + block->dataLength = dl; + block->data = data; + block->eccLength = el; + block->ecc = ecc; + + RSECC_encode((size_t)dl, (size_t)el, data, ecc); +} + +static int RSblock_init(RSblock *blocks, int spec[5], unsigned char *data, unsigned char *ecc) +{ + int i; + RSblock *block; + unsigned char *dp, *ep; + int el, dl; + + dl = QRspec_rsDataCodes1(spec); + el = QRspec_rsEccCodes1(spec); + + block = blocks; + dp = data; + ep = ecc; + for(i = 0; i < QRspec_rsBlockNum1(spec); i++) { + RSblock_initBlock(block, dl, dp, el, ep); + dp += dl; + ep += el; + block++; + } + + if(QRspec_rsBlockNum2(spec) == 0) return 0; + + dl = QRspec_rsDataCodes2(spec); + el = QRspec_rsEccCodes2(spec); + for(i = 0; i < QRspec_rsBlockNum2(spec); i++) { + RSblock_initBlock(block, dl, dp, el, ep); + dp += dl; + ep += el; + block++; + } + + return 0; +} + +STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw); +STATIC_IN_RELEASE QRRawCode *QRraw_new(QRinput *input) +{ + QRRawCode *raw; + int spec[5], ret; + + raw = (QRRawCode *)malloc(sizeof(QRRawCode)); + if(raw == NULL) return NULL; + + raw->datacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + + QRspec_getEccSpec(input->version, input->level, spec); + + raw->version = input->version; + raw->b1 = QRspec_rsBlockNum1(spec); + raw->dataLength = QRspec_rsDataLength(spec); + raw->eccLength = QRspec_rsEccLength(spec); + raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->blocks = QRspec_rsBlockNum(spec); + raw->rsblock = (RSblock *)calloc((size_t)(raw->blocks), sizeof(RSblock)); + if(raw->rsblock == NULL) { + QRraw_free(raw); + return NULL; + } + ret = RSblock_init(raw->rsblock, spec, raw->datacode, raw->ecccode); + if(ret < 0) { + QRraw_free(raw); + return NULL; + } + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +STATIC_IN_RELEASE unsigned char QRraw_getCode(QRRawCode *raw) +{ + int col, row; + unsigned char ret; + + if(raw->count < raw->dataLength) { + row = raw->count % raw->blocks; + col = raw->count / raw->blocks; + if(col >= raw->rsblock[0].dataLength) { + row += raw->b1; + } + ret = raw->rsblock[row].data[col]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + row = (raw->count - raw->dataLength) % raw->blocks; + col = (raw->count - raw->dataLength) / raw->blocks; + ret = raw->rsblock[row].ecc[col]; + } else { + return 0; + } + raw->count++; + return ret; +} + +STATIC_IN_RELEASE void QRraw_free(QRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + +/****************************************************************************** + * Raw code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw); +STATIC_IN_RELEASE MQRRawCode *MQRraw_new(QRinput *input) +{ + MQRRawCode *raw; + + raw = (MQRRawCode *)malloc(sizeof(MQRRawCode)); + if(raw == NULL) return NULL; + + raw->version = input->version; + raw->dataLength = MQRspec_getDataLength(input->version, input->level); + raw->eccLength = MQRspec_getECCLength(input->version, input->level); + raw->oddbits = raw->dataLength * 8 - MQRspec_getDataLengthBit(input->version, input->level); + raw->datacode = QRinput_getByteStream(input); + if(raw->datacode == NULL) { + free(raw); + return NULL; + } + raw->ecccode = (unsigned char *)malloc((size_t)raw->eccLength); + if(raw->ecccode == NULL) { + free(raw->datacode); + free(raw); + return NULL; + } + + raw->rsblock = (RSblock *)calloc(1, sizeof(RSblock)); + if(raw->rsblock == NULL) { + MQRraw_free(raw); + return NULL; + } + + RSblock_initBlock(raw->rsblock, raw->dataLength, raw->datacode, raw->eccLength, raw->ecccode); + + raw->count = 0; + + return raw; +} + +/** + * Return a code (byte). + * This function can be called iteratively. + * @param raw raw code. + * @return code + */ +STATIC_IN_RELEASE unsigned char MQRraw_getCode(MQRRawCode *raw) +{ + unsigned char ret; + + if(raw->count < raw->dataLength) { + ret = raw->datacode[raw->count]; + } else if(raw->count < raw->dataLength + raw->eccLength) { + ret = raw->ecccode[raw->count - raw->dataLength]; + } else { + return 0; + } + raw->count++; + return ret; +} + +STATIC_IN_RELEASE void MQRraw_free(MQRRawCode *raw) +{ + if(raw != NULL) { + free(raw->datacode); + free(raw->ecccode); + free(raw->rsblock); + free(raw); + } +} + + +/****************************************************************************** + * Frame filling + *****************************************************************************/ + +typedef struct { + int width; + unsigned char *frame; + int x, y; + int dir; + int bit; + int mqr; +} FrameFiller; + +static void FrameFiller_set(FrameFiller *filler, int width, unsigned char *frame, int mqr) +{ + filler->width = width; + filler->frame = frame; + filler->x = width - 1; + filler->y = width - 1; + filler->dir = -1; + filler->bit = -1; + filler->mqr = mqr; +} + +static unsigned char *FrameFiller_next(FrameFiller *filler) +{ + unsigned char *p; + int x, y, w; + + if(filler->bit == -1) { + filler->bit = 0; + return filler->frame + filler->y * filler->width + filler->x; + } + + x = filler->x; + y = filler->y; + p = filler->frame; + w = filler->width; + + if(filler->bit == 0) { + x--; + filler->bit++; + } else { + x++; + y += filler->dir; + filler->bit--; + } + + if(filler->dir < 0) { + if(y < 0) { + y = 0; + x -= 2; + filler->dir = 1; + if(!filler->mqr && x == 6) { + x--; + y = 9; + } + } + } else if(y == w) { + y = w - 1; + x -= 2; + filler->dir = -1; + if(!filler->mqr && x == 6) { + x--; + y -= 8; + } + } + if(x < 0 || y < 0) return NULL; + + filler->x = x; + filler->y = y; + + if(p[y * w + x] & 0x80) { + // This tail recursion could be optimized. + return FrameFiller_next(filler); + } + return &p[y * w + x]; +} + +#ifdef WITH_TESTS +unsigned char *FrameFiller_test(int version) +{ + int width; + unsigned char *frame, *p; + int i, length; + FrameFiller filler; + + width = QRspec_getWidth(version); + frame = QRspec_newFrame(version); + if(frame == NULL) return NULL; + FrameFiller_set(&filler, width, frame, 0); + length = QRspec_getDataLength(version, QR_ECLEVEL_L) * 8 + + QRspec_getECCLength(version, QR_ECLEVEL_L) * 8 + + QRspec_getRemainder(version); + for(i = 0; i < length; i++) { + p = FrameFiller_next(&filler); + if(p == NULL) { + free(frame); + return NULL; + } + *p = (unsigned char)(i & 0x7f) | 0x80; + } + return frame; +} + +unsigned char *FrameFiller_testMQR(int version) +{ + int width; + unsigned char *frame, *p; + int i, length; + FrameFiller filler; + + width = MQRspec_getWidth(version); + frame = MQRspec_newFrame(version); + if(frame == NULL) return NULL; + FrameFiller_set(&filler, width, frame, 1); + length = MQRspec_getDataLengthBit(version, QR_ECLEVEL_L) + + MQRspec_getECCLength(version, QR_ECLEVEL_L) * 8; + for(i = 0; i < length; i++) { + p = FrameFiller_next(&filler); + if(p == NULL) { + fprintf(stderr, "Frame filler run over the frame!\n"); + return frame; + } + *p = (unsigned char)(i & 0x7f) | 0x80; + } + return frame; +} +#endif + + +/****************************************************************************** + * QR-code encoding + *****************************************************************************/ + +STATIC_IN_RELEASE QRcode *QRcode_new(int version, int width, unsigned char *data) +{ + QRcode *qrcode; + + qrcode = (QRcode *)malloc(sizeof(QRcode)); + if(qrcode == NULL) return NULL; + + qrcode->version = version; + qrcode->width = width; + qrcode->data = data; + + return qrcode; +} + +void QRcode_free(QRcode *qrcode) +{ + if(qrcode != NULL) { + free(qrcode->data); + free(qrcode); + } +} + +STATIC_IN_RELEASE QRcode *QRcode_encodeMask(QRinput *input, int mask) +{ + int width, version; + QRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + int i, j; + QRcode *qrcode = NULL; + FrameFiller filler; + + if(input->mqr) { + errno = EINVAL; + return NULL; + } + if(input->version < 0 || input->version > QRSPEC_VERSION_MAX) { + errno = EINVAL; + return NULL; + } + if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_H)) { + errno = EINVAL; + return NULL; + } + + raw = QRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = QRspec_getWidth(version); + frame = QRspec_newFrame(version); + if(frame == NULL) { + QRraw_free(raw); + return NULL; + } + FrameFiller_set(&filler, width, frame, 0); + + /* interleaved data and ecc codes */ + for(i = 0; i < raw->dataLength; i++) { + code = QRraw_getCode(raw); + bit = 0x80; + for(j = 0; j < 8; j++) { + p = FrameFiller_next(&filler); + if(p == NULL) goto EXIT; + *p = ((bit & code) != 0); + bit = bit >> 1; + } + } + for(i = 0; i < raw->eccLength; i++) { + code = QRraw_getCode(raw); + bit = 0x80; + for(j = 0; j < 8; j++) { + p = FrameFiller_next(&filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + QRraw_free(raw); + raw = NULL; + /* remainder bits */ + j = QRspec_getRemainder(version); + for(i = 0; i < j; i++) { + p = FrameFiller_next(&filler); + if(p == NULL) goto EXIT; + *p = 0x02; + } + + /* masking */ + if(mask == -2) { // just for debug purpose + masked = (unsigned char *)malloc((size_t)(width * width)); + memcpy(masked, frame, (size_t)(width * width)); + } else if(mask < 0) { + masked = Mask_mask(width, frame, input->level); + } else { + masked = Mask_makeMask(width, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + qrcode = QRcode_new(version, width, masked); + if(qrcode == NULL) { + free(masked); + } + +EXIT: + QRraw_free(raw); + free(frame); + return qrcode; +} + +STATIC_IN_RELEASE QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask) +{ + int width, version; + MQRRawCode *raw; + unsigned char *frame, *masked, *p, code, bit; + int i, j, length; + QRcode *qrcode = NULL; + FrameFiller filler; + + if(!input->mqr) { + errno = EINVAL; + return NULL; + } + if(input->version <= 0 || input->version > MQRSPEC_VERSION_MAX) { + errno = EINVAL; + return NULL; + } + if(!(input->level >= QR_ECLEVEL_L && input->level <= QR_ECLEVEL_Q)) { + errno = EINVAL; + return NULL; + } + + raw = MQRraw_new(input); + if(raw == NULL) return NULL; + + version = raw->version; + width = MQRspec_getWidth(version); + frame = MQRspec_newFrame(version); + if(frame == NULL) { + MQRraw_free(raw); + return NULL; + } + FrameFiller_set(&filler, width, frame, 1); + + /* interleaved data and ecc codes */ + for(i = 0; i < raw->dataLength; i++) { + code = MQRraw_getCode(raw); + bit = 0x80; + if(raw->oddbits && i == raw->dataLength - 1) { + length = raw->oddbits; + } else { + length = 8; + } + for(j = 0; j < length; j++) { + p = FrameFiller_next(&filler); + if(p == NULL) goto EXIT; + *p = ((bit & code) != 0); + bit = bit >> 1; + } + } + for(i = 0; i < raw->eccLength; i++) { + code = MQRraw_getCode(raw); + bit = 0x80; + length = 8; + for(j = 0; j < length; j++) { + p = FrameFiller_next(&filler); + if(p == NULL) goto EXIT; + *p = 0x02 | ((bit & code) != 0); + bit = bit >> 1; + } + } + MQRraw_free(raw); + raw = NULL; + + /* masking */ + if(mask == -2) { // just for debug purpose + masked = (unsigned char *)malloc((size_t)(width * width)); + memcpy(masked, frame, (size_t)(width * width)); + } else if(mask < 0) { + masked = MMask_mask(version, frame, input->level); + } else { + masked = MMask_makeMask(version, frame, mask, input->level); + } + if(masked == NULL) { + goto EXIT; + } + + qrcode = QRcode_new(version, width, masked); + if(qrcode == NULL) { + free(masked); + } + +EXIT: + MQRraw_free(raw); + free(frame); + return qrcode; +} + +QRcode *QRcode_encodeInput(QRinput *input) +{ + if(input->mqr) { + return QRcode_encodeMaskMQR(input, -1); + } else { + return QRcode_encodeMask(input, -1); + } +} + +static QRcode *QRcode_encodeStringReal(const char *string, int version, QRecLevel level, int mqr, QRencodeMode hint, int casesensitive) +{ + QRinput *input; + QRcode *code; + int ret; + + if(string == NULL) { + errno = EINVAL; + return NULL; + } + if(hint != QR_MODE_8 && hint != QR_MODE_KANJI) { + errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = Split_splitStringToQRinput(string, input, hint, casesensitive); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + + return code; +} + +QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + return QRcode_encodeStringReal(string, version, level, 0, hint, casesensitive); +} + +QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + int i; + + if(version == 0) { + version = 1; + } + for(i = version; i <= MQRSPEC_VERSION_MAX ; i++) { + QRcode *code = QRcode_encodeStringReal(string, i, level, 1, hint, casesensitive); + if(code != NULL) return code; + } + + return NULL; +} + +static QRcode *QRcode_encodeDataReal(const unsigned char *data, int length, int version, QRecLevel level, int mqr) +{ + QRinput *input; + QRcode *code; + int ret; + + if(data == NULL || length == 0) { + errno = EINVAL; + return NULL; + } + + if(mqr) { + input = QRinput_newMQR(version, level); + } else { + input = QRinput_new2(version, level); + } + if(input == NULL) return NULL; + + ret = QRinput_append(input, QR_MODE_8, length, data); + if(ret < 0) { + QRinput_free(input); + return NULL; + } + code = QRcode_encodeInput(input); + QRinput_free(input); + + return code; +} + +QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level) +{ + return QRcode_encodeDataReal(data, size, version, level, 0); +} + +QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level) +{ + if(string == NULL) { + errno = EINVAL; + return NULL; + } + return QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), version, level, 0); +} + +QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level) +{ + int i; + + if(version == 0) { + version = 1; + } + for(i = version; i <= MQRSPEC_VERSION_MAX; i++) { + QRcode *code = QRcode_encodeDataReal(data, size, i, level, 1); + if(code != NULL) return code; + } + + return NULL; +} + +QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level) +{ + int i; + + if(string == NULL) { + errno = EINVAL; + return NULL; + } + if(version == 0) { + version = 1; + } + for(i = version; i <= MQRSPEC_VERSION_MAX; i++) { + QRcode *code = QRcode_encodeDataReal((unsigned char *)string, (int)strlen(string), i, level, 1); + if(code != NULL) return code; + } + + return NULL; +} + + +/****************************************************************************** + * Structured QR-code encoding + *****************************************************************************/ + +static QRcode_List *QRcode_List_newEntry(void) +{ + QRcode_List *entry; + + entry = (QRcode_List *)malloc(sizeof(QRcode_List)); + if(entry == NULL) return NULL; + + entry->next = NULL; + entry->code = NULL; + + return entry; +} + +static void QRcode_List_freeEntry(QRcode_List *entry) +{ + if(entry != NULL) { + QRcode_free(entry->code); + free(entry); + } +} + +void QRcode_List_free(QRcode_List *qrlist) +{ + QRcode_List *list = qrlist, *next; + + while(list != NULL) { + next = list->next; + QRcode_List_freeEntry(list); + list = next; + } +} + +int QRcode_List_size(QRcode_List *qrlist) +{ + QRcode_List *list = qrlist; + int size = 0; + + while(list != NULL) { + size++; + list = list->next; + } + + return size; +} + +#if 0 +static unsigned char QRcode_parity(const char *str, int size) +{ + unsigned char parity = 0; + int i; + + for(i = 0; i < size; i++) { + parity ^= str[i]; + } + + return parity; +} +#endif + +QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s) +{ + QRcode_List *head = NULL; + QRcode_List *tail = NULL; + QRcode_List *entry; + QRinput_InputList *list = s->head; + + while(list != NULL) { + if(head == NULL) { + entry = QRcode_List_newEntry(); + if(entry == NULL) goto ABORT; + head = entry; + tail = head; + } else { + entry = QRcode_List_newEntry(); + if(entry == NULL) goto ABORT; + tail->next = entry; + tail = tail->next; + } + tail->code = QRcode_encodeInput(list->input); + if(tail->code == NULL) { + goto ABORT; + } + list = list->next; + } + + return head; +ABORT: + QRcode_List_free(head); + return NULL; +} + +static QRcode_List *QRcode_encodeInputToStructured(QRinput *input) +{ + QRinput_Struct *s; + QRcode_List *codes; + + s = QRinput_splitQRinputToStruct(input); + if(s == NULL) return NULL; + + codes = QRcode_encodeInputStructured(s); + QRinput_Struct_free(s); + + return codes; +} + +static QRcode_List *QRcode_encodeDataStructuredReal( + int size, const unsigned char *data, + int version, QRecLevel level, + int eightbit, QRencodeMode hint, int casesensitive) +{ + QRinput *input; + QRcode_List *codes; + int ret; + + if(version <= 0) { + errno = EINVAL; + return NULL; + } + if(!eightbit && (hint != QR_MODE_8 && hint != QR_MODE_KANJI)) { + errno = EINVAL; + return NULL; + } + + input = QRinput_new2(version, level); + if(input == NULL) return NULL; + + if(eightbit) { + ret = QRinput_append(input, QR_MODE_8, size, data); + } else { + ret = Split_splitStringToQRinput((char *)data, input, hint, casesensitive); + } + if(ret < 0) { + QRinput_free(input); + return NULL; + } + codes = QRcode_encodeInputToStructured(input); + QRinput_free(input); + + return codes; +} + +QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level) { + return QRcode_encodeDataStructuredReal(size, data, version, level, 1, QR_MODE_NUL, 0); +} + +QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level) { + if(string == NULL) { + errno = EINVAL; + return NULL; + } + return QRcode_encodeDataStructured((int)strlen(string), (unsigned char *)string, version, level); +} + +QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive) +{ + if(string == NULL) { + errno = EINVAL; + return NULL; + } + return QRcode_encodeDataStructuredReal((int)strlen(string), (unsigned char *)string, version, level, 0, hint, casesensitive); +} + +/****************************************************************************** + * System utilities + *****************************************************************************/ + +// Changed by Libbitcoin (use own version defines). + +void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version) +{ + if(major_version != NULL) { + *major_version = LIBBITCOIN_SYSTEM_MAJOR_VERSION; + } + if(minor_version != NULL) { + *minor_version = LIBBITCOIN_SYSTEM_MINOR_VERSION; + } + if(micro_version != NULL) { + *micro_version = LIBBITCOIN_SYSTEM_PATCH_VERSION; + } +} + +char *QRcode_APIVersionString(void) +{ + return LIBBITCOIN_SYSTEM_VERSION; +} + +void QRcode_clearCache(void) +{ + return; +} diff --git a/src/wallet/qrencode/qrencode.h b/src/wallet/qrencode/qrencode.h new file mode 100644 index 0000000000..9d12aa2b99 --- /dev/null +++ b/src/wallet/qrencode/qrencode.h @@ -0,0 +1,572 @@ +/** + * qrencode - QR Code encoder + * + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** \mainpage + * Libqrencode is a library for encoding data in a QR Code symbol, a kind of 2D + * symbology. + * + * \section encoding Encoding + * + * There are two methods to encode data: encoding a string/data or + * encoding a structured data. + * + * \subsection encoding-string Encoding a string/data + * You can encode a string by calling QRcode_encodeString(). + * The given string is parsed automatically and encoded. If you want to encode + * data that can be represented as a C string style (NUL terminated), you can + * simply use this way. + * + * If the input data contains Kanji (Shift-JIS) characters and you want to + * encode them as Kanji in QR Code, you should give QR_MODE_KANJI as a hint. + * Otherwise, all of non-alphanumeric characters are encoded as 8-bit data. + * If you want to encode a whole string in 8-bit mode, you can use + * QRcode_encodeString8bit() instead. + * + * Please note that a C string can not contain NUL characters. If your data + * contains NUL, you must use QRcode_encodeData(). + * + * \subsection encoding-input Encoding a structured data + * You can construct a structured input data manually. If the structure of the + * input data is known, you can use this method. + * At first, create a ::QRinput object by QRinput_new(). Then add input data + * to the QRinput object by QRinput_append(). Finally call QRcode_encodeInput() + * to encode the QRinput data. + * You can reuse the QRinput object again to encode it in other symbols with + * different parameters. + * + * \section result Result + * The encoded symbol is generated as a ::QRcode object. It will contain its + * version number, the width of the symbol, and an array represents the symbol. + * See ::QRcode for the details. You can free the object by QRcode_free(). + * + * Please note that the version of the result may be larger than specified. + * In such cases, the input data would be too large to be encoded in a + * symbol of the specified version. + * + * \section structured Structured append + * Libqrencode can generate "Structured-appended" symbols that enables to split + * a large data set into mulitple QR codes. A QR code reader concatenates + * multiple QR code symbols into a string. + * Just like QRcode_encodeString(), you can use QRcode_encodeStringStructured() + * to generate structured-appended symbols. This functions returns an instance + * of ::QRcode_List. The returned list is a singly-linked list of QRcode: you + * can retrieve each QR code in this way: + * + * \code + * QRcode_List *qrcodes; + * QRcode_List *entry; + * QRcode *qrcode; + * + * qrcodes = QRcode_encodeStringStructured(...); + * entry = qrcodes; + * while(entry != NULL) { + * qrcode = entry->code; + * // do something + * entry = entry->next; + * } + * QRcode_List_free(entry); + * \endcode + * + * Instead of using auto-parsing functions, you can construct your own + * structured input. At first, instantiate an object of ::QRinput_Struct + * by calling QRinput_Struct_new(). This object can hold multiple ::QRinput, + * and one QR code is generated for a ::QRinput. + * QRinput_Struct_appendInput() appends a ::QRinput to a ::QRinput_Struct + * object. In order to generate structured-appended symbols, it is required to + * embed headers to each symbol. You can use + * QRinput_Struct_insertStructuredAppendHeaders() to insert appropriate + * headers to each symbol. You should call this function just once before + * encoding symbols. + */ + +#ifndef QRENCODE_H +#define QRENCODE_H + +// Added by Libbitcoin. +#include "..\include\bitcoin\system\version.hpp" +#define STATIC_IN_RELEASE static + +#if defined(__cplusplus) +extern "C" { +#endif + +/** + * Encoding mode. + */ +typedef enum { + QR_MODE_NUL = -1, ///< Terminator (NUL character). Internal use only + QR_MODE_NUM = 0, ///< Numeric mode + QR_MODE_AN, ///< Alphabet-numeric mode + QR_MODE_8, ///< 8-bit data mode + QR_MODE_KANJI, ///< Kanji (shift-jis) mode + QR_MODE_STRUCTURE, ///< Internal use only + QR_MODE_ECI, ///< ECI mode + QR_MODE_FNC1FIRST, ///< FNC1, first position + QR_MODE_FNC1SECOND, ///< FNC1, second position +} QRencodeMode; + +/** + * Level of error correction. + */ +typedef enum { + QR_ECLEVEL_L = 0, ///< lowest + QR_ECLEVEL_M, + QR_ECLEVEL_Q, + QR_ECLEVEL_H ///< highest +} QRecLevel; + +/** + * Maximum version (size) of QR-code symbol. + */ +#define QRSPEC_VERSION_MAX 40 + +/** + * Maximum version (size) of QR-code symbol. + */ +#define MQRSPEC_VERSION_MAX 4 + + +/****************************************************************************** + * Input data (qrinput.c) + *****************************************************************************/ + +/** + * Singly linked list to contain input strings. An instance of this class + * contains its version and error correction level too. It is required to + * set them by QRinput_setVersion() and QRinput_setErrorCorrectionLevel(), + * or use QRinput_new2() to instantiate an object. + */ +typedef struct _QRinput QRinput; + +/** + * Instantiate an input data object. The version is set to 0 (auto-select) + * and the error correction level is set to QR_ECLEVEL_L. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput *QRinput_new(void); + +/** + * Instantiate an input data object. + * @param version version number. + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_new2(int version, QRecLevel level); + +/** + * Instantiate an input data object. Object's Micro QR Code flag is set. + * Unlike with full-sized QR Code, version number must be specified (>0). + * @param version version number (1--4). + * @param level Error correction level. + * @return an input object (initialized). On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw EINVAL invalid arguments. + */ +extern QRinput *QRinput_newMQR(int version, QRecLevel level); + +/** + * Append data to an input object. + * The data is copied and appended to the input object. + * @param input input object. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data); + +/** + * Append ECI header. + * @param input input object. + * @param ecinum ECI indicator number (0 - 999999) + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL input data is invalid. + * + */ +extern int QRinput_appendECIheader(QRinput *input, unsigned int ecinum); + +/** + * Get current version. + * @param input input object. + * @return current version. + */ +extern int QRinput_getVersion(QRinput *input); + +/** + * Set version of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code. + * @param input input object. + * @param version version number (0 = auto) + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersion(QRinput *input, int version); + +/** + * Get current error correction level. + * @param input input object. + * @return Current error correcntion level. + */ +extern QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input); + +/** + * Set error correction level of the QR code that is to be encoded. + * This function cannot be applied to Micro QR Code. + * @param input input object. + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level); + +/** + * Set version and error correction level of the QR code at once. + * This function is recommened for Micro QR Code. + * @param input input object. + * @param version version number (0 = auto) + * @param level Error correction level. + * @retval 0 success. + * @retval -1 invalid argument. + */ +extern int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level); + +/** + * Free the input object. + * All of data chunks in the input object are freed too. + * @param input input object. + */ +extern void QRinput_free(QRinput *input); + +/** + * Validate the input data. + * @param mode encoding mode. + * @param size size of data (byte). + * @param data a pointer to the memory area of the input data. + * @retval 0 success. + * @retval -1 invalid arguments. + */ +extern int QRinput_check(QRencodeMode mode, int size, const unsigned char *data); + +/** + * Set of QRinput for structured symbols. + */ +typedef struct _QRinput_Struct QRinput_Struct; + +/** + * Instantiate a set of input data object. + * @return an instance of QRinput_Struct. On error, NULL is returned and errno + * is set to indicate the error. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput_Struct *QRinput_Struct_new(void); + +/** + * Set parity of structured symbols. + * @param s structured input object. + * @param parity parity of s. + */ +extern void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity); + +/** + * Append a QRinput object to the set. QRinput created by QRinput_newMQR() + * will be rejected. + * @warning never append the same QRinput object twice or more. + * @param s structured input object. + * @param input an input object. + * @retval >0 number of input objects in the structure. + * @retval -1 an error occurred. See Exceptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid arguments. + */ +extern int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input); + +/** + * Free all of QRinput in the set. + * @param s a structured input object. + */ +extern void QRinput_Struct_free(QRinput_Struct *s); + +/** + * Split a QRinput to QRinput_Struct. It calculates a parity, set it, then + * insert structured-append headers. QRinput created by QRinput_newMQR() will + * be rejected. + * @param input input object. Version number and error correction level must be + * set. + * @return a set of input data. On error, NULL is returned, and errno is set + * to indicate the error. See Exceptions for the details. + * @throw ERANGE input data is too large. + * @throw EINVAL invalid input data. + * @throw ENOMEM unable to allocate memory. + */ +extern QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input); + +/** + * Insert structured-append headers to the input structure. It calculates + * a parity and set it if the parity is not set yet. + * @param s input structure + * @retval 0 success. + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory. + */ +extern int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s); + +/** + * Set FNC1-1st position flag. + */ +extern int QRinput_setFNC1First(QRinput *input); + +/** + * Set FNC1-2nd position flag and application identifier. + */ +extern int QRinput_setFNC1Second(QRinput *input, unsigned char appid); + +/****************************************************************************** + * QRcode output (qrencode.c) + *****************************************************************************/ + +/** + * QRcode class. + * Symbol data is represented as an array contains width*width uchars. + * Each uchar represents a module (dot). If the less significant bit of + * the uchar is 1, the corresponding module is black. The other bits are + * meaningless for usual applications, but here its specification is described. + * + * @verbatim + MSB 76543210 LSB + |||||||`- 1=black/0=white + ||||||`-- 1=ecc/0=data code area + |||||`--- format information + ||||`---- version information + |||`----- timing pattern + ||`------ alignment pattern + |`------- finder pattern and separator + `-------- non-data modules (format, timing, etc.) + @endverbatim + */ +typedef struct { + int version; ///< version of the symbol + int width; ///< width of the symbol + unsigned char *data; ///< symbol data +} QRcode; + +/** + * Singly-linked list of QRcode. Used to represent a structured symbols. + * A list is terminated with NULL. + */ +typedef struct _QRcode_List { + QRcode *code; + struct _QRcode_List *next; +} QRcode_List; + +/** + * Create a symbol from the input data. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param input input data. + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode *QRcode_encodeInput(QRinput *input); + +/** + * Create a symbol from the string. The library automatically parses the input + * string and encodes in a QR Code symbol. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param string input string. It must be NUL terminated. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @param hint tell the library how Japanese Kanji characters should be + * encoded. If QR_MODE_KANJI is given, the library assumes that the + * given string contains Shift-JIS characters and encodes them in + * Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical + * characters will be encoded as is. If you want to embed UTF-8 + * string, choose this. Other mode will cause EINVAL error. + * @param casesensitive case-sensitive(1) or not(0). + * @return an instance of QRcode class. The version of the result QRcode may + * be larger than the designated version. On error, NULL is returned, + * and errno is set to indicate the error. See Exceptions for the + * details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeString(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Same to QRcode_encodeString(), but encode whole data in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeString8bit(const char *string, int version, QRecLevel level); + +/** + * Micro QR Code version of QRcode_encodeString(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeStringMQR(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Micro QR Code version of QRcode_encodeString8bit(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeString8bitMQR(const char *string, int version, QRecLevel level); + +/** + * Encode byte stream (may include '\0') in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param size size of the input data. + * @param data input data. + * @param version version of the symbol. If 0, the library chooses the minimum + * version for the given input data. + * @param level error correction level. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + * @throw ERANGE input data is too large. + */ +extern QRcode *QRcode_encodeData(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Micro QR Code version of QRcode_encodeData(). + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode *QRcode_encodeDataMQR(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Free the instance of QRcode class. + * @param qrcode an instance of QRcode class. + */ +extern void QRcode_free(QRcode *qrcode); + +/** + * Create structured symbols from the input data. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param s input data, structured. + * @return a singly-linked list of QRcode. + */ +extern QRcode_List *QRcode_encodeInputStructured(QRinput_Struct *s); + +/** + * Create structured symbols from the string. The library automatically parses + * the input string and encodes in a QR Code symbol. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param string input string. It must be NUL terminated. + * @param version version of the symbol. + * @param level error correction level. + * @param hint tell the library how Japanese Kanji characters should be + * encoded. If QR_MODE_KANJI is given, the library assumes that the + * given string contains Shift-JIS characters and encodes them in + * Kanji-mode. If QR_MODE_8 is given, all of non-alphanumerical + * characters will be encoded as is. If you want to embed UTF-8 + * string, choose this. Other mode will cause EINVAL error. + * @param casesensitive case-sensitive(1) or not(0). + * @return a singly-linked list of QRcode. On error, NULL is returned, and + * errno is set to indicate the error. See Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode_List *QRcode_encodeStringStructured(const char *string, int version, QRecLevel level, QRencodeMode hint, int casesensitive); + +/** + * Same to QRcode_encodeStringStructured(), but encode whole data in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + */ +extern QRcode_List *QRcode_encodeString8bitStructured(const char *string, int version, QRecLevel level); + +/** + * Create structured symbols from byte stream (may include '\0'). Wholde data + * are encoded in 8-bit mode. + * @warning This function is THREAD UNSAFE when pthread is disabled. + * @param size size of the input data. + * @param data input dat. + * @param version version of the symbol. + * @param level error correction level. + * @return a singly-linked list of QRcode. On error, NULL is returned, and + * errno is set to indicate the error. See Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern QRcode_List *QRcode_encodeDataStructured(int size, const unsigned char *data, int version, QRecLevel level); + +/** + * Return the number of symbols included in a QRcode_List. + * @param qrlist a head entry of a QRcode_List. + * @return number of symbols in the list. + */ +extern int QRcode_List_size(QRcode_List *qrlist); + +/** + * Free the QRcode_List. + * @param qrlist a head entry of a QRcode_List. + */ +extern void QRcode_List_free(QRcode_List *qrlist); + + +/****************************************************************************** + * System utilities + *****************************************************************************/ + +/** + * Return a string that identifies the library version. + * @param major_version major version number + * @param minor_version minor version number + * @param micro_version micro version number + */ +extern void QRcode_APIVersion(int *major_version, int *minor_version, int *micro_version); + +/** + * Return a string that identifies the library version. + * @return a string identifies the library version. The string is held by the + * library. Do NOT free it. + */ +extern char *QRcode_APIVersionString(void); + +/** + * @deprecated + */ +#ifndef _MSC_VER +extern void QRcode_clearCache(void) __attribute__ ((deprecated)); +#else +extern void QRcode_clearCache(void); +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* QRENCODE_H */ diff --git a/src/wallet/qrencode/qrencode_inner.h b/src/wallet/qrencode/qrencode_inner.h new file mode 100644 index 0000000000..2ea54f59d0 --- /dev/null +++ b/src/wallet/qrencode/qrencode_inner.h @@ -0,0 +1,88 @@ +/** + * qrencode - QR Code encoder + * + * Header for test use + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef QRENCODE_INNER_H +#define QRENCODE_INNER_H + +/** + * This header file includes definitions for test use. + */ + +/****************************************************************************** + * Raw code + *****************************************************************************/ + +typedef struct { + int dataLength; + int eccLength; + unsigned char *data; + unsigned char *ecc; +} RSblock; + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + int b1; + int blocks; + RSblock *rsblock; + int count; +} QRRawCode; + +extern QRRawCode *QRraw_new(QRinput *input); +extern unsigned char QRraw_getCode(QRRawCode *raw); +extern void QRraw_free(QRRawCode *raw); + +/****************************************************************************** + * Raw code for Micro QR Code + *****************************************************************************/ + +typedef struct { + int version; + int dataLength; + int eccLength; + unsigned char *datacode; + unsigned char *ecccode; + RSblock *rsblock; + int oddbits; + int count; +} MQRRawCode; + +extern MQRRawCode *MQRraw_new(QRinput *input); +extern unsigned char MQRraw_getCode(MQRRawCode *raw); +extern void MQRraw_free(MQRRawCode *raw); + +/****************************************************************************** + * Frame filling + *****************************************************************************/ +extern unsigned char *FrameFiller_test(int version); +extern unsigned char *FrameFiller_testMQR(int version); + +/****************************************************************************** + * QR-code encoding + *****************************************************************************/ +extern QRcode *QRcode_encodeMask(QRinput *input, int mask); +extern QRcode *QRcode_encodeMaskMQR(QRinput *input, int mask); +extern QRcode *QRcode_new(int version, int width, unsigned char *data); + +#endif /* QRENCODE_INNER_H */ diff --git a/src/wallet/qrencode/qrinput.c b/src/wallet/qrencode/qrinput.c new file mode 100644 index 0000000000..34bedc2a0c --- /dev/null +++ b/src/wallet/qrencode/qrinput.c @@ -0,0 +1,1639 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrencode.h" +#include "qrspec.h" +#include "mqrspec.h" +#include "bitstream.h" +#include "qrinput.h" + +/****************************************************************************** + * Utilities + *****************************************************************************/ +int QRinput_isSplittableMode(QRencodeMode mode) +{ + return (mode >= QR_MODE_NUM && mode <= QR_MODE_KANJI); +} + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ + +static QRinput_List *QRinput_List_newEntry(QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + if(QRinput_check(mode, size, data)) { + errno = EINVAL; + return NULL; + } + + entry = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(entry == NULL) return NULL; + + entry->mode = mode; + entry->size = size; + entry->data = NULL; + if(size > 0) { + entry->data = (unsigned char *)malloc((size_t)size); + if(entry->data == NULL) { + free(entry); + return NULL; + } + memcpy(entry->data, data, (size_t)size); + } + entry->bstream = NULL; + entry->next = NULL; + + return entry; +} + +static void QRinput_List_freeEntry(QRinput_List *entry) +{ + if(entry != NULL) { + free(entry->data); + BitStream_free(entry->bstream); + free(entry); + } +} + +static QRinput_List *QRinput_List_dup(QRinput_List *entry) +{ + QRinput_List *n; + + n = (QRinput_List *)malloc(sizeof(QRinput_List)); + if(n == NULL) return NULL; + + n->mode = entry->mode; + n->size = entry->size; + n->data = (unsigned char *)malloc((size_t)n->size); + if(n->data == NULL) { + free(n); + return NULL; + } + memcpy(n->data, entry->data, (size_t)entry->size); + n->bstream = NULL; + n->next = NULL; + + return n; +} + +/****************************************************************************** + * Input Data + *****************************************************************************/ + +QRinput *QRinput_new(void) +{ + return QRinput_new2(0, QR_ECLEVEL_L); +} + +QRinput *QRinput_new2(int version, QRecLevel level) +{ + QRinput *input; + + if(version < 0 || version > QRSPEC_VERSION_MAX || level < 0 || level > QR_ECLEVEL_H) { + errno = EINVAL; + return NULL; + } + + input = (QRinput *)malloc(sizeof(QRinput)); + if(input == NULL) return NULL; + + input->head = NULL; + input->tail = NULL; + input->version = version; + input->level = level; + input->mqr = 0; + input->fnc1 = 0; + + return input; +} + +QRinput *QRinput_newMQR(int version, QRecLevel level) +{ + QRinput *input; + + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + + input = QRinput_new2(version, level); + if(input == NULL) return NULL; + + input->mqr = 1; + + return input; + +INVALID: + errno = EINVAL; + return NULL; +} + +int QRinput_getVersion(QRinput *input) +{ + return input->version; +} + +int QRinput_setVersion(QRinput *input, int version) +{ + if(input->mqr || version < 0 || version > QRSPEC_VERSION_MAX) { + errno = EINVAL; + return -1; + } + + input->version = version; + + return 0; +} + +QRecLevel QRinput_getErrorCorrectionLevel(QRinput *input) +{ + return input->level; +} + +int QRinput_setErrorCorrectionLevel(QRinput *input, QRecLevel level) +{ + if(input->mqr || level > QR_ECLEVEL_H) { + errno = EINVAL; + return -1; + } + + input->level = level; + + return 0; +} + +int QRinput_setVersionAndErrorCorrectionLevel(QRinput *input, int version, QRecLevel level) +{ + if(input->mqr) { + if(version <= 0 || version > MQRSPEC_VERSION_MAX) goto INVALID; + if((MQRspec_getECCLength(version, level) == 0)) goto INVALID; + } else { + if(version < 0 || version > QRSPEC_VERSION_MAX) goto INVALID; + if(level > QR_ECLEVEL_H) goto INVALID; + } + + input->version = version; + input->level = level; + + return 0; + +INVALID: + errno = EINVAL; + return -1; +} + +static void QRinput_appendEntry(QRinput *input, QRinput_List *entry) +{ + if(input->tail == NULL) { + input->head = entry; + input->tail = entry; + } else { + input->tail->next = entry; + input->tail = entry; + } + entry->next = NULL; +} + +int QRinput_append(QRinput *input, QRencodeMode mode, int size, const unsigned char *data) +{ + QRinput_List *entry; + + entry = QRinput_List_newEntry(mode, size, data); + if(entry == NULL) { + return -1; + } + + QRinput_appendEntry(input, entry); + + return 0; +} + +/** + * Insert a structured-append header to the head of the input data. + * @param input input data. + * @param size number of structured symbols. + * @param number index number of the symbol. (1 <= number <= size) + * @param parity parity among input data. (NOTE: each symbol of a set of structured symbols has the same parity data) + * @retval 0 success. + * @retval -1 error occurred and errno is set to indeicate the error. See Execptions for the details. + * @throw EINVAL invalid parameter. + * @throw ENOMEM unable to allocate memory. + */ +STATIC_IN_RELEASE int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int number, unsigned char parity) +{ + QRinput_List *entry; + unsigned char buf[3]; + + if(size > MAX_STRUCTURED_SYMBOLS) { + errno = EINVAL; + return -1; + } + if(number <= 0 || number > size) { + errno = EINVAL; + return -1; + } + + buf[0] = (unsigned char)size; + buf[1] = (unsigned char)number; + buf[2] = parity; + entry = QRinput_List_newEntry(QR_MODE_STRUCTURE, 3, buf); + if(entry == NULL) { + return -1; + } + + entry->next = input->head; + input->head = entry; + + return 0; +} + +int QRinput_appendECIheader(QRinput *input, unsigned int ecinum) +{ + unsigned char data[4]; + + if(ecinum > 999999) { + errno = EINVAL; + return -1; + } + + /* We manually create byte array of ecinum because + (unsigned char *)&ecinum may cause bus error on some architectures, */ + data[0] = ecinum & 0xff; + data[1] = (ecinum >> 8) & 0xff; + data[2] = (ecinum >> 16) & 0xff; + data[3] = (ecinum >> 24) & 0xff; + return QRinput_append(input, QR_MODE_ECI, 4, data); +} + +void QRinput_free(QRinput *input) +{ + QRinput_List *list, *next; + + if(input != NULL) { + list = input->head; + while(list != NULL) { + next = list->next; + QRinput_List_freeEntry(list); + list = next; + } + free(input); + } +} + +static unsigned char QRinput_calcParity(QRinput *input) +{ + unsigned char parity = 0; + QRinput_List *list; + int i; + + list = input->head; + while(list != NULL) { + if(list->mode != QR_MODE_STRUCTURE) { + for(i = list->size-1; i >= 0; i--) { + parity ^= list->data[i]; + } + } + list = list->next; + } + + return parity; +} + +QRinput *QRinput_dup(QRinput *input) +{ + QRinput *n; + QRinput_List *list, *e; + + if(input->mqr) { + n = QRinput_newMQR(input->version, input->level); + } else { + n = QRinput_new2(input->version, input->level); + } + if(n == NULL) return NULL; + + list = input->head; + while(list != NULL) { + e = QRinput_List_dup(list); + if(e == NULL) { + QRinput_free(n); + return NULL; + } + QRinput_appendEntry(n, e); + list = list->next; + } + + return n; +} + +/****************************************************************************** + * Numeric data + *****************************************************************************/ + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeNum(int size, const char *data) +{ + int i; + + for(i = 0; i < size; i++) { + if(data[i] < '0' || data[i] > '9') + return -1; + } + + return 0; +} + +/** + * Estimate the length of the encoded bit stream of numeric data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeNum(int size) +{ + int w; + int bits; + + w = size / 3; + bits = w * 10; + switch(size - w * 3) { + case 1: + bits += 4; + break; + case 2: + bits += 7; + break; + default: + break; + } + + return bits; +} + +/** + * Convert the number data and append to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeModeNum(QRinput_List *entry, BitStream *bstream, int version, int mqr) +{ + int words, i, ret; + unsigned int val; + + if(mqr) { + if(version > 1) { + ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_NUM); + if(ret < 0) return -1; + } + ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_NUM, version), (unsigned int)entry->size); + if(ret < 0) return -1; + } else { + ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_NUM); + if(ret < 0) return -1; + + ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_NUM, version), (unsigned int)entry->size); + if(ret < 0) return -1; + } + + words = entry->size / 3; + for(i = 0; i < words; i++) { + val = (unsigned int)(entry->data[i*3 ] - '0') * 100; + val += (unsigned int)(entry->data[i*3+1] - '0') * 10; + val += (unsigned int)(entry->data[i*3+2] - '0'); + + ret = BitStream_appendNum(bstream, 10, val); + if(ret < 0) return -1; + } + + if(entry->size - words * 3 == 1) { + val = (unsigned int)(entry->data[words*3] - '0'); + ret = BitStream_appendNum(bstream, 4, val); + if(ret < 0) return -1; + } else if(entry->size - words * 3 == 2) { + val = (unsigned int)(entry->data[words*3 ] - '0') * 10; + val += (unsigned int)(entry->data[words*3+1] - '0'); + ret = BitStream_appendNum(bstream, 7, val); + if(ret < 0) return -1; + } + + return 0; +} + +/****************************************************************************** + * Alphabet-numeric data + *****************************************************************************/ + +const signed char QRinput_anTable[128] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, + -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +}; + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeAn(int size, const char *data) +{ + int i; + + for(i = 0; i < size; i++) { + if(QRinput_lookAnTable(data[i]) < 0) + return -1; + } + + return 0; +} + +/** + * Estimate the length of the encoded bit stream of alphabet-numeric data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeAn(int size) +{ + int w; + int bits; + + w = size / 2; + bits = w * 11; + if(size & 1) { + bits += 6; + } + + return bits; +} + +/** + * Convert the alphabet-numeric data and append to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid version. + */ +static int QRinput_encodeModeAn(QRinput_List *entry, BitStream *bstream, int version, int mqr) +{ + int words, i, ret; + unsigned int val; + + if(mqr) { + if(version < 2) { + errno = ERANGE; + return -1; + } + ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_AN); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_AN, version), (unsigned int)entry->size); + if(ret < 0) return -1; + } else { + ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_AN); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_AN, version), (unsigned int)entry->size); + if(ret < 0) return -1; + } + + words = entry->size / 2; + for(i = 0; i < words; i++) { + val = (unsigned int)QRinput_lookAnTable(entry->data[i*2 ]) * 45; + val += (unsigned int)QRinput_lookAnTable(entry->data[i*2+1]); + + ret = BitStream_appendNum(bstream, 11, val); + if(ret < 0) return -1; + } + + if(entry->size & 1) { + val = (unsigned int)QRinput_lookAnTable(entry->data[words * 2]); + + ret = BitStream_appendNum(bstream, 6, val); + if(ret < 0) return -1; + } + + return 0; +} + +/****************************************************************************** + * 8 bit data + *****************************************************************************/ + +/** + * Estimate the length of the encoded bit stream of 8 bit data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsMode8(int size) +{ + return size * 8; +} + +/** + * Convert the 8bits data and append to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_encodeMode8(QRinput_List *entry, BitStream *bstream, int version, int mqr) +{ + int ret; + + if(mqr) { + if(version < 3) { + errno = ERANGE; + return -1; + } + ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_8); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_8, version), (unsigned int)entry->size); + if(ret < 0) return -1; + } else { + ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_8); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_8, version), (unsigned int)entry->size); + if(ret < 0) return -1; + } + + ret = BitStream_appendBytes(bstream, (size_t)entry->size, entry->data); + if(ret < 0) return -1; + + return 0; +} + + +/****************************************************************************** + * Kanji data + *****************************************************************************/ + +/** + * Estimate the length of the encoded bit stream of kanji data. + * @param size + * @return number of bits + */ +int QRinput_estimateBitsModeKanji(int size) +{ + return (size / 2) * 13; +} + +/** + * Check the input data. + * @param size + * @param data + * @return result + */ +static int QRinput_checkModeKanji(int size, const unsigned char *data) +{ + int i; + unsigned int val; + + if(size & 1) + return -1; + + for(i = 0; i < size; i+=2) { + val = ((unsigned int)data[i] << 8) | data[i+1]; + if(val < 0x8140 || (val > 0x9ffc && val < 0xe040) || val > 0xebbf) { + return -1; + } + } + + return 0; +} + +/** + * Convert the kanji data and append to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid version. + */ +static int QRinput_encodeModeKanji(QRinput_List *entry, BitStream *bstream, int version, int mqr) +{ + int ret, i; + unsigned int val, h; + + if(mqr) { + if(version < 2) { + errno = ERANGE; + return -1; + } + ret = BitStream_appendNum(bstream, (size_t)(version - 1), MQRSPEC_MODEID_KANJI); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, (size_t)MQRspec_lengthIndicator(QR_MODE_KANJI, version), (unsigned int)entry->size/2); + if(ret < 0) return -1; + } else { + ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_KANJI); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, (size_t)QRspec_lengthIndicator(QR_MODE_KANJI, version), (unsigned int)entry->size/2); + if(ret < 0) return -1; + } + + for(i = 0; i < entry->size; i+=2) { + val = ((unsigned int)entry->data[i] << 8) | entry->data[i+1]; + if(val <= 0x9ffc) { + val -= 0x8140; + } else { + val -= 0xc140; + } + h = (val >> 8) * 0xc0; + val = (val & 0xff) + h; + + ret = BitStream_appendNum(bstream, 13, val); + if(ret < 0) return -1; + } + + return 0; +} + +/****************************************************************************** + * Structured Symbol + *****************************************************************************/ + +/** + * Convert a structure symbol code and append to a bit stream. + * @param entry + * @param mqr + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw EINVAL invalid entry. + */ +static int QRinput_encodeModeStructure(QRinput_List *entry, BitStream *bstream, int mqr) +{ + int ret; + + if(mqr) { + errno = EINVAL; + return -1; + } + + ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_STRUCTURE); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, 4, entry->data[1] - 1U); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, 4, entry->data[0] - 1U); + if(ret < 0) return -1; + ret = BitStream_appendNum(bstream, 8, entry->data[2]); + if(ret < 0) return -1; + + return 0; +} + +/****************************************************************************** + * FNC1 + *****************************************************************************/ + +static int QRinput_checkModeFNC1Second(int size) +{ + if(size != 1) return -1; + + /* No data check required. */ + + return 0; +} + +static int QRinput_encodeModeFNC1Second(QRinput_List *entry, BitStream *bstream) +{ + int ret; + + ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_FNC1SECOND); + if(ret < 0) return -1; + + ret = BitStream_appendBytes(bstream, 1, entry->data); + if(ret < 0) return -1; + + return 0; +} + +/****************************************************************************** + * ECI header + *****************************************************************************/ +static unsigned int QRinput_decodeECIfromByteArray(unsigned char *data) +{ + int i; + unsigned int ecinum; + + ecinum = 0; + for(i = 0; i < 4; i++) { + ecinum = ecinum << 8; + ecinum |= data[3-i]; + } + + return ecinum; +} + +static int QRinput_estimateBitsModeECI(unsigned char *data) +{ + unsigned int ecinum; + + ecinum = QRinput_decodeECIfromByteArray(data); + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + return MODE_INDICATOR_SIZE + 8; + } else if(ecinum < 16384) { + return MODE_INDICATOR_SIZE + 16; + } else { + return MODE_INDICATOR_SIZE + 24; + } +} + +static int QRinput_encodeModeECI(QRinput_List *entry, BitStream *bstream) +{ + int ret, words; + unsigned int ecinum, code; + + ecinum = QRinput_decodeECIfromByteArray(entry->data); + + /* See Table 4 of JISX 0510:2004 pp.17. */ + if(ecinum < 128) { + words = 1; + code = ecinum; + } else if(ecinum < 16384) { + words = 2; + code = 0x8000 + ecinum; + } else { + words = 3; + code = 0xc0000 + ecinum; + } + + ret = BitStream_appendNum(bstream, 4, QRSPEC_MODEID_ECI); + if(ret < 0) return -1; + + ret = BitStream_appendNum(bstream, (size_t)words * 8, code); + if(ret < 0) return -1; + + return 0; +} + +/****************************************************************************** + * Validation + *****************************************************************************/ + +int QRinput_check(QRencodeMode mode, int size, const unsigned char *data) +{ + if((mode == QR_MODE_FNC1FIRST && size < 0) || size <= 0) return -1; + + switch(mode) { + case QR_MODE_NUM: + return QRinput_checkModeNum(size, (const char *)data); + case QR_MODE_AN: + return QRinput_checkModeAn(size, (const char *)data); + case QR_MODE_KANJI: + return QRinput_checkModeKanji(size, data); + case QR_MODE_8: + return 0; + case QR_MODE_STRUCTURE: + return 0; + case QR_MODE_ECI: + return 0; + case QR_MODE_FNC1FIRST: + return 0; + case QR_MODE_FNC1SECOND: + return QRinput_checkModeFNC1Second(size); + case QR_MODE_NUL: + break; + } + + return -1; +} + +/****************************************************************************** + * Estimation of the bit length + *****************************************************************************/ + +/** + * Estimate the length of the encoded bit stream on the current version. + * @param entry + * @param version version of the symbol + * @param mqr + * @return number of bits + */ +static int QRinput_estimateBitStreamSizeOfEntry(QRinput_List *entry, int version, int mqr) +{ + int bits = 0; + int l, m; + int num; + + if(version == 0) version = 1; + + switch(entry->mode) { + case QR_MODE_NUM: + bits = QRinput_estimateBitsModeNum(entry->size); + break; + case QR_MODE_AN: + bits = QRinput_estimateBitsModeAn(entry->size); + break; + case QR_MODE_8: + bits = QRinput_estimateBitsMode8(entry->size); + break; + case QR_MODE_KANJI: + bits = QRinput_estimateBitsModeKanji(entry->size); + break; + case QR_MODE_STRUCTURE: + return STRUCTURE_HEADER_SIZE; + case QR_MODE_ECI: + bits = QRinput_estimateBitsModeECI(entry->data); + break; + case QR_MODE_FNC1FIRST: + return MODE_INDICATOR_SIZE; + case QR_MODE_FNC1SECOND: + return MODE_INDICATOR_SIZE + 8; + default: + return 0; + } + + if(mqr) { + l = MQRspec_lengthIndicator(entry->mode, version); + m = version - 1; + bits += l + m; + } else { + l = QRspec_lengthIndicator(entry->mode, version); + m = 1 << l; + if(entry->mode == QR_MODE_KANJI) { + num = (entry->size/2 + m - 1) / m; + } else { + num = (entry->size + m - 1) / m; + } + + bits += num * (MODE_INDICATOR_SIZE + l); + } + + return bits; +} + +/** + * Estimate the length of the encoded bit stream of the data. + * @param input input data + * @param version version of the symbol + * @return number of bits + */ +STATIC_IN_RELEASE int QRinput_estimateBitStreamSize(QRinput *input, int version) +{ + QRinput_List *list; + int bits = 0; + + list = input->head; + while(list != NULL) { + bits += QRinput_estimateBitStreamSizeOfEntry(list, version, input->mqr); + list = list->next; + } + + return bits; +} + +/** + * Estimate the required version number of the symbol. + * @param input input data + * @return required version number or -1 for failure. + */ +STATIC_IN_RELEASE int QRinput_estimateVersion(QRinput *input) +{ + int bits; + int version, prev; + + version = 0; + do { + prev = version; + bits = QRinput_estimateBitStreamSize(input, prev); + version = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if(prev == 0 && version > 1) { + version--; + } + } while (version > prev); + + return version; +} + +/** + * Return required length in bytes for specified mode, version and bits. + * @param mode + * @param version + * @param bits + * @return required length of code words in bytes. + */ +STATIC_IN_RELEASE int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits) +{ + int payload, size, chunks, remain, maxsize; + + payload = bits - 4 - QRspec_lengthIndicator(mode, version); + switch(mode) { + case QR_MODE_NUM: + chunks = payload / 10; + remain = payload - chunks * 10; + size = chunks * 3; + if(remain >= 7) { + size += 2; + } else if(remain >= 4) { + size += 1; + } + break; + case QR_MODE_AN: + chunks = payload / 11; + remain = payload - chunks * 11; + size = chunks * 2; + if(remain >= 6) size++; + break; + case QR_MODE_8: + size = payload / 8; + break; + case QR_MODE_KANJI: + size = (payload / 13) * 2; + break; + case QR_MODE_STRUCTURE: + size = payload / 8; + break; + default: + size = 0; + break; + } + maxsize = QRspec_maximumWords(mode, version); + if(size < 0) size = 0; + if(maxsize > 0 && size > maxsize) size = maxsize; + + return size; +} + +/****************************************************************************** + * Data conversion + *****************************************************************************/ + +/** + * Convert the input data in the data chunk and append to a bit stream. + * @param entry + * @param bstream + * @return number of bits (>0) or -1 for failure. + */ +static int QRinput_encodeBitStream(QRinput_List *entry, BitStream *bstream, int version, int mqr) +{ + int words, ret; + QRinput_List *st1 = NULL, *st2 = NULL; + int prevsize; + + prevsize = (int)BitStream_size(bstream); + + if(mqr) { + words = MQRspec_maximumWords(entry->mode, version); + } else { + words = QRspec_maximumWords(entry->mode, version); + } + if(words != 0 && entry->size > words) { + st1 = QRinput_List_newEntry(entry->mode, words, entry->data); + if(st1 == NULL) goto ABORT; + st2 = QRinput_List_newEntry(entry->mode, entry->size - words, &entry->data[words]); + if(st2 == NULL) goto ABORT; + + ret = QRinput_encodeBitStream(st1, bstream, version, mqr); + if(ret < 0) goto ABORT; + ret = QRinput_encodeBitStream(st2, bstream, version, mqr); + if(ret < 0) goto ABORT; + + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + } else { + ret = 0; + switch(entry->mode) { + case QR_MODE_NUM: + ret = QRinput_encodeModeNum(entry, bstream, version, mqr); + break; + case QR_MODE_AN: + ret = QRinput_encodeModeAn(entry, bstream, version, mqr); + break; + case QR_MODE_8: + ret = QRinput_encodeMode8(entry, bstream, version, mqr); + break; + case QR_MODE_KANJI: + ret = QRinput_encodeModeKanji(entry, bstream, version, mqr); + break; + case QR_MODE_STRUCTURE: + ret = QRinput_encodeModeStructure(entry, bstream, mqr); + break; + case QR_MODE_ECI: + ret = QRinput_encodeModeECI(entry, bstream); + break; + case QR_MODE_FNC1SECOND: + ret = QRinput_encodeModeFNC1Second(entry, bstream); + break; + default: + break; + } + if(ret < 0) return -1; + } + + return (int)BitStream_size(bstream) - prevsize; +ABORT: + QRinput_List_freeEntry(st1); + QRinput_List_freeEntry(st2); + return -1; +} + +/** + * Convert the input data to a bit stream. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_createBitStream(QRinput *input, BitStream *bstream) +{ + QRinput_List *list; + int bits, total = 0; + + list = input->head; + while(list != NULL) { + bits = QRinput_encodeBitStream(list, bstream, input->version, input->mqr); + if(bits < 0) return -1; + total += bits; + list = list->next; + } + + return total; +} + +/** + * Convert the input data to a bit stream. + * When the version number is given and that is not sufficient, it is increased + * automatically. + * @param input input data. + * @param bstream where the converted data is stored. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ENOMEM unable to allocate memory. + * @throw ERANGE input data is too large. + */ +static int QRinput_convertData(QRinput *input, BitStream *bstream) +{ + int bits; + int ver; + + ver = QRinput_estimateVersion(input); + if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } + + for(;;) { + BitStream_reset(bstream); + bits = QRinput_createBitStream(input, bstream); + if(bits < 0) return -1; + ver = QRspec_getMinimumVersion((bits + 7) / 8, input->level); + if(ver > QRinput_getVersion(input)) { + QRinput_setVersion(input, ver); + } else { + break; + } + } + + return 0; +} + +/** + * Append padding bits for the input data. + * @param bstream Bitstream to be appended. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ERANGE input data is too large. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_appendPaddingBit(BitStream *bstream, QRinput *input) +{ + int bits, maxbits, words, maxwords, i, ret; + int padlen; + + bits = (int)BitStream_size(bstream); + maxwords = QRspec_getDataLength(input->version, input->level); + maxbits = maxwords * 8; + + if(maxbits < bits) { + errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + if(maxbits - bits <= 4) { + return (int)BitStream_appendNum(bstream, (size_t)(maxbits - bits), 0); + } + + words = (bits + 4 + 7) / 8; + + ret = (int)BitStream_appendNum(bstream, (size_t)(words * 8 - bits), 0); + if(ret < 0) return ret; + + padlen = maxwords - words; + if(padlen > 0) { + for(i = 0; i < padlen; i++) { + ret = (int)BitStream_appendNum(bstream, 8, (i&1)?0x11:0xec); + if(ret < 0) { + return ret; + } + } + } + + return 0; +} + +/** + * Append padding bits for the input data - Micro QR Code version. + * @param bstream Bitstream to be appended. + * @param input input data. + * @retval 0 success + * @retval -1 an error occurred and errno is set to indeicate the error. + * See Execptions for the details. + * @throw ERANGE input data is too large. + * @throw ENOMEM unable to allocate memory. + */ +static int QRinput_appendPaddingBitMQR(BitStream *bstream, QRinput *input) +{ + int bits, maxbits, words, maxwords, i, ret, termbits; + int padlen; + + bits = (int)BitStream_size(bstream); + maxbits = MQRspec_getDataLengthBit(input->version, input->level); + maxwords = maxbits / 8; + + if(maxbits < bits) { + errno = ERANGE; + return -1; + } + if(maxbits == bits) { + return 0; + } + + termbits = input->version * 2 + 1; + + if(maxbits - bits <= termbits) { + return (int)BitStream_appendNum(bstream, (size_t)(maxbits - bits), 0); + } + + bits += termbits; + + words = (bits + 7) / 8; + if(maxbits - words * 8 > 0) { + termbits += words * 8 - bits; + if(words == maxwords) termbits += maxbits - words * 8; + } else { + termbits += words * 8 - bits; + } + ret = (int)BitStream_appendNum(bstream, (size_t)termbits, 0); + if(ret < 0) return ret; + + padlen = maxwords - words; + if(padlen > 0) { + for(i = 0; i < padlen; i++) { + ret = (int)BitStream_appendNum(bstream, 8, (i&1)?0x11:0xec); + if(ret < 0) return ret; + } + termbits = maxbits - maxwords * 8; + if(termbits > 0) { + ret = (int)BitStream_appendNum(bstream, (size_t)termbits, 0); + if(ret < 0) return ret; + } + } + + return 0; +} + +static int QRinput_insertFNC1Header(QRinput *input) +{ + QRinput_List *entry = NULL; + + if(input->fnc1 == 1) { + entry = QRinput_List_newEntry(QR_MODE_FNC1FIRST, 0, NULL); + } else if(input->fnc1 == 2) { + entry = QRinput_List_newEntry(QR_MODE_FNC1SECOND, 1, &(input->appid)); + } + if(entry == NULL) { + return -1; + } + + if(input->head->mode != QR_MODE_STRUCTURE && input->head->mode != QR_MODE_ECI) { + entry->next = input->head; + input->head = entry; + } else { + entry->next = input->head->next; + input->head->next = entry; + } + + return 0; +} + +/** + * Merge all bit streams in the input data. + * @param input input data. + * @return merged bit stream + */ + +STATIC_IN_RELEASE int QRinput_mergeBitStream(QRinput *input, BitStream *bstream) +{ + if(input->mqr) { + if(QRinput_createBitStream(input, bstream) < 0) { + return -1; + } + } else { + if(input->fnc1) { + if(QRinput_insertFNC1Header(input) < 0) { + return -1; + } + } + if(QRinput_convertData(input, bstream) < 0) { + return -1; + } + } + + return 0; +} + +/** + * Merge all bit streams in the input data and append padding bits + * @param input input data. + * @return padded merged bit stream + */ + +STATIC_IN_RELEASE int QRinput_getBitStream(QRinput *input, BitStream *bstream) +{ + int ret; + + ret = QRinput_mergeBitStream(input, bstream); + if(ret < 0) return -1; + + if(input->mqr) { + ret = QRinput_appendPaddingBitMQR(bstream, input); + } else { + ret = QRinput_appendPaddingBit(bstream, input); + } + if(ret < 0) return -1; + + return 0; +} + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ + +unsigned char *QRinput_getByteStream(QRinput *input) +{ + BitStream *bstream; + unsigned char *array; + int ret; + + bstream = BitStream_new(); + if(bstream == NULL) { + return NULL; + } + + ret = QRinput_getBitStream(input, bstream); + if(ret < 0) { + BitStream_free(bstream); + return NULL; + } + array = BitStream_toByte(bstream); + BitStream_free(bstream); + + return array; +} + +/****************************************************************************** + * Structured input data + *****************************************************************************/ + +static QRinput_InputList *QRinput_InputList_newEntry(QRinput *input) +{ + QRinput_InputList *entry; + + entry = (QRinput_InputList *)malloc(sizeof(QRinput_InputList)); + if(entry == NULL) return NULL; + + entry->input = input; + entry->next = NULL; + + return entry; +} + +static void QRinput_InputList_freeEntry(QRinput_InputList *entry) +{ + if(entry != NULL) { + QRinput_free(entry->input); + free(entry); + } +} + +QRinput_Struct *QRinput_Struct_new(void) +{ + QRinput_Struct *s; + + s = (QRinput_Struct *)malloc(sizeof(QRinput_Struct)); + if(s == NULL) return NULL; + + s->size = 0; + s->parity = -1; + s->head = NULL; + s->tail = NULL; + + return s; +} + +void QRinput_Struct_setParity(QRinput_Struct *s, unsigned char parity) +{ + s->parity = (int)parity; +} + +int QRinput_Struct_appendInput(QRinput_Struct *s, QRinput *input) +{ + QRinput_InputList *e; + + if(input->mqr) { + errno = EINVAL; + return -1; + } + + e = QRinput_InputList_newEntry(input); + if(e == NULL) return -1; + + s->size++; + if(s->tail == NULL) { + s->head = e; + s->tail = e; + } else { + s->tail->next = e; + s->tail = e; + } + + return s->size; +} + +void QRinput_Struct_free(QRinput_Struct *s) +{ + QRinput_InputList *list, *next; + + if(s != NULL) { + list = s->head; + while(list != NULL) { + next = list->next; + QRinput_InputList_freeEntry(list); + list = next; + } + free(s); + } +} + +static unsigned char QRinput_Struct_calcParity(QRinput_Struct *s) +{ + QRinput_InputList *list; + unsigned char parity = 0; + + list = s->head; + while(list != NULL) { + parity ^= QRinput_calcParity(list->input); + list = list->next; + } + + QRinput_Struct_setParity(s, parity); + + return parity; +} + +static int QRinput_List_shrinkEntry(QRinput_List *entry, int bytes) +{ + unsigned char *data; + + data = (unsigned char *)malloc((size_t)bytes); + if(data == NULL) return -1; + + memcpy(data, entry->data, (size_t)bytes); + free(entry->data); + entry->data = data; + entry->size = bytes; + + return 0; +} + +STATIC_IN_RELEASE int QRinput_splitEntry(QRinput_List *entry, int bytes) +{ + QRinput_List *e; + int ret; + + e = QRinput_List_newEntry(entry->mode, entry->size - bytes, entry->data + bytes); + if(e == NULL) { + return -1; + } + + ret = QRinput_List_shrinkEntry(entry, bytes); + if(ret < 0) { + QRinput_List_freeEntry(e); + return -1; + } + + e->next = entry->next; + entry->next = e; + + return 0; +} + +QRinput_Struct *QRinput_splitQRinputToStruct(QRinput *input) +{ + QRinput *p = NULL; + QRinput_Struct *s = NULL; + int bits, maxbits, nextbits, bytes, ret; + QRinput_List *list, *next, *prev; + BitStream *bstream = NULL; + + if(input->mqr) { + errno = EINVAL; + return NULL; + } + + s = QRinput_Struct_new(); + if(s == NULL) return NULL; + + input = QRinput_dup(input); + if(input == NULL) { + QRinput_Struct_free(s); + return NULL; + } + + QRinput_Struct_setParity(s, QRinput_calcParity(input)); + maxbits = QRspec_getDataLength(input->version, input->level) * 8 - STRUCTURE_HEADER_SIZE; + + if(maxbits <= 0) goto ABORT; + + bstream = BitStream_new(); + if(bstream == NULL) goto ABORT; + + bits = 0; + list = input->head; + prev = NULL; + while(list != NULL) { + nextbits = QRinput_estimateBitStreamSizeOfEntry(list, input->version, input->mqr); + if(bits + nextbits <= maxbits) { + BitStream_reset(bstream); + ret = QRinput_encodeBitStream(list, bstream, input->version, input->mqr); + if(ret < 0) goto ABORT; + bits += ret; + prev = list; + list = list->next; + } else { + bytes = QRinput_lengthOfCode(list->mode, input->version, maxbits - bits); + p = QRinput_new2(input->version, input->level); + if(p == NULL) goto ABORT; + if(bytes > 0) { + /* Splits this entry into 2 entries. */ + ret = QRinput_splitEntry(list, bytes); + if(ret < 0) { + QRinput_free(p); + goto ABORT; + } + /* First half is the tail of the current input. */ + next = list->next; + list->next = NULL; + /* Second half is the head of the next input, p.*/ + p->head = next; + /* Renew QRinput.tail. */ + p->tail = input->tail; + input->tail = list; + /* Point to the next entry. */ + prev = list; + list = next; + } else { + /* Current entry will go to the next input. */ + prev->next = NULL; + p->head = list; + p->tail = input->tail; + input->tail = prev; + } + ret = QRinput_Struct_appendInput(s, input); + if(ret < 0) { + QRinput_free(p); + goto ABORT; + } + input = p; + bits = 0; + } + } + ret = QRinput_Struct_appendInput(s, input); + if(ret < 0) goto ABORT; + if(s->size > MAX_STRUCTURED_SYMBOLS) { + errno = ERANGE; + QRinput_Struct_free(s); + BitStream_free(bstream); + return NULL; + } + ret = QRinput_Struct_insertStructuredAppendHeaders(s); + if(ret < 0) { + QRinput_Struct_free(s); + BitStream_free(bstream); + return NULL; + } + + BitStream_free(bstream); + return s; + +ABORT: + BitStream_free(bstream); + QRinput_free(input); + QRinput_Struct_free(s); + return NULL; +} + +int QRinput_Struct_insertStructuredAppendHeaders(QRinput_Struct *s) +{ + int i; + QRinput_InputList *list; + + if(s->size == 1) { + return 0; + } + + if(s->parity < 0) { + QRinput_Struct_calcParity(s); + } + i = 1; + list = s->head; + while(list != NULL) { + if(QRinput_insertStructuredAppendHeader(list->input, s->size, i, s->parity)) + return -1; + i++; + list = list->next; + } + + return 0; +} + +/****************************************************************************** + * Extended encoding mode (FNC1 and ECI) + *****************************************************************************/ + +int QRinput_setFNC1First(QRinput *input) +{ + if(input->mqr) { + errno = EINVAL; + return -1; + } + input->fnc1 = 1; + + return 0; +} + +int QRinput_setFNC1Second(QRinput *input, unsigned char appid) +{ + if(input->mqr) { + errno = EINVAL; + return -1; + } + input->fnc1 = 2; + input->appid = appid; + + return 0; +} diff --git a/src/wallet/qrencode/qrinput.h b/src/wallet/qrencode/qrinput.h new file mode 100644 index 0000000000..5892c48246 --- /dev/null +++ b/src/wallet/qrencode/qrinput.h @@ -0,0 +1,124 @@ +/* + * qrencode - QR Code encoder + * + * Input data chunk class + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef QRINPUT_H +#define QRINPUT_H + +#include "qrencode.h" +#include "bitstream.h" + +int QRinput_isSplittableMode(QRencodeMode mode); + +/****************************************************************************** + * Entry of input data + *****************************************************************************/ +typedef struct _QRinput_List QRinput_List; + +struct _QRinput_List { + QRencodeMode mode; + int size; ///< Size of data chunk (byte). + unsigned char *data; ///< Data chunk. + BitStream *bstream; + QRinput_List *next; +}; + +/****************************************************************************** + * Input Data + *****************************************************************************/ +struct _QRinput { + int version; + QRecLevel level; + QRinput_List *head; + QRinput_List *tail; + int mqr; + int fnc1; + unsigned char appid; +}; + +/****************************************************************************** + * Structured append input data + *****************************************************************************/ +typedef struct _QRinput_InputList QRinput_InputList; + +struct _QRinput_InputList { + QRinput *input; + QRinput_InputList *next; +}; + +struct _QRinput_Struct { + int size; ///< number of structured symbols + int parity; + QRinput_InputList *head; + QRinput_InputList *tail; +}; + +/** + * Pack all bit streams padding bits into a byte array. + * @param input input data. + * @return padded merged byte stream + */ +extern unsigned char *QRinput_getByteStream(QRinput *input); + + +extern int QRinput_estimateBitsModeNum(int size); +extern int QRinput_estimateBitsModeAn(int size); +extern int QRinput_estimateBitsMode8(int size); +extern int QRinput_estimateBitsModeKanji(int size); + +extern QRinput *QRinput_dup(QRinput *input); + +extern const signed char QRinput_anTable[128]; + +/** + * Look up the alphabet-numeric convesion table (see JIS X0510:2004, pp.19). + * @param __c__ character + * @return value + */ +#define QRinput_lookAnTable(__c__) \ + ((__c__ & 0x80)?-1:QRinput_anTable[(int)__c__]) + +/** + * Length of a standard mode indicator in bits. + */ + +#define MODE_INDICATOR_SIZE 4 + +/** + * Length of a segment of structured-append header. + */ +#define STRUCTURE_HEADER_SIZE 20 + +/** + * Maximum number of symbols in a set of structured-appended symbols. + */ +#define MAX_STRUCTURED_SYMBOLS 16 + +#ifdef WITH_TESTS +extern int QRinput_mergeBitStream(QRinput *input, BitStream *bstream); +extern int QRinput_getBitStream(QRinput *input, BitStream *bstream); +extern int QRinput_estimateBitStreamSize(QRinput *input, int version); +extern int QRinput_splitEntry(QRinput_List *entry, int bytes); +extern int QRinput_estimateVersion(QRinput *input); +extern int QRinput_lengthOfCode(QRencodeMode mode, int version, int bits); +extern int QRinput_insertStructuredAppendHeader(QRinput *input, int size, int index, unsigned char parity); +#endif + +#endif /* QRINPUT_H */ diff --git a/src/wallet/qrencode/qrspec.c b/src/wallet/qrencode/qrspec.c new file mode 100644 index 0000000000..f3d3b2c526 --- /dev/null +++ b/src/wallet/qrencode/qrspec.c @@ -0,0 +1,514 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include + +#include "qrspec.h" +#include "qrinput.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +typedef struct { + int width; //< Edge length of the symbol + int words; //< Data capacity (bytes) + int remainder; //< Remainder bit (bits) + int ec[4]; //< Number of ECC code (bytes) +} QRspec_Capacity; + +/** + * Table of the capacity of symbols + * See Table 1 (pp.13) and Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const QRspec_Capacity qrspecCapacity[QRSPEC_VERSION_MAX + 1] = { + { 0, 0, 0, { 0, 0, 0, 0}}, + { 21, 26, 0, { 7, 10, 13, 17}}, // 1 + { 25, 44, 7, { 10, 16, 22, 28}}, + { 29, 70, 7, { 15, 26, 36, 44}}, + { 33, 100, 7, { 20, 36, 52, 64}}, + { 37, 134, 7, { 26, 48, 72, 88}}, // 5 + { 41, 172, 7, { 36, 64, 96, 112}}, + { 45, 196, 0, { 40, 72, 108, 130}}, + { 49, 242, 0, { 48, 88, 132, 156}}, + { 53, 292, 0, { 60, 110, 160, 192}}, + { 57, 346, 0, { 72, 130, 192, 224}}, //10 + { 61, 404, 0, { 80, 150, 224, 264}}, + { 65, 466, 0, { 96, 176, 260, 308}}, + { 69, 532, 0, { 104, 198, 288, 352}}, + { 73, 581, 3, { 120, 216, 320, 384}}, + { 77, 655, 3, { 132, 240, 360, 432}}, //15 + { 81, 733, 3, { 144, 280, 408, 480}}, + { 85, 815, 3, { 168, 308, 448, 532}}, + { 89, 901, 3, { 180, 338, 504, 588}}, + { 93, 991, 3, { 196, 364, 546, 650}}, + { 97, 1085, 3, { 224, 416, 600, 700}}, //20 + {101, 1156, 4, { 224, 442, 644, 750}}, + {105, 1258, 4, { 252, 476, 690, 816}}, + {109, 1364, 4, { 270, 504, 750, 900}}, + {113, 1474, 4, { 300, 560, 810, 960}}, + {117, 1588, 4, { 312, 588, 870, 1050}}, //25 + {121, 1706, 4, { 336, 644, 952, 1110}}, + {125, 1828, 4, { 360, 700, 1020, 1200}}, + {129, 1921, 3, { 390, 728, 1050, 1260}}, + {133, 2051, 3, { 420, 784, 1140, 1350}}, + {137, 2185, 3, { 450, 812, 1200, 1440}}, //30 + {141, 2323, 3, { 480, 868, 1290, 1530}}, + {145, 2465, 3, { 510, 924, 1350, 1620}}, + {149, 2611, 3, { 540, 980, 1440, 1710}}, + {153, 2761, 3, { 570, 1036, 1530, 1800}}, + {157, 2876, 0, { 570, 1064, 1590, 1890}}, //35 + {161, 3034, 0, { 600, 1120, 1680, 1980}}, + {165, 3196, 0, { 630, 1204, 1770, 2100}}, + {169, 3362, 0, { 660, 1260, 1860, 2220}}, + {173, 3532, 0, { 720, 1316, 1950, 2310}}, + {177, 3706, 0, { 750, 1372, 2040, 2430}} //40 +}; + +int QRspec_getDataLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].words - qrspecCapacity[version].ec[level]; +} + +int QRspec_getECCLength(int version, QRecLevel level) +{ + return qrspecCapacity[version].ec[level]; +} + +int QRspec_getMinimumVersion(int size, QRecLevel level) +{ + int i; + int words; + + for(i = 1; i <= QRSPEC_VERSION_MAX; i++) { + words = qrspecCapacity[i].words - qrspecCapacity[i].ec[level]; + if(words >= size) return i; + } + + return QRSPEC_VERSION_MAX; +} + +int QRspec_getWidth(int version) +{ + return qrspecCapacity[version].width; +} + +int QRspec_getRemainder(int version) +{ + return qrspecCapacity[version].remainder; +} + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +static const int lengthTableBits[4][3] = { + {10, 12, 14}, + { 9, 11, 13}, + { 8, 16, 16}, + { 8, 10, 12} +}; + +int QRspec_lengthIndicator(QRencodeMode mode, int version) +{ + int l; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + return lengthTableBits[mode][l]; +} + +int QRspec_maximumWords(QRencodeMode mode, int version) +{ + int l; + int bits; + int words; + + if(!QRinput_isSplittableMode(mode)) return 0; + if(version <= 9) { + l = 0; + } else if(version <= 26) { + l = 1; + } else { + l = 2; + } + + bits = lengthTableBits[mode][l]; + words = (1 << bits) - 1; + if(mode == QR_MODE_KANJI) { + words *= 2; // the number of bytes is required + } + + return words; +} + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Table of the error correction code (Reed-Solomon block) + * See Table 12-16 (pp.30-36), JIS X0510:2004. + */ +static const int eccTable[QRSPEC_VERSION_MAX+1][4][2] = { + {{ 0, 0}, { 0, 0}, { 0, 0}, { 0, 0}}, + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, // 1 + {{ 1, 0}, { 1, 0}, { 1, 0}, { 1, 0}}, + {{ 1, 0}, { 1, 0}, { 2, 0}, { 2, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 0}, { 4, 0}}, + {{ 1, 0}, { 2, 0}, { 2, 2}, { 2, 2}}, // 5 + {{ 2, 0}, { 4, 0}, { 4, 0}, { 4, 0}}, + {{ 2, 0}, { 4, 0}, { 2, 4}, { 4, 1}}, + {{ 2, 0}, { 2, 2}, { 4, 2}, { 4, 2}}, + {{ 2, 0}, { 3, 2}, { 4, 4}, { 4, 4}}, + {{ 2, 2}, { 4, 1}, { 6, 2}, { 6, 2}}, //10 + {{ 4, 0}, { 1, 4}, { 4, 4}, { 3, 8}}, + {{ 2, 2}, { 6, 2}, { 4, 6}, { 7, 4}}, + {{ 4, 0}, { 8, 1}, { 8, 4}, {12, 4}}, + {{ 3, 1}, { 4, 5}, {11, 5}, {11, 5}}, + {{ 5, 1}, { 5, 5}, { 5, 7}, {11, 7}}, //15 + {{ 5, 1}, { 7, 3}, {15, 2}, { 3, 13}}, + {{ 1, 5}, {10, 1}, { 1, 15}, { 2, 17}}, + {{ 5, 1}, { 9, 4}, {17, 1}, { 2, 19}}, + {{ 3, 4}, { 3, 11}, {17, 4}, { 9, 16}}, + {{ 3, 5}, { 3, 13}, {15, 5}, {15, 10}}, //20 + {{ 4, 4}, {17, 0}, {17, 6}, {19, 6}}, + {{ 2, 7}, {17, 0}, { 7, 16}, {34, 0}}, + {{ 4, 5}, { 4, 14}, {11, 14}, {16, 14}}, + {{ 6, 4}, { 6, 14}, {11, 16}, {30, 2}}, + {{ 8, 4}, { 8, 13}, { 7, 22}, {22, 13}}, //25 + {{10, 2}, {19, 4}, {28, 6}, {33, 4}}, + {{ 8, 4}, {22, 3}, { 8, 26}, {12, 28}}, + {{ 3, 10}, { 3, 23}, { 4, 31}, {11, 31}}, + {{ 7, 7}, {21, 7}, { 1, 37}, {19, 26}}, + {{ 5, 10}, {19, 10}, {15, 25}, {23, 25}}, //30 + {{13, 3}, { 2, 29}, {42, 1}, {23, 28}}, + {{17, 0}, {10, 23}, {10, 35}, {19, 35}}, + {{17, 1}, {14, 21}, {29, 19}, {11, 46}}, + {{13, 6}, {14, 23}, {44, 7}, {59, 1}}, + {{12, 7}, {12, 26}, {39, 14}, {22, 41}}, //35 + {{ 6, 14}, { 6, 34}, {46, 10}, { 2, 64}}, + {{17, 4}, {29, 14}, {49, 10}, {24, 46}}, + {{ 4, 18}, {13, 32}, {48, 14}, {42, 32}}, + {{20, 4}, {40, 7}, {43, 22}, {10, 67}}, + {{19, 6}, {18, 31}, {34, 34}, {20, 61}},//40 +}; + +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]) +{ + int b1, b2; + int data, ecc; + + b1 = eccTable[version][level][0]; + b2 = eccTable[version][level][1]; + data = QRspec_getDataLength(version, level); + ecc = QRspec_getECCLength(version, level); + + if(b2 == 0) { + spec[0] = b1; + spec[1] = data / b1; + spec[2] = ecc / b1; + spec[3] = spec[4] = 0; + } else { + spec[0] = b1; + spec[1] = data / (b1 + b2); + spec[2] = ecc / (b1 + b2); + spec[3] = b2; + spec[4] = spec[1] + 1; + } +} + +/****************************************************************************** + * Alignment pattern + *****************************************************************************/ + +/** + * Positions of alignment patterns. + * This array includes only the second and the third position of the alignment + * patterns. Rest of them can be calculated from the distance between them. + * + * See Table 1 in Appendix E (pp.71) of JIS X0510:2004. + */ +static const int alignmentPattern[QRSPEC_VERSION_MAX+1][2] = { + { 0, 0}, + { 0, 0}, {18, 0}, {22, 0}, {26, 0}, {30, 0}, // 1- 5 + {34, 0}, {22, 38}, {24, 42}, {26, 46}, {28, 50}, // 6-10 + {30, 54}, {32, 58}, {34, 62}, {26, 46}, {26, 48}, //11-15 + {26, 50}, {30, 54}, {30, 56}, {30, 58}, {34, 62}, //16-20 + {28, 50}, {26, 50}, {30, 54}, {28, 54}, {32, 58}, //21-25 + {30, 58}, {34, 62}, {26, 50}, {30, 54}, {26, 52}, //26-30 + {30, 56}, {34, 60}, {30, 58}, {34, 62}, {30, 54}, //31-35 + {24, 50}, {28, 54}, {32, 58}, {26, 54}, {30, 58}, //35-40 +}; + +/** + * Put an alignment marker. + * @param frame + * @param width + * @param ox,oy center coordinate of the pattern + */ +static void QRspec_putAlignmentMarker(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa1, 0xa0, 0xa1, + 0xa1, 0xa0, 0xa0, 0xa0, 0xa1, + 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, + }; + int x, y; + const unsigned char *s; + + frame += (oy - 2) * width + ox - 2; + s = finder; + for(y = 0; y < 5; y++) { + for(x = 0; x < 5; x++) { + frame[x] = s[x]; + } + frame += width; + s += 5; + } +} + +static void QRspec_putAlignmentPattern(int version, unsigned char *frame, int width) +{ + int d, w, x, y, cx, cy; + + if(version < 2) return; + + d = alignmentPattern[version][1] - alignmentPattern[version][0]; + if(d < 0) { + w = 2; + } else { + w = (width - alignmentPattern[version][0]) / d + 2; + } + + if(w * w - 3 == 1) { + x = alignmentPattern[version][0]; + y = alignmentPattern[version][0]; + QRspec_putAlignmentMarker(frame, width, x, y); + return; + } + + cx = alignmentPattern[version][0]; + for(x = 1; x < w - 1; x++) { + QRspec_putAlignmentMarker(frame, width, 6, cx); + QRspec_putAlignmentMarker(frame, width, cx, 6); + cx += d; + } + + cy = alignmentPattern[version][0]; + for(y = 0; y < w-1; y++) { + cx = alignmentPattern[version][0]; + for(x = 0; x < w-1; x++) { + QRspec_putAlignmentMarker(frame, width, cx, cy); + cx += d; + } + cy += d; + } +} + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Version information pattern (BCH coded). + * See Table 1 in Appendix D (pp.68) of JIS X0510:2004. + */ +static const unsigned int versionPattern[QRSPEC_VERSION_MAX - 6] = { + 0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d, + 0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9, + 0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75, + 0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64, + 0x27541, 0x28c69 +}; + +unsigned int QRspec_getVersionPattern(int version) +{ + if(version < 7 || version > QRSPEC_VERSION_MAX) return 0; + + return versionPattern[version - 7]; +} + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/* See calcFormatInfo in tests/test_qrspec.c */ +static const unsigned int formatInfo[4][8] = { + {0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976}, + {0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0}, + {0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed}, + {0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b} +}; + +unsigned int QRspec_getFormatInfo(int mask, QRecLevel level) +{ + if(mask < 0 || mask > 7) return 0; + + return formatInfo[level][mask]; +} + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Put a finder pattern. + * @param frame + * @param width + * @param ox,oy upper-left coordinate of the pattern + */ +static void putFinderPattern(unsigned char *frame, int width, int ox, int oy) +{ + static const unsigned char finder[] = { + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc1, 0xc1, 0xc1, 0xc0, 0xc1, + 0xc1, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, + 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, + }; + int x, y; + const unsigned char *s; + + frame += oy * width + ox; + s = finder; + for(y = 0; y < 7; y++) { + for(x = 0; x < 7; x++) { + frame[x] = s[x]; + } + frame += width; + s += 7; + } +} + + +static unsigned char *QRspec_createFrame(int version) +{ + unsigned char *frame, *p, *q; + int width; + int x, y; + unsigned int verinfo, v; + + width = qrspecCapacity[version].width; + frame = (unsigned char *)malloc((size_t)(width * width)); + if(frame == NULL) return NULL; + + memset(frame, 0, (size_t)(width * width)); + /* Finder pattern */ + putFinderPattern(frame, width, 0, 0); + putFinderPattern(frame, width, width - 7, 0); + putFinderPattern(frame, width, 0, width - 7); + /* Separator */ + p = frame; + q = frame + width * (width - 7); + for(y = 0; y < 7; y++) { + p[7] = 0xc0; + p[width - 8] = 0xc0; + q[7] = 0xc0; + p += width; + q += width; + } + memset(frame + width * 7, 0xc0, 8); + memset(frame + width * 8 - 8, 0xc0, 8); + memset(frame + width * (width - 8), 0xc0, 8); + /* Mask format information area */ + memset(frame + width * 8, 0x84, 9); + memset(frame + width * 9 - 8, 0x84, 8); + p = frame + 8; + for(y = 0; y < 8; y++) { + *p = 0x84; + p += width; + } + p = frame + width * (width - 7) + 8; + for(y = 0; y < 7; y++) { + *p = 0x84; + p += width; + } + /* Timing pattern */ + p = frame + width * 6 + 8; + q = frame + width * 8 + 6; + for(x = 1; x < width-15; x++) { + *p = 0x90 | (x & 1); + *q = 0x90 | (x & 1); + p++; + q += width; + } + /* Alignment pattern */ + QRspec_putAlignmentPattern(version, frame, width); + + /* Version information */ + if(version >= 7) { + verinfo = QRspec_getVersionPattern(version); + + p = frame + width * (width - 11); + v = verinfo; + for(x = 0; x < 6; x++) { + for(y = 0; y < 3; y++) { + p[width * y + x] = 0x88 | (v & 1); + v = v >> 1; + } + } + + p = frame + width - 11; + v = verinfo; + for(y = 0; y < 6; y++) { + for(x = 0; x < 3; x++) { + p[x] = 0x88 | (v & 1); + v = v >> 1; + } + p += width; + } + } + /* and a little bit... */ + frame[width * (width - 8) + 8] = 0x81; + + return frame; +} + +unsigned char *QRspec_newFrame(int version) +{ + if(version < 1 || version > QRSPEC_VERSION_MAX) return NULL; + + return QRspec_createFrame(version); +} diff --git a/src/wallet/qrencode/qrspec.h b/src/wallet/qrencode/qrspec.h new file mode 100644 index 0000000000..4d01879ed3 --- /dev/null +++ b/src/wallet/qrencode/qrspec.h @@ -0,0 +1,174 @@ +/* + * qrencode - QR Code encoder + * + * QR Code specification in convenient format. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef QRSPEC_H +#define QRSPEC_H + +#include "qrencode.h" + +/****************************************************************************** + * Version and capacity + *****************************************************************************/ + +/** + * Maximum width of a symbol + */ +#define QRSPEC_WIDTH_MAX 177 + +/** + * Return maximum data code length (bytes) for the version. + * @param version version of the symbol + * @param level error correction level + * @return maximum size (bytes) + */ +extern int QRspec_getDataLength(int version, QRecLevel level); + +/** + * Return maximum error correction code length (bytes) for the version. + * @param version version of the symbol + * @param level error correction level + * @return ECC size (bytes) + */ +extern int QRspec_getECCLength(int version, QRecLevel level); + +/** + * Return a version number that satisfies the input code length. + * @param size input code length (byte) + * @param level error correction level + * @return version number + */ +extern int QRspec_getMinimumVersion(int size, QRecLevel level); + +/** + * Return the width of the symbol for the version. + * @param version vesion of the symbol + * @return width of the symbol + */ +extern int QRspec_getWidth(int version); + +/** + * Return the numer of remainder bits. + * @param version vesion of the symbol + * @return number of remainder bits + */ +extern int QRspec_getRemainder(int version); + +/****************************************************************************** + * Length indicator + *****************************************************************************/ + +/** + * Return the size of length indicator for the mode and version. + * @param mode encode mode + * @param version vesion of the symbol + * @return the size of the appropriate length indicator (bits). + */ +extern int QRspec_lengthIndicator(QRencodeMode mode, int version); + +/** + * Return the maximum length for the mode and version. + * @param mode encode mode + * @param version vesion of the symbol + * @return the maximum length (bytes) + */ +extern int QRspec_maximumWords(QRencodeMode mode, int version); + +/****************************************************************************** + * Error correction code + *****************************************************************************/ + +/** + * Return an array of ECC specification. + * @param version version of the symbol + * @param level error correction level + * @param spec an array of ECC specification contains as following: + * {# of type1 blocks, # of data code, # of ecc code, + * # of type2 blocks, # of data code} + */ +void QRspec_getEccSpec(int version, QRecLevel level, int spec[5]); + +#define QRspec_rsBlockNum(__spec__) (__spec__[0] + __spec__[3]) +#define QRspec_rsBlockNum1(__spec__) (__spec__[0]) +#define QRspec_rsDataCodes1(__spec__) (__spec__[1]) +#define QRspec_rsEccCodes1(__spec__) (__spec__[2]) +#define QRspec_rsBlockNum2(__spec__) (__spec__[3]) +#define QRspec_rsDataCodes2(__spec__) (__spec__[4]) +#define QRspec_rsEccCodes2(__spec__) (__spec__[2]) + +#define QRspec_rsDataLength(__spec__) \ + ((QRspec_rsBlockNum1(__spec__) * QRspec_rsDataCodes1(__spec__)) + \ + (QRspec_rsBlockNum2(__spec__) * QRspec_rsDataCodes2(__spec__))) +#define QRspec_rsEccLength(__spec__) \ + (QRspec_rsBlockNum(__spec__) * QRspec_rsEccCodes1(__spec__)) + +/****************************************************************************** + * Version information pattern + *****************************************************************************/ + +/** + * Return BCH encoded version information pattern that is used for the symbol + * of version 7 or greater. Use lower 18 bits. + * @param version version of the symbol + * @return BCH encoded version information pattern + */ +extern unsigned int QRspec_getVersionPattern(int version); + +/****************************************************************************** + * Format information + *****************************************************************************/ + +/** + * Return BCH encoded format information pattern. + * @param mask mask number + * @param level error correction level + * @return BCH encoded format information pattern + */ +extern unsigned int QRspec_getFormatInfo(int mask, QRecLevel level); + +/****************************************************************************** + * Frame + *****************************************************************************/ + +/** + * Return a copy of initialized frame. + * @param version version of the symbol + * @return Array of unsigned char. You can free it by free(). + */ +extern unsigned char *QRspec_newFrame(int version); + +/****************************************************************************** + * Mode indicator + *****************************************************************************/ + +/** + * Mode indicator. See Table 2 of JIS X0510:2004, pp.16. + */ +#define QRSPEC_MODEID_ECI 7 +#define QRSPEC_MODEID_NUM 1 +#define QRSPEC_MODEID_AN 2 +#define QRSPEC_MODEID_8 4 +#define QRSPEC_MODEID_KANJI 8 +#define QRSPEC_MODEID_FNC1FIRST 5 +#define QRSPEC_MODEID_FNC1SECOND 9 +#define QRSPEC_MODEID_STRUCTURE 3 +#define QRSPEC_MODEID_TERMINATOR 0 + +#endif /* QRSPEC_H */ diff --git a/src/wallet/qrencode/rsecc.c b/src/wallet/qrencode/rsecc.c new file mode 100644 index 0000000000..b88cae3071 --- /dev/null +++ b/src/wallet/qrencode/rsecc.c @@ -0,0 +1,149 @@ +/* + * qrencode - QR Code encoder + * + * Reed solomon error correction code encoder specialized for QR code. + * This code is rewritten by Kentaro Fukuchi, referring to the FEC library + * developed by Phil Karn (KA9Q). + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * Copyright (C) 2014-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#if HAVE_LIBPTHREAD +#include +#endif + +#include "rsecc.h" + +#if HAVE_LIBPTHREAD +static pthread_mutex_t RSECC_mutex = PTHREAD_MUTEX_INITIALIZER; +#endif + +static int initialized = 0; + +#define SYMBOL_SIZE (8) +#define symbols ((1U << SYMBOL_SIZE) - 1) +static const unsigned int proot = 0x11d; /* stands for x^8+x^4+x^3+x^2+1 (see pp.37 of JIS X0510:2004) */ + +/* min/max codeword length of ECC, calculated from the specification. */ +#define min_length (2) +#define max_length (30) +#define max_generatorSize (max_length) + +static unsigned char alpha[symbols + 1]; +static unsigned char aindex[symbols + 1]; +static unsigned char generator[max_length - min_length + 1][max_generatorSize + 1]; +static unsigned char generatorInitialized[max_length - min_length + 1]; + +static void RSECC_initLookupTable(void) +{ + unsigned int i, b; + + alpha[symbols] = 0; + aindex[0] = symbols; + + b = 1; + for(i = 0; i < symbols; i++) { + alpha[i] = b; + aindex[b] = i; + b <<= 1; + if(b & (symbols + 1)) { + b ^= proot; + } + b &= symbols; + } +} + +static void RSECC_init(void) +{ + RSECC_initLookupTable(); + memset(generatorInitialized, 0, (max_length - min_length + 1)); + initialized = 1; +} + +static void generator_init(size_t length) +{ + size_t i, j; + int g[max_generatorSize + 1]; + + g[0] = 1; + for(i = 0; i < length; i++) { + g[i + 1] = 1; + /* Because g[0] never be zero, skipped some conditional checks. */ + for(j = i; j > 0; j--) { + g[j] = g[j - 1] ^ alpha[(aindex[g[j]] + i) % symbols]; + } + g[0] = alpha[(aindex[g[0]] + i) % symbols]; + } + + for(i = 0; i <= length; i++) { + generator[length - min_length][i] = aindex[g[i]]; + } + + generatorInitialized[length - min_length] = 1; +} + +int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc) +{ + size_t i, j; + unsigned char feedback; + unsigned char *gen; + +#if HAVE_LIBPTHREAD + pthread_mutex_lock(&RSECC_mutex); +#endif + if(!initialized) { + RSECC_init(); + } +#if HAVE_LIBPTHREAD + pthread_mutex_unlock(&RSECC_mutex); +#endif + + if(ecc_length > max_length) return -1; + + memset(ecc, 0, ecc_length); +#if HAVE_LIBPTHREAD + pthread_mutex_lock(&RSECC_mutex); +#endif + if(!generatorInitialized[ecc_length - min_length]) generator_init(ecc_length); +#if HAVE_LIBPTHREAD + pthread_mutex_unlock(&RSECC_mutex); +#endif + gen = generator[ecc_length - min_length]; + + for(i = 0; i < data_length; i++) { + feedback = aindex[data[i] ^ ecc[0]]; + if(feedback != symbols) { + for(j = 1; j < ecc_length; j++) { + ecc[j] ^= alpha[(unsigned int)(feedback + gen[ecc_length - j]) % symbols]; + } + } + memmove(&ecc[0], &ecc[1], ecc_length - 1); + if(feedback != symbols) { + ecc[ecc_length - 1] = alpha[(unsigned int)(feedback + gen[0]) % symbols]; + } else { + ecc[ecc_length - 1] = 0; + } + } + + return 0; +} diff --git a/src/wallet/qrencode/rsecc.h b/src/wallet/qrencode/rsecc.h new file mode 100644 index 0000000000..2c17dedb92 --- /dev/null +++ b/src/wallet/qrencode/rsecc.h @@ -0,0 +1,31 @@ +/* + * qrencode - QR Code encoder + * + * Reed solomon error correction code encoder specialized for QR code. + * This code is rewritten by Kentaro Fukuchi, referring to the FEC library + * developed by Phil Karn (KA9Q). + * + * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q + * Copyright (C) 2014-2017 Kentaro Fukuchi + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef RSECC_H +#define RSECC_H + +extern int RSECC_encode(size_t data_length, size_t ecc_length, const unsigned char *data, unsigned char *ecc); + +#endif /* RSECC_H */ diff --git a/src/wallet/qrencode/split.c b/src/wallet/qrencode/split.c new file mode 100644 index 0000000000..dca7ed2aa5 --- /dev/null +++ b/src/wallet/qrencode/split.c @@ -0,0 +1,325 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#if HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include +#include "qrencode.h" +#include "qrinput.h" +#include "qrspec.h" +#include "split.h" + +#define isdigit(__c__) ((unsigned char)((signed char)(__c__) - '0') < 10) +#define isalnum(__c__) (QRinput_lookAnTable(__c__) >= 0) + +#if !HAVE_STRDUP +#undef strdup +char *strdup(const char *s) +{ + size_t len = strlen(s) + 1; + void *newstring = malloc(len); + if(newstring == NULL) return NULL; + return (char *)memcpy(newstring, s, len); +} +#endif + +static QRencodeMode Split_identifyMode(const char *string, QRencodeMode hint) +{ + unsigned char c, d; + unsigned int word; + + c = (unsigned char)string[0]; + + if(c == '\0') return QR_MODE_NUL; + if(isdigit(c)) { + return QR_MODE_NUM; + } else if(isalnum(c)) { + return QR_MODE_AN; + } else if(hint == QR_MODE_KANJI) { + d = (unsigned char)string[1]; + if(d != '\0') { + word = ((unsigned int)c << 8) | d; + if((word >= 0x8140 && word <= 0x9ffc) || (word >= 0xe040 && word <= 0xebbf)) { + return QR_MODE_KANJI; + } + } + } + + return QR_MODE_8; +} + +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint); +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint); + +static int Split_eatNum(const char *string, QRinput *input,QRencodeMode hint) +{ + const char *p; + int ret; + int run; + int dif; + int ln; + QRencodeMode mode; + + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isdigit(*p)) { + p++; + } + run = (int)(p - string); + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_8) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + if(mode == QR_MODE_AN) { + dif = QRinput_estimateBitsModeNum(run) + 4 + ln + + QRinput_estimateBitsModeAn(1) /* + 4 + la */ + - QRinput_estimateBitsModeAn(run + 1) /* - 4 - la */; + if(dif > 0) { + return Split_eatAn(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_NUM, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatAn(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + int ret; + int run; + int dif; + int la, ln; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + + p = string; + while(isalnum(*p)) { + if(isdigit(*p)) { + q = p; + while(isdigit(*q)) { + q++; + } + dif = QRinput_estimateBitsModeAn((int)(p - string)) /* + 4 + la */ + + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln + + (isalnum(*q)?(4 + ln):0) + - QRinput_estimateBitsModeAn((int)(q - string)) /* - 4 - la */; + if(dif < 0) { + break; + } + p = q; + } else { + p++; + } + } + + run = (int)(p - string); + + if(*p && !isalnum(*p)) { + dif = QRinput_estimateBitsModeAn(run) + 4 + la + + QRinput_estimateBitsMode8(1) /* + 4 + l8 */ + - QRinput_estimateBitsMode8(run + 1) /* - 4 - l8 */; + if(dif > 0) { + return Split_eat8(string, input, hint); + } + } + + ret = QRinput_append(input, QR_MODE_AN, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eatKanji(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p; + int ret; + int run; + + p = string; + while(Split_identifyMode(p, hint) == QR_MODE_KANJI) { + p += 2; + } + run = (int)(p - string); + ret = QRinput_append(input, QR_MODE_KANJI, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_eat8(const char *string, QRinput *input, QRencodeMode hint) +{ + const char *p, *q; + QRencodeMode mode; + int ret; + int run; + int dif; + int la, ln, l8; + int swcost; + + la = QRspec_lengthIndicator(QR_MODE_AN, input->version); + ln = QRspec_lengthIndicator(QR_MODE_NUM, input->version); + l8 = QRspec_lengthIndicator(QR_MODE_8, input->version); + + p = string + 1; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + break; + } + if(mode == QR_MODE_NUM) { + q = p; + while(isdigit(*q)) { + q++; + } + if(Split_identifyMode(q, hint) == QR_MODE_8) { + swcost = 4 + l8; + } else { + swcost = 0; + } + dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */ + + QRinput_estimateBitsModeNum((int)(q - p)) + 4 + ln + + swcost + - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */; + if(dif < 0) { + break; + } + p = q; + } else if(mode == QR_MODE_AN) { + q = p; + while(isalnum(*q)) { + q++; + } + if(Split_identifyMode(q, hint) == QR_MODE_8) { + swcost = 4 + l8; + } else { + swcost = 0; + } + dif = QRinput_estimateBitsMode8((int)(p - string)) /* + 4 + l8 */ + + QRinput_estimateBitsModeAn((int)(q - p)) + 4 + la + + swcost + - QRinput_estimateBitsMode8((int)(q - string)) /* - 4 - l8 */; + if(dif < 0) { + break; + } + p = q; + } else { + p++; + } + } + + run = (int)(p - string); + ret = QRinput_append(input, QR_MODE_8, run, (unsigned char *)string); + if(ret < 0) return -1; + + return run; +} + +static int Split_splitString(const char *string, QRinput *input, + QRencodeMode hint) +{ + int length; + QRencodeMode mode; + + while(*string != '\0') { + mode = Split_identifyMode(string, hint); + if(mode == QR_MODE_NUM) { + length = Split_eatNum(string, input, hint); + } else if(mode == QR_MODE_AN) { + length = Split_eatAn(string, input, hint); + } else if(mode == QR_MODE_KANJI && hint == QR_MODE_KANJI) { + length = Split_eatKanji(string, input, hint); + } else { + length = Split_eat8(string, input, hint); + } + if(length == 0) break; + if(length < 0) return -1; + string += length; + } + + return 0; +} + +static char *dupAndToUpper(const char *str, QRencodeMode hint) +{ + char *newstr, *p; + QRencodeMode mode; + + // Changed by Libbitcoin, prevent deprecation warning. + newstr = _strdup(str); + ////newstr = strdup(str); + if(newstr == NULL) return NULL; + + p = newstr; + while(*p != '\0') { + mode = Split_identifyMode(p, hint); + if(mode == QR_MODE_KANJI) { + p += 2; + } else { + if (*p >= 'a' && *p <= 'z') { + *p = (char)((int)*p - 32); + } + p++; + } + } + + return newstr; +} + +int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive) +{ + char *newstr; + int ret; + + if(string == NULL || *string == '\0') { + errno = EINVAL; + return -1; + } + if(!casesensitive) { + newstr = dupAndToUpper(string, hint); + if(newstr == NULL) return -1; + ret = Split_splitString(newstr, input, hint); + free(newstr); + } else { + ret = Split_splitString(string, input, hint); + } + + return ret; +} diff --git a/src/wallet/qrencode/split.h b/src/wallet/qrencode/split.h new file mode 100644 index 0000000000..81829e078e --- /dev/null +++ b/src/wallet/qrencode/split.h @@ -0,0 +1,47 @@ +/* + * qrencode - QR Code encoder + * + * Input data splitter. + * Copyright (C) 2006-2017 Kentaro Fukuchi + * + * The following data / specifications are taken from + * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) + * or + * "Automatic identification and data capture techniques -- + * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef SPLIT_H +#define SPLIT_H + +#include "qrencode.h" + +/** + * Split the input string (null terminated) into QRinput. + * @param string input string + * @param hint give QR_MODE_KANJI if the input string contains Kanji character encoded in Shift-JIS. If not, give QR_MODE_8. + * @param casesensitive 0 for case-insensitive encoding (all alphabet characters are replaced to UPPER-CASE CHARACTERS. + * @retval 0 success. + * @retval -1 an error occurred. errno is set to indicate the error. See + * Exceptions for the details. + * @throw EINVAL invalid input object. + * @throw ENOMEM unable to allocate memory for input objects. + */ +extern int Split_splitStringToQRinput(const char *string, QRinput *input, + QRencodeMode hint, int casesensitive); + +#endif /* SPLIT_H */ diff --git a/test/utility/qr_code.cpp b/test/utility/qr_code.cpp deleted file mode 100644 index d73427e457..0000000000 --- a/test/utility/qr_code.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) - * - * This file is part of libbitcoin. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#include - -#include - -using namespace bc::system; - -BOOST_AUTO_TEST_SUITE(qr_code_tests) - -#ifdef WITH_QRENCODE - -// This test may be sensitive to changes in qrencode conversion formatting. -BOOST_AUTO_TEST_CASE(qr_code__encode__always__expected) -{ - ////static const data_chunk expected - ////{ - //// // TODO: generate from qrencode. - ////}; - - ////data_chunk out; - ////data_sink sink(out); - ////BOOST_REQUIRE(!qr_code::encode(sink, "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus")); - ////BOOST_REQUIRE_EQUAL(out.size(), expected.size()); - - ////// Encode as base16 so that failure message is intelligible. - ////BOOST_REQUIRE_EQUAL(encode_base16(out), encode_base16(expected)); - BOOST_REQUIRE(true); -} - -#else - -BOOST_AUTO_TEST_CASE(qr_code__encode__not_implemented__false) -{ - data_chunk out; - data_sink sink(out); - BOOST_REQUIRE(!qr_code::encode(sink, "bitcoin:1L4M4obtbpexxuKpLrDimMEYWB2Rx2yzus")); -} - -#endif // WITH_QRENCODE - -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__partial_header__empty) -{ - static const data_chunk data - { - 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00 - }; - - // Must be at least 8 bytes of data (header), so empty result (failure). - static const data_chunk expected{}; - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data)), encode_base16(expected)); -} - -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_0_margin_0__empty) -{ - static const data_chunk data - { - 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00 - }; - - // Empty image with no margin creates empty result (success). - static const data_chunk expected{}; - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 0, 0)), encode_base16(expected)); -} - -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__no_image_scale_8_margin_2__expected) -{ - static const data_chunk data - { - 0xff, 0xff, 0xff, 0xff, - 0x00, 0x00, 0x00, 0x00 - }; - - // A 2 pixel margin on an empty image creates 16 zeroed pixels. - static const data_chunk expected{ 0x00, 0x00 }; - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 8, 2)), encode_base16(expected)); -} - -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_0_margin_0__empty) -{ - static const data_chunk data - { - 0xff, 0xff, 0xff, 0xff, - 0x01, 0x00, 0x00, 0x00, - 0xff - }; - - // Scale zero creates an empty image if there is no margin specified. - static const data_chunk expected{}; - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 0, 0)), encode_base16(expected)); -} - -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_1_margin_0__expected) -{ - static const data_chunk data - { - 0xff, 0xff, 0xff, 0xff, - 0x01, 0x00, 0x00, 0x00, - - // // This pixel state is true. - 0x01 - }; - - // Scale 1 does not expand. A single pixel image with no margin creates a - // one byte image with only the most significant bit set to 1. - static const data_chunk expected{ 0x80 }; - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 1, 0)), encode_base16(expected)); -} - -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__one_pixel_scale_1_margin_1__expected) -{ - static const data_chunk data - { - 0xff, 0xff, 0xff, 0xff, - 0x01, 0x00, 0x00, 0x00, - - // This pixel state is true. - 0x01 - }; - - // Scale 1 does not expand. A single pixel image with single pixel margin - // creates a 9 pixel image with the 5th most significant bit set. - static const data_chunk expected{ 0x08, 0x00 }; - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 1, 1)), encode_base16(expected)); -} - -BOOST_AUTO_TEST_CASE(qr_code__to_image_data__four_pixel_scale_2_margin_2__expected) -{ - static const data_chunk data - { - 0xff, 0xff, 0xff, 0xff, - 0x02, 0x00, 0x00, 0x00, - - // The pixel states are true, true, false, false. - 0x01, 0xff, - 0xfe, 0xfe - }; - - // Area is 2x2px so image is scaled to 4x4px and 2px margin makes it 8x8px. - static const data_chunk expected - { - // byte pixel - 0x00, // 00 0000 00 - 0x00, // 00 0000 00 - - 0x3c, // 00 1111 00 - 0x3c, // 00 1111 00 - - 0x00, // 00 0000 00 - 0x00, // 00 0000 00 - - 0x00, // 00 0000 00 - 0x00 // 00 0000 00 - }; - - // Encode as base16 so that failure message is intelligible. - BOOST_REQUIRE_EQUAL(encode_base16(qr_code::to_image_data(data, 2, 2)), encode_base16(expected)); -} - -// TODO: determine if TIFF encoding renders bits high-to-low => left-to-right. - -BOOST_AUTO_TEST_SUITE_END() diff --git a/test/wallet/qr_code.cpp b/test/wallet/qr_code.cpp new file mode 100644 index 0000000000..1ee4297e87 --- /dev/null +++ b/test/wallet/qr_code.cpp @@ -0,0 +1,269 @@ +/** + * Copyright (c) 2011-2019 libbitcoin developers (see AUTHORS) + * + * This file is part of libbitcoin. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +#include + +#include +#include + +using namespace bc::system; +using namespace bc::system::wallet; + +BOOST_AUTO_TEST_SUITE(qr_code_tests) + +// encode + +static const uint16_t no_scale = 0u; +static const uint16_t no_margin = 0u; +static const uint8_t default_version = 0u; + +BOOST_AUTO_TEST_CASE(qr_code__encode__no_value__false) +{ + data_chunk out; + data_sink sink(out); + BOOST_REQUIRE(!qr_code::encode(sink, "")); +} + +BOOST_AUTO_TEST_CASE(qr_code__encode__excessive_character_value__false) +{ + data_chunk out; + data_sink sink(out); + + // ERANGE returned by qrencode. + std::string value(bc::max_uint16, 0x42); + BOOST_REQUIRE(!qr_code::encode(sink, value)); +} + +BOOST_AUTO_TEST_CASE(qr_code__encode__one_character_version_0_scale_1_margin_0__expected) +{ + static const data_chunk expected + { + // TIFF metadata. + 0x4d, 0x4d, 0x00, 0x2a, + 0x00, 0x00, 0x00, 0x08, + 0x00, 0x0a, 0x01, 0x00, + 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x15, 0x01, 0x01, + 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x15, 0x01, 0x03, + 0x00, 0x03, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x01, 0x06, + 0x00, 0x03, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x11, + 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x9c, 0x01, 0x16, + 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x15, 0x01, 0x17, + 0x00, 0x04, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x38, 0x01, 0x1a, + 0x00, 0x05, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x88, 0x01, 0x1b, + 0x00, 0x05, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, + 0x00, 0x90, 0x01, 0x28, + 0x00, 0x03, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x48, + 0x00, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x48, + 0x00, 0x00, 0x00, 0x01, + + // Delimiter. + 0xba, 0xad, 0xf0, 0x0d, + + // Image data. + 0xfe, 0x5b, 0xfc, 0x13, + 0x90, 0x6e, 0xb6, 0xbb, + 0x74, 0xa5, 0xdb, 0xa2, + 0xae, 0xc1, 0x05, 0x07, + 0xfa, 0xaf, 0xe0, 0x1b, + 0x00, 0xef, 0xf6, 0x21, + 0x88, 0x11, 0xaf, 0xea, + 0x22, 0x40, 0x04, 0x70, + 0xee, 0xaa, 0x80, 0x4a, + 0xab, 0xfa, 0x5d, 0xd0, + 0x57, 0xba, 0xba, 0xb7, + 0x6d, 0xd0, 0x11, 0xae, + 0xa2, 0x23, 0x05, 0xc4, + 0x7f, 0xec, 0xaa, 0x80 + }; + + data_chunk out; + data_sink sink(out); + BOOST_REQUIRE(qr_code::encode(sink, "X", default_version, 1, no_margin)); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(out), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__encode__invalid_version__false) +{ + data_chunk out; + data_sink sink(out); + + // EINVAL returned by qrencode. + BOOST_REQUIRE(!qr_code::encode(sink, "X", qr_code::maximum_version + 1u)); +} + +BOOST_AUTO_TEST_CASE(qr_code__encode__maximum_version__expected_size) +{ + data_chunk out; + data_sink sink(out); + BOOST_REQUIRE(qr_code::encode(sink, "X", qr_code::maximum_version)); + BOOST_REQUIRE_EQUAL(out.size(), 252206u); +} + +BOOST_AUTO_TEST_CASE(qr_code__encode__excessive_margin__false) +{ + data_chunk out; + data_sink sink(out); + + // At scale 0, (2 * (2^16 - 1))^2 > (2^32 - 1), the TIFF pixel limit. + BOOST_REQUIRE(!qr_code::encode(sink, "X", default_version, no_scale, bc::max_uint16)); +} + +BOOST_AUTO_TEST_CASE(qr_code__encode__excessive_scale__false) +{ + data_chunk out; + data_sink sink(out); + + // At margin 0, scaling even a single pixel to 2^16 overflows the TIFF pixel limit. + BOOST_REQUIRE(!qr_code::encode(sink, "X", default_version, bc::max_uint16, no_margin)); +} + +// to_pixels + +class qr_code_accessor + : qr_code +{ +public: + static data_chunk to_pixels(const data_chunk& coded, uint32_t coded_width, + uint16_t scale=8, uint16_t margin=2) + { + return qr_code::to_pixels(coded, coded_width, scale, margin); + } +}; + +BOOST_AUTO_TEST_CASE(qr_code__to_pixels__no_image_scale_0_margin_0__empty) +{ + // No image with no margin creates empty result (success). + static const data_chunk expected{}; + + static const data_chunk data; + const auto pixels = qr_code_accessor::to_pixels(data, 0, 0, 0); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(pixels), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_pixels__no_image_scale_8_margin_2__expected) +{ + // A 2 pixel margin on no image creates 16 zeroed pixels. + static const data_chunk expected{ 0x00, 0x00 }; + + static const data_chunk data; + const auto pixels = qr_code_accessor::to_pixels(data, 0, 8, 2); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(pixels), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_pixels__one_pixel_scale_0_margin_0__empty) +{ + // Scale zero creates a no image if there is no margin specified. + static const data_chunk expected{}; + + // This pixel state is true. + static const data_chunk data{ 0xff }; + const auto pixels = qr_code_accessor::to_pixels(data, 1, 0, 0); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(pixels), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_pixels__one_pixel_scale_1_margin_0__expected) +{ + // Scale 1 does not expand. A single pixel image with no margin creates a + // one byte image with only the most significant bit set to 1. + static const data_chunk expected{ 0x80 }; + + // This pixel state is true. + static const data_chunk data{ 0x01 }; + const auto pixels = qr_code_accessor::to_pixels(data, 1, 1, 0); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(pixels), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_pixels__one_pixel_scale_1_margin_1__expected) +{ + // Scale 1 does not expand. A single pixel image with single pixel margin + // creates a 9 pixel image with the 5th most significant bit set. + static const data_chunk expected{ 0x08, 0x00 }; + + // This pixel state is true. + static const data_chunk data{ 0x01 }; + const auto pixels = qr_code_accessor::to_pixels(data, 1, 1, 1); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(pixels), encode_base16(expected)); +} + +BOOST_AUTO_TEST_CASE(qr_code__to_pixels__four_pixels_scale_2_margin_2__expected) +{ + // Area is 2x2px so image is scaled to 4x4px and 2px margin makes it 8x8px. + static const data_chunk expected + { + // byte pixel + 0x00, // 00 0000 00 + 0x00, // 00 0000 00 + + 0x3c, // 00 1111 00 + 0x3c, // 00 1111 00 + + 0x00, // 00 0000 00 + 0x00, // 00 0000 00 + + 0x00, // 00 0000 00 + 0x00 // 00 0000 00 + }; + + // The pixel states are true, true, false, false. + static const data_chunk data + { + 0x01, 0xff, + 0xfe, 0xfe + }; + + const auto pixels = qr_code_accessor::to_pixels(data, 2, 2, 2); + + // Encode as base16 so that failure message is intelligible. + BOOST_REQUIRE_EQUAL(encode_base16(pixels), encode_base16(expected)); +} + +BOOST_AUTO_TEST_SUITE_END() From 594e34e195b3831d6aeecc9e9db4abfa018df0ca Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 17 Mar 2021 19:11:37 -0700 Subject: [PATCH 23/44] Comments. --- include/bitcoin/system/utility/tiff.hpp | 5 +++-- include/bitcoin/system/wallet/qr_code.hpp | 1 + src/wallet/qr_code.cpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/include/bitcoin/system/utility/tiff.hpp b/include/bitcoin/system/utility/tiff.hpp index f041e09818..ddfe4f6778 100644 --- a/include/bitcoin/system/utility/tiff.hpp +++ b/include/bitcoin/system/utility/tiff.hpp @@ -38,8 +38,9 @@ class BC_API tiff /// (((2^16) - 1)^2 + 7)/ 8 = 536,854,529 or 0x1fffc001 bytes. static uint32_t max_image_bytes; - - /// Data size must be (width^2 + 7) / 8. Last byte may be buffered. + + /// False if width parameter is inconsistent with data size. + /// Data size must be (width^2 + 7) / 8. Last byte padded as necessary. static bool to_image(std::ostream& out, const data_chunk& data, uint16_t width); }; diff --git a/include/bitcoin/system/wallet/qr_code.hpp b/include/bitcoin/system/wallet/qr_code.hpp index 71afd06906..122dfefa55 100644 --- a/include/bitcoin/system/wallet/qr_code.hpp +++ b/include/bitcoin/system/wallet/qr_code.hpp @@ -54,6 +54,7 @@ class BC_API qr_code static uint8_t maximum_version; + /// False if version > maximum_version or size > tiff::max_image_bytes. /// Create a TIFF formatter QR code representing the given string value. static bool encode(std::ostream& out, const std::string& value, uint8_t version=0, uint16_t scale=8, uint16_t margin=2, diff --git a/src/wallet/qr_code.cpp b/src/wallet/qr_code.cpp index a961b0e50e..1e286b789f 100644 --- a/src/wallet/qr_code.cpp +++ b/src/wallet/qr_code.cpp @@ -109,7 +109,7 @@ bool qr_code::encode(std::ostream& out, const std::string& value, recovery_level_to_qr_recovery_level(level), encode_mode_to_qr_encode_mode(mode), case_sensitive); - // Empty or excessive value returns null pointer. + // Empty or excessive value string length returns null pointer. if (qrcode == nullptr) return false; From 48e5c1b99d340a1bc3c5b112ee7e246c71535503 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Wed, 17 Mar 2021 19:15:07 -0700 Subject: [PATCH 24/44] Drop qrencode, png and zlib dependencies. --- .travis.yml | 6 ++-- Makefile.am | 12 +++---- builds/cmake/CMakeLists.txt | 52 +-------------------------- configure.ac | 72 ------------------------------------- install.sh | 60 ------------------------------- libbitcoin-system.pc.in | 4 +-- 6 files changed, 12 insertions(+), 194 deletions(-) diff --git a/.travis.yml b/.travis.yml index 932ebc5f1f..aa8c2c47cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -77,9 +77,9 @@ install: script: # Download and build libbitcoin-system and all dependencies. - - if [[ $OSX && $CLANG && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --with-icu --with-png --with-qrencode --build-icu --build-zlib --build-png --build-qrencode --build-boost --disable-shared --prefix=$TRAVIS_BUILD_DIR/my-prefix; fi - - if [[ $LINUX && $CLANG && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --with-icu --with-png --with-qrencode --build-icu --build-zlib --build-png --build-qrencode --build-boost --disable-shared --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os' CXXFLAGS='-Os'; fi - - if [[ $LINUX && $GCC && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --with-icu --with-png --with-qrencode --build-icu --build-zlib --build-png --build-qrencode --build-boost --disable-shared --build-dir=my-build --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Og -g --coverage' CXXFLAGS='-Og -g --coverage'; fi + - if [[ $OSX && $CLANG && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --with-icu --build-icu --build-boost --disable-shared --prefix=$TRAVIS_BUILD_DIR/my-prefix; fi + - if [[ $LINUX && $CLANG && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --with-icu --build-icu --build-boost --disable-shared --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os' CXXFLAGS='-Os'; fi + - if [[ $LINUX && $GCC && $STATIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --with-icu --build-icu --build-boost --disable-shared --build-dir=my-build --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Og -g --coverage' CXXFLAGS='-Og -g --coverage'; fi - if [[ $OSX && $CLANG && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --disable-static; fi - if [[ $LINUX && $CLANG && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --with-icu --build-icu --build-boost --disable-ndebug --disable-static --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os' CXXFLAGS='-Os'; fi - if [[ $LINUX && $GCC && $DYNAMIC ]]; then CC=$CC CXX=$CXX ./install.sh --enable-isystem --disable-static --build-boost --prefix=$TRAVIS_BUILD_DIR/my-prefix CFLAGS='-Os -s' CXXFLAGS='-Os -s'; fi diff --git a/Makefile.am b/Makefile.am index 50abdd849c..66894fffc3 100755 --- a/Makefile.am +++ b/Makefile.am @@ -32,9 +32,9 @@ doc_DATA = \ # src/libbitcoin-system.la => ${libdir} #------------------------------------------------------------------------------ lib_LTLIBRARIES = src/libbitcoin-system.la -src_libbitcoin_system_la_CPPFLAGS = -I${srcdir}/include ${icu} ${png} ${qrencode} ${boost_BUILD_CPPFLAGS} ${pthread_BUILD_CPPFLAGS} ${icu_i18n_BUILD_CPPFLAGS} ${png_BUILD_CPPFLAGS} ${qrencode_BUILD_CPPFLAGS} ${secp256k1_BUILD_CPPFLAGS} +src_libbitcoin_system_la_CPPFLAGS = -I${srcdir}/include ${icu} ${boost_BUILD_CPPFLAGS} ${pthread_BUILD_CPPFLAGS} ${icu_i18n_BUILD_CPPFLAGS} ${secp256k1_BUILD_CPPFLAGS} src_libbitcoin_system_la_LDFLAGS = ${boost_LDFLAGS} -src_libbitcoin_system_la_LIBADD = ${boost_chrono_LIBS} ${boost_date_time_LIBS} ${boost_filesystem_LIBS} ${boost_iostreams_LIBS} ${boost_locale_LIBS} ${boost_log_LIBS} ${boost_program_options_LIBS} ${boost_regex_LIBS} ${boost_system_LIBS} ${boost_thread_LIBS} ${pthread_LIBS} ${rt_LIBS} ${icu_i18n_LIBS} ${dl_LIBS} ${png_LIBS} ${qrencode_LIBS} ${secp256k1_LIBS} +src_libbitcoin_system_la_LIBADD = ${boost_chrono_LIBS} ${boost_date_time_LIBS} ${boost_filesystem_LIBS} ${boost_iostreams_LIBS} ${boost_locale_LIBS} ${boost_log_LIBS} ${boost_program_options_LIBS} ${boost_regex_LIBS} ${boost_system_LIBS} ${boost_thread_LIBS} ${pthread_LIBS} ${rt_LIBS} ${icu_i18n_LIBS} ${dl_LIBS} ${secp256k1_LIBS} src_libbitcoin_system_la_SOURCES = \ src/error.cpp \ src/settings.cpp \ @@ -270,9 +270,9 @@ src_libbitcoin_system_la_SOURCES = \ if WITH_EXAMPLES noinst_PROGRAMS = examples/libbitcoin-system-examples -examples_libbitcoin_system_examples_CPPFLAGS = -I${srcdir}/include ${icu} ${png} ${qrencode} ${boost_BUILD_CPPFLAGS} ${pthread_BUILD_CPPFLAGS} ${icu_i18n_BUILD_CPPFLAGS} ${png_BUILD_CPPFLAGS} ${qrencode_BUILD_CPPFLAGS} ${secp256k1_BUILD_CPPFLAGS} +examples_libbitcoin_system_examples_CPPFLAGS = -I${srcdir}/include ${icu} ${boost_BUILD_CPPFLAGS} ${pthread_BUILD_CPPFLAGS} ${icu_i18n_BUILD_CPPFLAGS} ${secp256k1_BUILD_CPPFLAGS} examples_libbitcoin_system_examples_LDFLAGS = ${boost_LDFLAGS} -examples_libbitcoin_system_examples_LDADD = src/libbitcoin-system.la ${boost_chrono_LIBS} ${boost_date_time_LIBS} ${boost_filesystem_LIBS} ${boost_iostreams_LIBS} ${boost_locale_LIBS} ${boost_log_LIBS} ${boost_program_options_LIBS} ${boost_regex_LIBS} ${boost_system_LIBS} ${boost_thread_LIBS} ${pthread_LIBS} ${rt_LIBS} ${icu_i18n_LIBS} ${dl_LIBS} ${png_LIBS} ${qrencode_LIBS} ${secp256k1_LIBS} +examples_libbitcoin_system_examples_LDADD = src/libbitcoin-system.la ${boost_chrono_LIBS} ${boost_date_time_LIBS} ${boost_filesystem_LIBS} ${boost_iostreams_LIBS} ${boost_locale_LIBS} ${boost_log_LIBS} ${boost_program_options_LIBS} ${boost_regex_LIBS} ${boost_system_LIBS} ${boost_thread_LIBS} ${pthread_LIBS} ${rt_LIBS} ${icu_i18n_LIBS} ${dl_LIBS} ${secp256k1_LIBS} examples_libbitcoin_system_examples_SOURCES = \ examples/main.cpp @@ -285,9 +285,9 @@ if WITH_TESTS TESTS = libbitcoin-system-test_runner.sh check_PROGRAMS = test/libbitcoin-system-test -test_libbitcoin_system_test_CPPFLAGS = -I${srcdir}/include ${icu} ${png} ${qrencode} ${boost_BUILD_CPPFLAGS} ${pthread_BUILD_CPPFLAGS} ${icu_i18n_BUILD_CPPFLAGS} ${png_BUILD_CPPFLAGS} ${qrencode_BUILD_CPPFLAGS} ${secp256k1_BUILD_CPPFLAGS} +test_libbitcoin_system_test_CPPFLAGS = -I${srcdir}/include ${icu} ${boost_BUILD_CPPFLAGS} ${pthread_BUILD_CPPFLAGS} ${icu_i18n_BUILD_CPPFLAGS} ${secp256k1_BUILD_CPPFLAGS} test_libbitcoin_system_test_LDFLAGS = ${boost_LDFLAGS} -test_libbitcoin_system_test_LDADD = src/libbitcoin-system.la ${boost_unit_test_framework_LIBS} ${boost_chrono_LIBS} ${boost_date_time_LIBS} ${boost_filesystem_LIBS} ${boost_iostreams_LIBS} ${boost_locale_LIBS} ${boost_log_LIBS} ${boost_program_options_LIBS} ${boost_regex_LIBS} ${boost_system_LIBS} ${boost_thread_LIBS} ${pthread_LIBS} ${rt_LIBS} ${icu_i18n_LIBS} ${dl_LIBS} ${png_LIBS} ${qrencode_LIBS} ${secp256k1_LIBS} +test_libbitcoin_system_test_LDADD = src/libbitcoin-system.la ${boost_unit_test_framework_LIBS} ${boost_chrono_LIBS} ${boost_date_time_LIBS} ${boost_filesystem_LIBS} ${boost_iostreams_LIBS} ${boost_locale_LIBS} ${boost_log_LIBS} ${boost_program_options_LIBS} ${boost_regex_LIBS} ${boost_system_LIBS} ${boost_thread_LIBS} ${pthread_LIBS} ${rt_LIBS} ${icu_i18n_LIBS} ${dl_LIBS} ${secp256k1_LIBS} test_libbitcoin_system_test_SOURCES = \ test/main.cpp \ test/overloads.cpp \ diff --git a/builds/cmake/CMakeLists.txt b/builds/cmake/CMakeLists.txt index ce96f31872..46ca2dda84 100644 --- a/builds/cmake/CMakeLists.txt +++ b/builds/cmake/CMakeLists.txt @@ -97,22 +97,6 @@ if (with-icu) set( icu "-DWITH_ICU" ) endif() -# Implement -Dwith-png and output ${png}. -#------------------------------------------------------------------------------ -set( with-png "no" CACHE BOOL "Compile with Libpng support." ) - -if (with-png) - set( png "-DWITH_PNG" ) -endif() - -# Implement -Dwith-qrencode and output ${qrencode}. -#------------------------------------------------------------------------------ -set( with-qrencode "no" CACHE BOOL "Compile with QREncode." ) - -if (with-qrencode) - set( qrencode "-DWITH_QRENCODE" ) -endif() - # Implement -Denable-ndebug and define NDEBUG. #------------------------------------------------------------------------------ set( enable-ndebug "yes" CACHE BOOL "Compile without debug assertions." ) @@ -201,18 +185,6 @@ if ((${CMAKE_SYSTEM_NAME} MATCHES "Linux")) find_package( Dl REQUIRED ) endif() -# Find png -#------------------------------------------------------------------------------ -if (with-png) - find_package( Png 1.6.37 REQUIRED ) -endif() - -# Find qrencode -#------------------------------------------------------------------------------ -if (with-qrencode) - find_package( Qrencode 4.1.1 REQUIRED ) -endif() - # Find secp256k1 #------------------------------------------------------------------------------ find_package( Secp256K1 0.1.0.19 REQUIRED ) @@ -226,8 +198,6 @@ if (BUILD_SHARED_LIBS) ${rt_INCLUDE_DIRS} ${icu_i18n_INCLUDE_DIRS} ${dl_INCLUDE_DIRS} - ${png_INCLUDE_DIRS} - ${qrencode_INCLUDE_DIRS} ${secp256k1_INCLUDE_DIRS} ) else() include_directories( SYSTEM @@ -236,8 +206,6 @@ else() ${rt_INCLUDE_DIRS} ${icu_i18n_STATIC_INCLUDE_DIRS} ${dl_INCLUDE_DIRS} - ${png_STATIC_INCLUDE_DIRS} - ${qrencode_STATIC_INCLUDE_DIRS} ${secp256k1_STATIC_INCLUDE_DIRS} ) endif() @@ -250,8 +218,6 @@ if (BUILD_SHARED_LIBS) ${rt_LIBRARY_DIRS} ${icu_i18n_LIBRARY_DIRS} ${dl_LIBRARY_DIRS} - ${png_LIBRARY_DIRS} - ${qrencode_LIBRARY_DIRS} ${secp256k1_LIBRARY_DIRS} ) else() link_directories( @@ -260,8 +226,6 @@ else() ${rt_LIBRARY_DIRS} ${icu_i18n_STATIC_LIBRARY_DIRS} ${dl_LIBRARY_DIRS} - ${png_STATIC_LIBRARY_DIRS} - ${qrencode_STATIC_LIBRARY_DIRS} ${secp256k1_STATIC_LIBRARY_DIRS} ) endif() @@ -285,8 +249,6 @@ if (BUILD_SHARED_LIBS) ${rt_LIBRARIES} ${icu_i18n_LIBRARIES} ${dl_LIBRARIES} - ${png_LIBRARIES} - ${qrencode_LIBRARIES} ${secp256k1_LIBRARIES} ) else() link_libraries( @@ -306,15 +268,11 @@ else() ${rt_LIBRARIES} ${icu_i18n_STATIC_LIBRARIES} ${dl_LIBRARIES} - ${png_STATIC_LIBRARIES} - ${qrencode_STATIC_LIBRARIES} ${secp256k1_STATIC_LIBRARIES} ) endif() add_definitions( - ${icu} - ${png} - ${qrencode} ) + ${icu} ) # Define ${CANONICAL_LIB_NAME} project. #------------------------------------------------------------------------------ @@ -558,8 +516,6 @@ if (BUILD_SHARED_LIBS) ${rt_INCLUDE_DIRS} ${icu_i18n_INCLUDE_DIRS} ${dl_INCLUDE_DIRS} - ${png_INCLUDE_DIRS} - ${qrencode_INCLUDE_DIRS} ${secp256k1_INCLUDE_DIRS} ) else() target_include_directories( ${CANONICAL_LIB_NAME} PRIVATE @@ -569,8 +525,6 @@ else() ${rt_INCLUDE_DIRS} ${icu_i18n_STATIC_INCLUDE_DIRS} ${dl_INCLUDE_DIRS} - ${png_STATIC_INCLUDE_DIRS} - ${qrencode_STATIC_INCLUDE_DIRS} ${secp256k1_STATIC_INCLUDE_DIRS} ) endif() @@ -595,8 +549,6 @@ if (BUILD_SHARED_LIBS) ${rt_LIBRARIES} ${icu_i18n_LIBRARIES} ${dl_LIBRARIES} - ${png_LIBRARIES} - ${qrencode_LIBRARIES} ${secp256k1_LIBRARIES} ) else() target_link_libraries( ${CANONICAL_LIB_NAME} @@ -614,8 +566,6 @@ else() ${rt_LIBRARIES} ${icu_i18n_STATIC_LIBRARIES} ${dl_LIBRARIES} - ${png_STATIC_LIBRARIES} - ${qrencode_STATIC_LIBRARIES} ${secp256k1_STATIC_LIBRARIES} ) endif() diff --git a/configure.ac b/configure.ac index fb32819ebb..bb8a8205a6 100644 --- a/configure.ac +++ b/configure.ac @@ -121,28 +121,6 @@ AC_MSG_RESULT([$with_icu]) AS_CASE([${with_icu}], [yes], AC_DEFINE([BOOST_HAS_ICU])) AS_CASE([${with_icu}], [yes], AC_SUBST([icu], [-DWITH_ICU])) -# Implement --with-png and output ${png}. -#------------------------------------------------------------------------------ -AC_MSG_CHECKING([--with-png option]) -AC_ARG_WITH([png], - AS_HELP_STRING([--with-png], - [Compile with Libpng support. @<:@default=no@:>@]), - [with_png=$withval], - [with_png=no]) -AC_MSG_RESULT([$with_png]) -AS_CASE([${with_png}], [yes], AC_SUBST([png], [-DWITH_PNG])) - -# Implement --with-qrencode and output ${qrencode}. -#------------------------------------------------------------------------------ -AC_MSG_CHECKING([--with-qrencode option]) -AC_ARG_WITH([qrencode], - AS_HELP_STRING([--with-qrencode], - [Compile with QREncode. @<:@default=no@:>@]), - [with_qrencode=$withval], - [with_qrencode=no]) -AC_MSG_RESULT([$with_qrencode]) -AS_CASE([${with_qrencode}], [yes], AC_SUBST([qrencode], [-DWITH_QRENCODE])) - # Implement --enable-ndebug and define NDEBUG. #------------------------------------------------------------------------------ AC_MSG_CHECKING([--enable-ndebug option]) @@ -312,56 +290,6 @@ AS_CASE([${host_os}], AC_MSG_NOTICE([dl_LIBS : ${dl_LIBS}]) -# Require png of at least version 1.6.37 and output ${png_CPPFLAGS/LIBS/PKG}. -#------------------------------------------------------------------------------ -AS_CASE([${with_png}], [yes], - [PKG_CHECK_MODULES([png], [libpng >= 1.6.37], - [png_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libpng >= 1.6.37" 2>/dev/null`" - png_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libpng >= 1.6.37" 2>/dev/null`"], - [AC_MSG_ERROR([--with-png specified but libpng >= 1.6.37 was not found.])]) - AC_SUBST([png_PKG], ['libpng >= 1.6.37']) - AC_SUBST([png_CPPFLAGS], [${png_CFLAGS}]) - AS_IF([test x${png_INCLUDEDIR} != "x"], - [AC_SUBST([png_ISYS_CPPFLAGS], ["-isystem${png_INCLUDEDIR} ${png_OTHER_CFLAGS}"])], - [AC_SUBST([png_ISYS_CPPFLAGS], [${png_OTHER_CFLAGS}])]) - AC_MSG_NOTICE([png_CPPFLAGS : ${png_CPPFLAGS}]) - AC_MSG_NOTICE([png_ISYS_CPPFLAGS : ${png_ISYS_CPPFLAGS}]) - AC_MSG_NOTICE([png_OTHER_CFLAGS : ${png_OTHER_CFLAGS}]) - AC_MSG_NOTICE([png_INCLUDEDIR : ${png_INCLUDEDIR}]) - AC_MSG_NOTICE([png_LIBS : ${png_LIBS}])], - [AC_SUBST([png_PKG], [])]) - -AS_CASE([${enable_isystem}],[yes], - [AC_SUBST([png_BUILD_CPPFLAGS], [${png_ISYS_CPPFLAGS}])], - [AC_SUBST([png_BUILD_CPPFLAGS], [${png_CPPFLAGS}])]) - -AC_MSG_NOTICE([png_BUILD_CPPFLAGS : ${png_BUILD_CPPFLAGS}]) - -# Require qrencode of at least version 4.1.1 and output ${qrencode_CPPFLAGS/LIBS/PKG}. -#------------------------------------------------------------------------------ -AS_CASE([${with_qrencode}], [yes], - [PKG_CHECK_MODULES([qrencode], [libqrencode >= 4.1.1], - [qrencode_INCLUDEDIR="`$PKG_CONFIG --variable=includedir "libqrencode >= 4.1.1" 2>/dev/null`" - qrencode_OTHER_CFLAGS="`$PKG_CONFIG --cflags-only-other "libqrencode >= 4.1.1" 2>/dev/null`"], - [AC_MSG_ERROR([--with-qrencode specified but libqrencode >= 4.1.1 was not found.])]) - AC_SUBST([qrencode_PKG], ['libqrencode >= 4.1.1']) - AC_SUBST([qrencode_CPPFLAGS], [${qrencode_CFLAGS}]) - AS_IF([test x${qrencode_INCLUDEDIR} != "x"], - [AC_SUBST([qrencode_ISYS_CPPFLAGS], ["-isystem${qrencode_INCLUDEDIR} ${qrencode_OTHER_CFLAGS}"])], - [AC_SUBST([qrencode_ISYS_CPPFLAGS], [${qrencode_OTHER_CFLAGS}])]) - AC_MSG_NOTICE([qrencode_CPPFLAGS : ${qrencode_CPPFLAGS}]) - AC_MSG_NOTICE([qrencode_ISYS_CPPFLAGS : ${qrencode_ISYS_CPPFLAGS}]) - AC_MSG_NOTICE([qrencode_OTHER_CFLAGS : ${qrencode_OTHER_CFLAGS}]) - AC_MSG_NOTICE([qrencode_INCLUDEDIR : ${qrencode_INCLUDEDIR}]) - AC_MSG_NOTICE([qrencode_LIBS : ${qrencode_LIBS}])], - [AC_SUBST([qrencode_PKG], [])]) - -AS_CASE([${enable_isystem}],[yes], - [AC_SUBST([qrencode_BUILD_CPPFLAGS], [${qrencode_ISYS_CPPFLAGS}])], - [AC_SUBST([qrencode_BUILD_CPPFLAGS], [${qrencode_CPPFLAGS}])]) - -AC_MSG_NOTICE([qrencode_BUILD_CPPFLAGS : ${qrencode_BUILD_CPPFLAGS}]) - # Require secp256k1 of at least version 0.1.0.19 and output ${secp256k1_CPPFLAGS/LIBS/PKG}. #------------------------------------------------------------------------------ PKG_CHECK_MODULES([secp256k1], [libsecp256k1 >= 0.1.0.19], diff --git a/install.sh b/install.sh index 43f286a97a..f30b86e8e9 100755 --- a/install.sh +++ b/install.sh @@ -17,23 +17,7 @@ # accesses this feature, so if you do not intend to # use passphrase normalization this dependency can # be avoided. -# --with-png Compile with QR Code PNG Output Support -# Since the addition of png support, libbitcoin -# conditionally incorporates libpng (which in turn -# requires zlib). Currently libbitcoin-explorer is -# the only other library that accesses this feature, -# so if you do not intend to use png this dependency -# can be avoided. -# --with-qrencode Compile with QR Code Support -# Since the addition of qrcode support, libbitcoin -# conditionally incorporates qrencode. Currently -# libbitcoin-explorer is the only other library that -# accesses this feature, so if you do not intend to -# use qrcode this dependency can be avoided. # --build-icu Builds ICU libraries. -# --build-zlib Builds ZLib libraries. -# --build-png Builds PNG libraries. -# --build-qrencode Builds QREncode libraries. # --build-boost Builds Boost libraries. # --build-dir= Location of downloaded and intermediate files. # --prefix= Library install location (defaults to /usr/local). @@ -62,21 +46,6 @@ BUILD_DIR="build-libbitcoin-system" ICU_URL="https://github.com/unicode-org/icu/releases/download/release-55-2/icu4c-55_2-src.tgz" ICU_ARCHIVE="icu4c-55_2-src.tgz" -# ZLib archive. -#------------------------------------------------------------------------------ -ZLIB_URL="https://github.com/madler/zlib/archive/v1.2.11.tar.gz" -ZLIB_ARCHIVE="v1.2.11.tar.gz" - -# PNG archive. -#------------------------------------------------------------------------------ -PNG_URL="https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz" -PNG_ARCHIVE="libpng-1.6.37.tar.xz" - -# QREncode archive. -#------------------------------------------------------------------------------ -QRENCODE_URL="http://fukuchi.org/works/qrencode/qrencode-4.1.1.tar.bz2" -QRENCODE_ARCHIVE="qrencode-4.1.1.tar.bz2" - # Boost archive. #------------------------------------------------------------------------------ BOOST_URL="http://downloads.sourceforge.net/project/boost/boost/1.72.0/boost_1_72_0.tar.bz2" @@ -225,23 +194,7 @@ display_help() display_message " accesses this feature, so if you do not intend to " display_message " use passphrase normalization this dependency can " display_message " be avoided." - display_message " --with-png Compile with QR Code PNG Output Support" - display_message " Since the addition of png support, libbitcoin " - display_message " conditionally incorporates libpng (which in turn " - display_message " requires zlib). Currently libbitcoin-explorer is " - display_message " the only other library that accesses this feature, " - display_message " so if you do not intend to use png this dependency " - display_message " can be avoided." - display_message " --with-qrencode Compile with QR Code Support" - display_message " Since the addition of qrcode support, libbitcoin " - display_message " conditionally incorporates qrencode. Currently " - display_message " libbitcoin-explorer is the only other library that " - display_message " accesses this feature, so if you do not intend to " - display_message " use qrcode this dependency can be avoided." display_message " --build-icu Builds ICU libraries." - display_message " --build-zlib Builds ZLib libraries." - display_message " --build-png Builds PNG libraries." - display_message " --build-qrencode Builds QREncode libraries." display_message " --build-boost Builds Boost libraries." display_message " --build-dir= Location of downloaded and intermediate files." display_message " --prefix= Library install location (defaults to /usr/local)." @@ -269,14 +222,9 @@ parse_command_line_options() # Common project options. (--with-icu) WITH_ICU="yes";; - (--with-png) WITH_PNG="yes";; - (--with-qrencode) WITH_QRENCODE="yes";; # Custom build options (in the form of --build- \ No newline at end of file + From 1636c9287b8fe5634a97bb187e20534fcd3898c5 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 05:24:02 -0700 Subject: [PATCH 36/44] Remove qrencode, png and zlib dependencies. --- install.sh | 50 +------------------------------------------------- 1 file changed, 1 insertion(+), 49 deletions(-) diff --git a/install.sh b/install.sh index f30b86e8e9..0090a0754a 100755 --- a/install.sh +++ b/install.sh @@ -456,26 +456,6 @@ initialize_icu_packages() fi } -# Because ZLIB doesn't actually parse its --disable-shared option. -# Because ZLIB doesn't follow GNU recommentation for unknown arguments. -patch_zlib_configuration() -{ - sed -i.tmp "s/leave 1/shift/" configure - sed -i.tmp "s/--static/--static | --disable-shared/" configure - sed -i.tmp "/unknown option/d" configure - sed -i.tmp "/help for help/d" configure - - # display_message "Hack: ZLIB configuration options modified." -} - -# Because ZLIB can't build shared only. -clean_zlib_build() -{ - if [[ $DISABLE_STATIC ]]; then - rm --force "$PREFIX/lib/libz.a" - fi -} - # Standard build from tarball. build_from_tarball() { @@ -496,19 +476,12 @@ build_from_tarball() return fi - # Because libpng doesn't actually use pkg-config to locate zlib. # Because ICU tools don't know how to locate internal dependencies. - if [[ ($ARCHIVE == "$ICU_ARCHIVE") || ($ARCHIVE == "$PNG_ARCHIVE") ]]; then + if [[ ($ARCHIVE == "$ICU_ARCHIVE") ]]; then local SAVE_LDFLAGS="$LDFLAGS" export LDFLAGS="-L$PREFIX/lib $LDFLAGS" fi - # Because libpng doesn't actually use pkg-config to locate zlib.h. - if [[ ($ARCHIVE == "$PNG_ARCHIVE") ]]; then - local SAVE_CPPFLAGS="$CPPFLAGS" - export CPPFLAGS="-I$PREFIX/include $CPPFLAGS" - fi - display_heading_message "Download $ARCHIVE" # Use the suffixed archive name as the extraction directory. @@ -522,11 +495,6 @@ build_from_tarball() tar --extract --file "$ARCHIVE" "--$COMPRESSION" --strip-components=1 push_directory "$PUSH_DIR" - # Enable static only zlib build. - if [[ $ARCHIVE == "$ZLIB_ARCHIVE" ]]; then - patch_zlib_configuration - fi - # Join generated and command line options. local CONFIGURATION=("${OPTIONS[@]}" "$@") @@ -541,11 +509,6 @@ build_from_tarball() configure_links - # Enable shared only zlib build. - if [[ $ARCHIVE == "$ZLIB_ARCHIVE" ]]; then - clean_zlib_build - fi - pop_directory pop_directory @@ -667,8 +630,6 @@ build_from_tarball_boost() display_message "-sNO_BZIP2 : 1" display_message "-sICU_PATH : $ICU_PREFIX" # display_message "-sICU_LINK : " "${ICU_LIBS[*]}" - display_message "-sZLIB_LIBPATH : $PREFIX/lib" - display_message "-sZLIB_INCLUDE : $PREFIX/include" display_message "-j : $JOBS" display_message "-d0 : [supress informational messages]" display_message "-q : [stop at the first error]" @@ -681,13 +642,6 @@ build_from_tarball_boost() "--prefix=$PREFIX" \ "--with-icu=$ICU_PREFIX" - # boost_iostreams: - # The zlib options prevent boost linkage to system libs in the case where - # we have built zlib in a prefix dir. Disabling zlib in boost is broken in - # all versions (through 1.61). There has been a patch pull request since - # 2015 but not merged as of 3/5/2021. svn.boost.org/trac/boost/ticket/9156 - # The bzip2 auto-detection is not implemented, but disabling it works. - # boost_regex: # As of boost 1.72.0 the ICU_LINK symbol is no longer supported and # produces a hard stop if WITH_ICU is also defined. Removal is sufficient. @@ -705,8 +659,6 @@ build_from_tarball_boost() "boost.locale.posix=$BOOST_ICU_POSIX" \ "-sNO_BZIP2=1" \ "-sICU_PATH=$ICU_PREFIX" \ - "-sZLIB_LIBPATH=$PREFIX/lib" \ - "-sZLIB_INCLUDE=$PREFIX/include" \ "-j $JOBS" \ "-d0" \ "-q" \ From 6c6a4741321743a0e77dc7c8560d46b9b9bf1866 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 13:41:08 -0700 Subject: [PATCH 37/44] Optimize qr_code::encode. --- include/bitcoin/system/wallet/qr_code.hpp | 2 +- src/wallet/qr_code.cpp | 84 ++++++++++++----------- 2 files changed, 46 insertions(+), 40 deletions(-) diff --git a/include/bitcoin/system/wallet/qr_code.hpp b/include/bitcoin/system/wallet/qr_code.hpp index c47bbd3255..9ecf6df1f0 100644 --- a/include/bitcoin/system/wallet/qr_code.hpp +++ b/include/bitcoin/system/wallet/qr_code.hpp @@ -63,7 +63,7 @@ class BC_API qr_code protected: /// Convert QR encoded data stream to bit stream with margin and scaling. - static data_chunk to_pixels(const data_chunk& coded, uint32_t coded_width, + static data_chunk to_pixels(const data_chunk& coded, uint32_t width_coded, uint16_t scale=8, uint16_t margin=2); }; diff --git a/src/wallet/qr_code.cpp b/src/wallet/qr_code.cpp index 79f32e7fb9..0b645c572d 100644 --- a/src/wallet/qr_code.cpp +++ b/src/wallet/qr_code.cpp @@ -119,14 +119,14 @@ bool qr_code::encode(std::ostream& out, const std::string& value, // Bound: 2^1 * 2^16 + 2^32 < 2^64. const auto pixel_width = uint64_t{ 2u } * margin + scale * qrcode->width; - // Guard against TIFF parameter overflow. + // Guard: TIFF parameter overflow. if (pixel_width > max_uint16) return safe_free_and_return(qrcode, false); - // Bound: (2^32 - 1)^2 < (2^64 - 1). + // Bound: (2^32 - 1)^2 < 2^64. const auto data_area = qrcode->width * static_cast(qrcode->width); - // Guard against data_chunk overflow (32 bit builds). + // Guard: data_chunk overflow (32 bit builds). if (data_area > max_size_t) return safe_free_and_return(qrcode, false); @@ -146,34 +146,44 @@ bool qr_code::encode(std::ostream& out, const std::string& value, // pixel_width = 2 * margin + scale * coded_width. // The result may be up to max_size_t, which exceeds the TIFF limit of 2^32 // when size_t is 2^64. Caller can optimize a failure by guarding pixel_width. -data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t coded_width, +data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t width_coded, uint16_t scale, uint16_t margin) { - // Bound: (2^32 - 1)^2 < (2^64 - 1). - // Guard against mismatched sizes from qrencode. - if (coded.size() != coded_width * static_cast(coded_width)) + // Pixel is the least significant bit of a qrencode byte. + constexpr auto pixel_mask = uint8_t{ 0x01 }; + constexpr auto pixels_off = uint8_t{ 0x00 }; + constexpr auto pixel_off = false; + + // For readability (image is always square). + const auto height_coded = width_coded; + + // Bound: (2^32 - 1)^2 < 2^64. + const auto size = width_coded * height_coded; + + // Guard: mismatched sizes. + if (coded.size() != size) return {}; // Bound: 2^16 * 2^32 < 2^48 < 2^64. - const auto scaled_width = scale * static_cast(coded_width); + const auto width_scaled = scale * static_cast(width_coded); - // Bound: 2^48 + 2 * 2^16 < 2^48 + 2^17 < 2 * 2^48 < 2^64. - const auto pixel_width = (margin + scaled_width + margin); + // Bound: 2^48 + 2^1 * 2^16 < 2^48 + 2^17 < 2^1 * 2^48 < 2^64. + const auto width_pixels = (margin + width_scaled + margin); - // Guard against index overflows (all below limited to size_t). - if ((pixel_width > 0u) && (max_size_t / pixel_width < pixel_width)) + // Guard: empty image and division by zero. + if (width_pixels == 0u) return {}; - // Pixel is the least significant bit of a qrencode byte. - constexpr auto pixel_mask = uint8_t{ 0x01 }; - constexpr auto pixels_off = uint8_t{ 0x00 }; - constexpr auto pixel_off = false; - - // For readability (image is always square). - const auto coded_height = coded_width; + // Guard: area overflow (all below limited to size_t). + if (max_size_t / width_pixels < width_pixels) + return {}; // Horizontal margins and full row copies can be done bytewise. - const auto row_bytes = (pixel_width + (byte_bits - 1u)) / byte_bits; + const auto row_bytes = (width_pixels + (byte_bits - 1u)) / byte_bits; + const auto row_margin = data_chunk(row_bytes, pixels_off); + + // Bound: (2^16 - 1)^2 < 2^32 or (2^32 - 1)^2 < 2^64. + const auto area_bytes = row_bytes * static_cast(width_pixels); // For reading the qrcode byte stream. data_source image_source(coded); @@ -184,27 +194,30 @@ data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t coded_width, data_sink image_sink(image_out); ostream_writer image_writer(image_sink); ostream_bit_writer image_bit_writer(image_writer); + image_out.reserve(area_bytes); - // Write top margin bytes. + // ------------------------- Write top margin ------------------------- for (size_t row = 0; row < margin; ++row) - for (size_t column = 0; column < row_bytes; ++column) - image_bit_writer.write_byte(pixels_off); + image_bit_writer.write_bytes(row_margin); + // -------------------------------------------------------------------- // Write each row. - for (size_t row = 0; row < coded_height; ++row) + for (size_t row = 0; row < height_coded; ++row) { // For repeatedly writing a row buffer. data_chunk row_out; data_sink row_sink(row_out); ostream_writer row_writer(row_sink); ostream_bit_writer row_bit_writer(row_writer); + row_out.reserve(row_bytes); - // Buffer left margin. + // ------------------------ Buffer left margin ------------------------ for (size_t column = 0; column < margin; ++column) row_bit_writer.write_bit(pixel_off); + // -------------------------------------------------------------------- // Buffer scaled row pixels. - for (size_t column = 0; column < coded_width; ++column) + for (size_t column = 0; column < width_coded; ++column) { // Read byte and extract pixel (least significant) bit. const auto pixel_on = (image_reader.read_byte() & pixel_mask) != 0; @@ -214,9 +227,10 @@ data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t coded_width, row_bit_writer.write_bit(pixel_on); } - // Buffer right margin. + // ------------------------ Buffer right margin ----------------------- for (size_t column = 0; column < margin; ++column) row_bit_writer.write_bit(pixel_off); + // -------------------------------------------------------------------- // Flush any partial byte and then flush bytes to data_chunk. row_bit_writer.flush(); @@ -224,21 +238,13 @@ data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t coded_width, // Write row buffer scale times. for (size_t scaled = 0; scaled < scale; ++scaled) - { - // For repeatedly reading the row buffer. - data_source row_source(row_out); - istream_reader row_reader(row_source); - - // Copy each byte in the row buffer to the output buffer. - for (size_t column = 0; column < row_bytes; ++column) - image_bit_writer.write_byte(row_reader.read_byte()); - } + image_bit_writer.write_bytes(row_out); } - // Write bottom margin bytes. + // ------------------------ Write bottom margin ----------------------- for (size_t row = 0; row < margin; ++row) - for (size_t column = 0; column < row_bytes; ++column) - image_bit_writer.write_byte(pixels_off); + image_bit_writer.write_bytes(row_margin); + // -------------------------------------------------------------------- // Guard against writer failure and unexpected stream length. if (!image_bit_writer || !image_reader || !image_reader.is_exhausted()) From 17bb1a0908f14a785e57927278f50eba69b6e4e6 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 13:41:23 -0700 Subject: [PATCH 38/44] Refactor tiff tests. --- test/utility/tiff.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/utility/tiff.cpp b/test/utility/tiff.cpp index eb355524f1..2bb086959b 100644 --- a/test/utility/tiff.cpp +++ b/test/utility/tiff.cpp @@ -77,14 +77,14 @@ BOOST_AUTO_TEST_CASE(tiff__to_image__maximum_bytes__expected_size_true) } static const auto width = 1u; - static const size_t expected_image_bytes = tiff::max_image_bytes; + static const auto expected_tiff_size = tiff::image_offset + tiff::max_image_bytes; // 2^32 memory allocation here. - data_chunk bitmap(expected_image_bytes, 'x'); + data_chunk bitmap(tiff::max_image_bytes, 'x'); data_chunk tiff; data_sink stream(tiff); BOOST_REQUIRE(tiff::to_image(stream, bitmap, width)); - BOOST_REQUIRE_EQUAL(tiff.size(), tiff::image_offset + expected_image_bytes); + BOOST_REQUIRE_EQUAL(tiff.size(), expected_tiff_size); } BOOST_AUTO_TEST_CASE(tiff__to_image__overflow_bytes__false) @@ -97,9 +97,10 @@ BOOST_AUTO_TEST_CASE(tiff__to_image__overflow_bytes__false) } static const auto width = 1u; + static const auto excess_image_size = tiff::max_image_bytes + 1u; // 2^32 + 1 memory allocation here. - data_chunk bitmap(tiff::max_image_bytes + 1u, 'x'); + data_chunk bitmap(excess_image_size, 'x'); data_chunk tiff; data_sink stream(tiff); BOOST_REQUIRE(!tiff::to_image(stream, bitmap, width)); From 46cfe9dec2bb605a28b4e6f2d49c3a21c6155f72 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 17:49:15 -0700 Subject: [PATCH 39/44] Move ostream_bit_writer flush method, comments. --- .../system/utility/ostream_bit_writer.hpp | 1 + src/utility/ostream_bit_writer.cpp | 20 +++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/include/bitcoin/system/utility/ostream_bit_writer.hpp b/include/bitcoin/system/utility/ostream_bit_writer.hpp index 6fc20a7d4f..6647eea0f5 100644 --- a/include/bitcoin/system/utility/ostream_bit_writer.hpp +++ b/include/bitcoin/system/utility/ostream_bit_writer.hpp @@ -101,6 +101,7 @@ class BC_API ostream_bit_writer /// Advance iterator without writing. void skip(size_t size); + /// This does not flush the member stream. /// Flush the buffer on a zero-padded byte boundary. void flush(); diff --git a/src/utility/ostream_bit_writer.cpp b/src/utility/ostream_bit_writer.cpp index 98b0d79d4e..0cb2229289 100644 --- a/src/utility/ostream_bit_writer.cpp +++ b/src/utility/ostream_bit_writer.cpp @@ -63,16 +63,6 @@ void ostream_bit_writer::buffered_write(data_chunk& data) } } -void ostream_bit_writer::flush() -{ - if (offset_ > 0) - { - writer_.write_byte(buffer_); - buffer_ = 0x00; - offset_ = 0; - } -} - // Context. //----------------------------------------------------------------------------- @@ -307,5 +297,15 @@ void ostream_bit_writer::skip(size_t size) writer_.skip(size); } +void ostream_bit_writer::flush() +{ + if (offset_ > 0) + { + writer_.write_byte(buffer_); + buffer_ = 0x00; + offset_ = 0; + } +} + } // namespace system } // namespace libbitcoin From 1a49076168a57ad1d59b17008997d3335a020cab Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 18:33:27 -0700 Subject: [PATCH 40/44] Verify std container limits. --- test/utility/tiff.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/utility/tiff.cpp b/test/utility/tiff.cpp index 2bb086959b..5d656b23db 100644 --- a/test/utility/tiff.cpp +++ b/test/utility/tiff.cpp @@ -81,6 +81,19 @@ BOOST_AUTO_TEST_CASE(tiff__to_image__maximum_bytes__expected_size_true) // 2^32 memory allocation here. data_chunk bitmap(tiff::max_image_bytes, 'x'); + + // CHECK FOR UNEXPECTED ALLOCATION. + BOOST_REQUIRE_EQUAL(bitmap.size(), tiff::max_image_bytes); + + // CHECK FOR UNEXPECTED VECTOR SIZE TYPE. + BOOST_REQUIRE_EQUAL(sizeof(data_chunk::size_type), sizeof(uint64_t)); + + // CHECK FOR UNEXPECTED VECTOR SIZE LIMIT. + // cppreference.com/w/cpp/container/vector/max_size + // At runtime, the size of the container may be limited to a value + // smaller than max_size() by the amount of RAM available. + BOOST_REQUIRE_EQUAL(bitmap.max_size(), bc::max_uint64); + data_chunk tiff; data_sink stream(tiff); BOOST_REQUIRE(tiff::to_image(stream, bitmap, width)); From e5305b8125d0bb5ff066351d6960fc7eb7b97529 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 21:25:23 -0700 Subject: [PATCH 41/44] Comments, style, fix 32 bit implicit downcasts. --- src/utility/tiff.cpp | 1 + src/wallet/qr_code.cpp | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/utility/tiff.cpp b/src/utility/tiff.cpp index da180e5472..902169cb80 100644 --- a/src/utility/tiff.cpp +++ b/src/utility/tiff.cpp @@ -146,6 +146,7 @@ bool tiff::to_image(std::ostream& out, const data_chunk& data, uint16_t width) return false; // TIFF encoding limit is max_uint32. + // This method is otherwise limited only by the stream capacity. if (data.size() > max_image_bytes) return false; diff --git a/src/wallet/qr_code.cpp b/src/wallet/qr_code.cpp index 0b645c572d..983fbd9057 100644 --- a/src/wallet/qr_code.cpp +++ b/src/wallet/qr_code.cpp @@ -94,6 +94,8 @@ static bool safe_free_and_return(QRcode* qrcode, bool result) return result; } +// TODO: remove scale and margin, call to_pixels() independently. +// TODO: create independent method to perform scaling and margining. bool qr_code::encode(std::ostream& out, const std::string& value, uint8_t version, uint16_t scale, uint16_t margin, recovery_level level, encode_mode mode, bool case_sensitive) @@ -117,10 +119,10 @@ bool qr_code::encode(std::ostream& out, const std::string& value, return safe_free_and_return(qrcode, false); // Bound: 2^1 * 2^16 + 2^32 < 2^64. - const auto pixel_width = uint64_t{ 2u } * margin + scale * qrcode->width; + const auto width_pixels = uint64_t{ 2u } * margin + scale * qrcode->width; // Guard: TIFF parameter overflow. - if (pixel_width > max_uint16) + if (width_pixels > max_uint16) return safe_free_and_return(qrcode, false); // Bound: (2^32 - 1)^2 < 2^64. @@ -138,14 +140,13 @@ bool qr_code::encode(std::ostream& out, const std::string& value, // Convert to TIFF image stream. return safe_free_and_return(qrcode, tiff::to_image(out, pixels, - static_cast(pixel_width))); + static_cast(width_pixels))); } +// TODO: return stream and split out scaling and margining. // Scale may move the image off of a byte-aligned square of pixels in bytes. // So the dimensions cannot be derived from the result, caller must retain. // pixel_width = 2 * margin + scale * coded_width. -// The result may be up to max_size_t, which exceeds the TIFF limit of 2^32 -// when size_t is 2^64. Caller can optimize a failure by guarding pixel_width. data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t width_coded, uint16_t scale, uint16_t margin) { @@ -178,12 +179,16 @@ data_chunk qr_code::to_pixels(const data_chunk& coded, uint32_t width_coded, if (max_size_t / width_pixels < width_pixels) return {}; + // Cast guarded width and define height for readability. + const auto width = static_cast(width_pixels); + const auto height = static_cast(height_coded); + // Horizontal margins and full row copies can be done bytewise. - const auto row_bytes = (width_pixels + (byte_bits - 1u)) / byte_bits; + const auto row_bytes = (width + (byte_bits - 1u)) / byte_bits; const auto row_margin = data_chunk(row_bytes, pixels_off); // Bound: (2^16 - 1)^2 < 2^32 or (2^32 - 1)^2 < 2^64. - const auto area_bytes = row_bytes * static_cast(width_pixels); + const auto area_bytes = height * row_bytes; // For reading the qrcode byte stream. data_source image_source(coded); From dc6e8ddaa8d08cf4583dfb163d192e50b8b76952 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 21:25:43 -0700 Subject: [PATCH 42/44] Remove pointless tests (testing test buffer size). --- test/utility/tiff.cpp | 52 ------------------------------------------- 1 file changed, 52 deletions(-) diff --git a/test/utility/tiff.cpp b/test/utility/tiff.cpp index 5d656b23db..d39e333ba6 100644 --- a/test/utility/tiff.cpp +++ b/test/utility/tiff.cpp @@ -67,58 +67,6 @@ BOOST_AUTO_TEST_CASE(tiff__to_image__width_0__false) BOOST_REQUIRE(!tiff::to_image(stream, bitmap, width)); } -BOOST_AUTO_TEST_CASE(tiff__to_image__maximum_bytes__expected_size_true) -{ - // Guard against overflow in tiff data_chunk (not a method/stream limit). - if (sizeof(data_chunk::size_type) < sizeof(uint64_t)) - { - BOOST_REQUIRE(true); - return; - } - - static const auto width = 1u; - static const auto expected_tiff_size = tiff::image_offset + tiff::max_image_bytes; - - // 2^32 memory allocation here. - data_chunk bitmap(tiff::max_image_bytes, 'x'); - - // CHECK FOR UNEXPECTED ALLOCATION. - BOOST_REQUIRE_EQUAL(bitmap.size(), tiff::max_image_bytes); - - // CHECK FOR UNEXPECTED VECTOR SIZE TYPE. - BOOST_REQUIRE_EQUAL(sizeof(data_chunk::size_type), sizeof(uint64_t)); - - // CHECK FOR UNEXPECTED VECTOR SIZE LIMIT. - // cppreference.com/w/cpp/container/vector/max_size - // At runtime, the size of the container may be limited to a value - // smaller than max_size() by the amount of RAM available. - BOOST_REQUIRE_EQUAL(bitmap.max_size(), bc::max_uint64); - - data_chunk tiff; - data_sink stream(tiff); - BOOST_REQUIRE(tiff::to_image(stream, bitmap, width)); - BOOST_REQUIRE_EQUAL(tiff.size(), expected_tiff_size); -} - -BOOST_AUTO_TEST_CASE(tiff__to_image__overflow_bytes__false) -{ - // Guard against overflow in tiff data_chunk (not a method/stream limit). - if (sizeof(data_chunk::size_type) < sizeof(uint64_t)) - { - BOOST_REQUIRE(true); - return; - } - - static const auto width = 1u; - static const auto excess_image_size = tiff::max_image_bytes + 1u; - - // 2^32 + 1 memory allocation here. - data_chunk bitmap(excess_image_size, 'x'); - data_chunk tiff; - data_sink stream(tiff); - BOOST_REQUIRE(!tiff::to_image(stream, bitmap, width)); -} - BOOST_AUTO_TEST_CASE(tiff__to_image__perfect_square__expected_true) { // A square with sides of 4 pixels is 4 rows of 1 byte. From b52aa6ae9ade849d640106b163ea422453e32b43 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 22:15:40 -0700 Subject: [PATCH 43/44] Style, comments. --- src/utility/tiff.cpp | 1 + src/wallet/qr_code.cpp | 12 +++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/utility/tiff.cpp b/src/utility/tiff.cpp index 902169cb80..ce4f397011 100644 --- a/src/utility/tiff.cpp +++ b/src/utility/tiff.cpp @@ -139,6 +139,7 @@ static_assert(strip0_offset % sizeof(offset) == 0, uint32_t tiff::image_offset = strip0_offset; size_t tiff::max_image_bytes = max_uint32; +// TODO: accept and return stream. bool tiff::to_image(std::ostream& out, const data_chunk& data, uint16_t width) { // Empty image is not valid TIFF. diff --git a/src/wallet/qr_code.cpp b/src/wallet/qr_code.cpp index 983fbd9057..4bd14a9955 100644 --- a/src/wallet/qr_code.cpp +++ b/src/wallet/qr_code.cpp @@ -119,10 +119,10 @@ bool qr_code::encode(std::ostream& out, const std::string& value, return safe_free_and_return(qrcode, false); // Bound: 2^1 * 2^16 + 2^32 < 2^64. - const auto width_pixels = uint64_t{ 2u } * margin + scale * qrcode->width; + const auto width = uint64_t{ 2u } * margin + scale * qrcode->width; // Guard: TIFF parameter overflow. - if (width_pixels > max_uint16) + if (width > max_uint16) return safe_free_and_return(qrcode, false); // Bound: (2^32 - 1)^2 < 2^64. @@ -139,11 +139,13 @@ bool qr_code::encode(std::ostream& out, const std::string& value, const auto pixels = to_pixels(data, qrcode->width, scale, margin); // Convert to TIFF image stream. - return safe_free_and_return(qrcode, tiff::to_image(out, pixels, - static_cast(width_pixels))); + const auto result = tiff::to_image(out, pixels, + static_cast(width)); + + return safe_free_and_return(qrcode, result); } -// TODO: return stream and split out scaling and margining. +// TODO: accept and return stream and split out scaling and margining. // Scale may move the image off of a byte-aligned square of pixels in bytes. // So the dimensions cannot be derived from the result, caller must retain. // pixel_width = 2 * margin + scale * coded_width. From 6730df4c08e40a5506f7463446ab50f1337cf9a6 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Thu, 18 Mar 2021 22:15:57 -0700 Subject: [PATCH 44/44] Resolve missing virtual destructor warnings. --- include/bitcoin/system/config/parameter.hpp | 5 +++++ include/bitcoin/system/config/printer.hpp | 5 +++++ src/config/parameter.cpp | 4 ++++ src/config/printer.cpp | 4 ++++ 4 files changed, 18 insertions(+) diff --git a/include/bitcoin/system/config/parameter.hpp b/include/bitcoin/system/config/parameter.hpp index 71d7668cb1..fa9e0b0b98 100644 --- a/include/bitcoin/system/config/parameter.hpp +++ b/include/bitcoin/system/config/parameter.hpp @@ -93,6 +93,11 @@ class BC_API parameter */ static const char option_prefix_char; + /** + * Destructor. + */ + virtual ~parameter(); + /** * Populate with normalized parameter data. * @param[in] option The metadata of the option to test. diff --git a/include/bitcoin/system/config/printer.hpp b/include/bitcoin/system/config/printer.hpp index a5f9af8ff4..3441750a72 100644 --- a/include/bitcoin/system/config/printer.hpp +++ b/include/bitcoin/system/config/printer.hpp @@ -57,6 +57,11 @@ class BC_API printer */ BC_API static const int max_arguments; + /** + * Destructor. + */ + virtual ~printer(); + /** * Construct an instance of the printer class. * @param[in] settings Populated config file settings metadata. diff --git a/src/config/parameter.cpp b/src/config/parameter.cpp index 662f7ce1b9..7cca8da329 100644 --- a/src/config/parameter.cpp +++ b/src/config/parameter.cpp @@ -29,6 +29,10 @@ const int parameter::not_positional = -1; const char parameter::no_short_name = 0x00; const char parameter::option_prefix_char = '-'; +parameter::~parameter() +{ +} + // 100% component coverage, common scenarios. // A required argument may only be preceded by required arguments. // Requiredness may be in error if the metadata is inconsistent. diff --git a/src/config/printer.cpp b/src/config/printer.cpp index 8846049bad..0753bbd54f 100644 --- a/src/config/printer.cpp +++ b/src/config/printer.cpp @@ -69,6 +69,10 @@ using boost::format; const int printer::max_arguments = 256; +printer::~printer() +{ +} + printer::printer(const po::options_description& options, const po::positional_options_description& arguments, const std::string& application, const std::string& description,