tdiary 5.5.0 → 5.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ChangeLog +2 -0
- data/Gemfile +2 -1
- data/Gemfile.lock +37 -37
- data/doc/UPGRADE.md +1 -1
- data/lib/tdiary/admin.rb +11 -13
- data/lib/tdiary/application.rb +2 -7
- data/lib/tdiary/author_only_base.rb +78 -9
- data/lib/tdiary/base.rb +2 -2
- data/lib/tdiary/cgi_adapter.rb +7 -5
- data/lib/tdiary/cgi_compat.rb +27 -95
- data/lib/tdiary/configuration.rb +4 -0
- data/lib/tdiary/core_ext.rb +146 -1
- data/lib/tdiary/dispatcher/index_main.rb +5 -23
- data/lib/tdiary/dispatcher/update_main.rb +2 -17
- data/lib/tdiary/dispatcher.rb +29 -15
- data/lib/tdiary/filter/default.rb +2 -2
- data/lib/tdiary/filter/spam.rb +2 -2
- data/lib/tdiary/filter.rb +1 -1
- data/lib/tdiary/plugin/00default.rb +18 -3
- data/lib/tdiary/plugin/en/00default.rb +15 -0
- data/lib/tdiary/plugin/ja/00default.rb +15 -0
- data/lib/tdiary/plugin.rb +1 -1
- data/lib/tdiary/rack/error_handler.rb +36 -0
- data/lib/tdiary/rack.rb +1 -0
- data/lib/tdiary/request.rb +12 -2
- data/lib/tdiary/server.rb +25 -3
- data/lib/tdiary/version.rb +1 -1
- data/lib/tdiary/view.rb +33 -28
- data/lib/tdiary/view_helper.rb +10 -2
- data/lib/tdiary.rb +6 -1
- data/misc/plugin/image.rb +1 -1
- data/misc/plugin/makerss.rb +3 -3
- data/tdiary.conf.sample +8 -0
- data/tdiary.conf.sample-en +8 -0
- data/vendor/bundle/ruby/3.4.0/cache/net-imap-0.6.6.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/net-protocol-0.3.0.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rack-3.2.7.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/cgi-0.5.2/gem_make.out +5 -5
- data/vendor/bundle/ruby/3.4.0/extensions/x86_64-linux/3.4.0/date-3.5.1/gem_make.out +5 -5
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/Gemfile +3 -4
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/README.md +1 -1
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.6.6/Rakefile +24 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/command_data.rb +62 -92
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_accessors.rb +8 -9
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_inheritance.rb +64 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_version_defaults.rb +1 -4
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config.rb +209 -35
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/connection_state.rb +1 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/data_encoding.rb +127 -27
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.6.6/lib/net/imap/errors.rb +372 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/esearch_result.rb +6 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_data.rb +90 -11
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_parser/parser_utils.rb +14 -23
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_parser.rb +41 -26
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/response_reader.rb +16 -21
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/scram_authenticator.rb +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/search_result.rb +11 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sequence_set.rb +620 -312
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/uidplus_data.rb +2 -63
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap.rb +279 -162
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/net-imap.gemspec +1 -1
- data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/rdoc.rake +1 -18
- data/vendor/bundle/ruby/3.4.0/gems/{net-protocol-0.2.2/LICENSE.txt → net-protocol-0.3.0/BSDL} +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.3.0/COPYING +56 -0
- data/vendor/bundle/ruby/3.4.0/gems/{net-protocol-0.2.2 → net-protocol-0.3.0}/lib/net/protocol.rb +58 -4
- data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/CHANGELOG.md +54 -1
- data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/utils.rb +3 -3
- data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/version.rb +1 -1
- data/vendor/bundle/ruby/3.4.0/specifications/{net-imap-0.5.15.gemspec → net-imap-0.6.6.gemspec} +4 -4
- data/vendor/bundle/ruby/3.4.0/specifications/{net-protocol-0.2.2.gemspec → net-protocol-0.3.0.gemspec} +5 -5
- data/vendor/bundle/ruby/3.4.0/specifications/{rack-3.2.6.gemspec → rack-3.2.7.gemspec} +3 -3
- data/views/tdiary.rconf +2 -0
- metadata +127 -131
- data/vendor/bundle/ruby/3.4.0/cache/net-imap-0.5.15.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/net-protocol-0.2.2.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/cache/rack-3.2.6.gem +0 -0
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/Rakefile +0 -13
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/data_lite.rb +0 -226
- data/vendor/bundle/ruby/3.4.0/gems/net-imap-0.5.15/lib/net/imap/errors.rb +0 -118
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Gemfile +0 -7
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/Rakefile +0 -10
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/console +0 -14
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/bin/setup +0 -8
- data/vendor/bundle/ruby/3.4.0/gems/net-protocol-0.2.2/net-protocol.gemspec +0 -33
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/BSDL +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/COPYING +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/LICENSE.txt +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/docs/styles.css +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/authenticators.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/config/attr_type_coercion.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/deprecated_client_options.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/fetch_data.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/flags.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/anonymous_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/authentication_exchange.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/authenticators.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/client_adapter.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/cram_md5_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/digest_md5_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/external_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/gs2_header.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/login_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/oauthbearer_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/plain_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/protocol_adapters.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/scram_algorithm.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/stringprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl/xoauth2_authenticator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sasl_adapter.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/nameprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/saslprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/saslprep_tables.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/tables.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep/trace.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/stringprep.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/vanished_data.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/benchmarks.rake +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/rfcs.rake +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/saslprep.rake +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/rakelib/string_prep_tables_generator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/sample/net-imap.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{net-protocol-0.2.2 → net-protocol-0.3.0}/README.md +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/CONTRIBUTING.md +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/MIT-LICENSE +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/README.md +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/SPEC.rdoc +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/auth/abstract/handler.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/auth/abstract/request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/auth/basic.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/bad_request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/body_proxy.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/builder.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/cascade.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/common_logger.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/conditional_get.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/config.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/constants.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/content_length.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/content_type.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/deflater.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/directory.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/etag.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/events.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/files.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/head.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/headers.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/lint.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/lock.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/media_type.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/method_override.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mime.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mock.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mock_request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/mock_response.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart/generator.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart/parser.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart/uploaded_file.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/multipart.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/null_logger.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/query_parser.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/recursive.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/reloader.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/request.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/response.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/rewindable_input.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/runtime.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/sendfile.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/show_exceptions.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/show_status.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/static.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/tempfile_reaper.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack/urlmap.rb +0 -0
- /data/vendor/bundle/ruby/3.4.0/gems/{rack-3.2.6 → rack-3.2.7}/lib/rack.rb +0 -0
data/vendor/bundle/ruby/3.4.0/gems/{net-imap-0.5.15 → net-imap-0.6.6}/lib/net/imap/sequence_set.rb
RENAMED
|
@@ -145,6 +145,10 @@ module Net
|
|
|
145
145
|
# #entries and #elements are identical. Use #append to preserve #entries
|
|
146
146
|
# order while modifying a set.
|
|
147
147
|
#
|
|
148
|
+
# Non-normalized sets store both representations of the set, which can more
|
|
149
|
+
# than double memory usage. Very large sequence sets should avoid
|
|
150
|
+
# denormalizing methods (such as #append) unless order is significant.
|
|
151
|
+
#
|
|
148
152
|
# == Using <tt>*</tt>
|
|
149
153
|
#
|
|
150
154
|
# \IMAP sequence sets may contain a special value <tt>"*"</tt>, which
|
|
@@ -179,7 +183,7 @@ module Net
|
|
|
179
183
|
#
|
|
180
184
|
# When a set includes <tt>*</tt>, some methods may have surprising behavior.
|
|
181
185
|
#
|
|
182
|
-
# For example, #complement treats <tt>*</tt> as its own
|
|
186
|
+
# For example, #complement treats <tt>*</tt> as its own member. This way,
|
|
183
187
|
# the #intersection of a set and its #complement will always be empty. And
|
|
184
188
|
# <tt>*</tt> is sorted as greater than any other number in the set. This is
|
|
185
189
|
# not how an \IMAP server interprets the set: it will convert <tt>*</tt> to
|
|
@@ -199,7 +203,7 @@ module Net
|
|
|
199
203
|
# (set.limit(max: 4) & (~set).limit(max: 4)).to_a => [4]
|
|
200
204
|
#
|
|
201
205
|
# When counting the number of numbers in a set, <tt>*</tt> will be counted
|
|
202
|
-
#
|
|
206
|
+
# as if it were equal to UINT32_MAX:
|
|
203
207
|
# UINT32_MAX = 2**32 - 1
|
|
204
208
|
# Net::IMAP::SequenceSet["*"].count => 1
|
|
205
209
|
# Net::IMAP::SequenceSet[1..UINT32_MAX - 1, :*].count => UINT32_MAX
|
|
@@ -208,6 +212,12 @@ module Net
|
|
|
208
212
|
# Net::IMAP::SequenceSet[UINT32_MAX, :*].count => 1
|
|
209
213
|
# Net::IMAP::SequenceSet[UINT32_MAX..].count => 1
|
|
210
214
|
#
|
|
215
|
+
# Use #cardinality to count the set members wxth <tt>*</tt> counted as a
|
|
216
|
+
# distinct member:
|
|
217
|
+
# Net::IMAP::SequenceSet[1..].cardinality #=> UINT32_MAX + 1
|
|
218
|
+
# Net::IMAP::SequenceSet[UINT32_MAX, :*].cardinality #=> 2
|
|
219
|
+
# Net::IMAP::SequenceSet[UINT32_MAX..].cardinality #=> 2
|
|
220
|
+
#
|
|
211
221
|
# == What's here?
|
|
212
222
|
#
|
|
213
223
|
# SequenceSet provides methods for:
|
|
@@ -271,8 +281,10 @@ module Net
|
|
|
271
281
|
# occurrence in entries.
|
|
272
282
|
#
|
|
273
283
|
# <i>Set cardinality:</i>
|
|
274
|
-
# - #
|
|
275
|
-
#
|
|
284
|
+
# - #cardinality: Returns the number of distinct members in the set.
|
|
285
|
+
# <tt>*</tt> is counted as its own member, distinct from UINT32_MAX.
|
|
286
|
+
# - #count: Returns the count of distinct numbers in the set.
|
|
287
|
+
# <tt>*</tt> is counted as equal to UINT32_MAX.
|
|
276
288
|
# - #empty?: Returns whether the set has no members. \IMAP syntax does not
|
|
277
289
|
# allow empty sequence sets.
|
|
278
290
|
# - #valid?: Returns whether the set has any members.
|
|
@@ -280,12 +292,18 @@ module Net
|
|
|
280
292
|
# <tt>*</tt>.
|
|
281
293
|
#
|
|
282
294
|
# <i>Denormalized properties:</i>
|
|
295
|
+
# - #normalized?: Returns whether #entries are sorted, deduplicated, and
|
|
296
|
+
# coalesced, and all #string entries are in normalized form.
|
|
283
297
|
# - #has_duplicates?: Returns whether the ordered entries repeat any
|
|
284
298
|
# numbers.
|
|
285
|
-
# - #
|
|
286
|
-
#
|
|
299
|
+
# - #size: Returns the total size of all #entries, including repeated
|
|
300
|
+
# numbers. <tt>*</tt> is counted as its own member, distinct from
|
|
301
|
+
# UINT32_MAX.
|
|
287
302
|
# - #count_with_duplicates: Returns the count of numbers in the ordered
|
|
288
|
-
# entries, including
|
|
303
|
+
# #entries, including repeated numbers. <tt>*</tt> is counted as
|
|
304
|
+
# equal to UINT32_MAX.
|
|
305
|
+
# - #count_duplicates: Returns the count of repeated numbers in the ordered
|
|
306
|
+
# #entries. <tt>*</tt> is counted as equal to UINT32_MAX.
|
|
289
307
|
#
|
|
290
308
|
# === Methods for Iterating
|
|
291
309
|
#
|
|
@@ -332,7 +350,7 @@ module Net
|
|
|
332
350
|
# given maximum value and removed all members over that maximum.
|
|
333
351
|
#
|
|
334
352
|
# === Methods for Assigning
|
|
335
|
-
# These methods add or replace
|
|
353
|
+
# These methods add or replace numbers in +self+.
|
|
336
354
|
#
|
|
337
355
|
# <i>Normalized (sorted and coalesced):</i>
|
|
338
356
|
#
|
|
@@ -341,8 +359,12 @@ module Net
|
|
|
341
359
|
# - #add (aliased as #<<): Adds a given element to the set; returns +self+.
|
|
342
360
|
# - #add?: If the given element is not fully included the set, adds it and
|
|
343
361
|
# returns +self+; otherwise, returns +nil+.
|
|
344
|
-
# - #merge: Adds all members of the given sets into
|
|
345
|
-
#
|
|
362
|
+
# - #merge: In-place set #union. Adds all members of the given sets into
|
|
363
|
+
# this set; returns +self+.
|
|
364
|
+
# - #complement!: In-place set #complement. Replaces the contents of this
|
|
365
|
+
# set with its own #complement; returns +self+.
|
|
366
|
+
# - #xor!: In-place +XOR+ operation. Adds numbers that are unique to the
|
|
367
|
+
# other set and removes numbers that are common to both; returns +self+.
|
|
346
368
|
#
|
|
347
369
|
# <i>Order preserving:</i>
|
|
348
370
|
#
|
|
@@ -355,7 +377,7 @@ module Net
|
|
|
355
377
|
# of a given object.
|
|
356
378
|
#
|
|
357
379
|
# === Methods for Deleting
|
|
358
|
-
# These methods remove
|
|
380
|
+
# These methods remove numbers from +self+, and update #string to be fully
|
|
359
381
|
# sorted and coalesced.
|
|
360
382
|
#
|
|
361
383
|
# - #clear: Removes all elements in the set; returns +self+.
|
|
@@ -363,10 +385,12 @@ module Net
|
|
|
363
385
|
# - #delete?: If the given element is included in the set, removes it and
|
|
364
386
|
# returns it; otherwise, returns +nil+.
|
|
365
387
|
# - #delete_at: Removes the number at a given offset.
|
|
388
|
+
# - #intersect!: In-place set #intersection. Removes numbers that are not
|
|
389
|
+
# in the given set; returns +self+.
|
|
366
390
|
# - #slice!: Removes the number or consecutive numbers at a given offset or
|
|
367
391
|
# range of offsets.
|
|
368
|
-
# - #subtract: Removes all members of the given
|
|
369
|
-
# +self+.
|
|
392
|
+
# - #subtract: In-place set #difference. Removes all members of the given
|
|
393
|
+
# sets from this set; returns +self+.
|
|
370
394
|
# - #limit!: Replaces <tt>*</tt> with a given maximum value and removes all
|
|
371
395
|
# members over that maximum; returns +self+.
|
|
372
396
|
#
|
|
@@ -531,12 +555,17 @@ module Net
|
|
|
531
555
|
# combined with set operations (#|, #&, #^, #-, etc) to make new sets.
|
|
532
556
|
#
|
|
533
557
|
# See SequenceSet@Creating+sequence+sets.
|
|
534
|
-
def initialize(input = nil)
|
|
558
|
+
def initialize(input = nil)
|
|
559
|
+
@set_data = new_set_data
|
|
560
|
+
@string = nil
|
|
561
|
+
replace(input) unless input.nil?
|
|
562
|
+
end
|
|
535
563
|
|
|
536
564
|
# Removes all elements and returns self.
|
|
537
565
|
def clear
|
|
538
|
-
modifying! # redundant check
|
|
539
|
-
|
|
566
|
+
modifying! # redundant check (normalizes the error message for JRuby)
|
|
567
|
+
set_data.clear
|
|
568
|
+
@string = nil
|
|
540
569
|
self
|
|
541
570
|
end
|
|
542
571
|
|
|
@@ -549,7 +578,7 @@ module Net
|
|
|
549
578
|
case other
|
|
550
579
|
when SequenceSet then
|
|
551
580
|
modifying! # short circuit before doing any work
|
|
552
|
-
@
|
|
581
|
+
@set_data = other.dup_set_data
|
|
553
582
|
@string = other.instance_variable_get(:@string)
|
|
554
583
|
when String then self.string = other
|
|
555
584
|
else clear; merge other
|
|
@@ -580,7 +609,7 @@ module Net
|
|
|
580
609
|
# the set is updated the string will be normalized.
|
|
581
610
|
#
|
|
582
611
|
# Related: #valid_string, #normalized_string, #to_s, #inspect
|
|
583
|
-
def string; @string
|
|
612
|
+
def string; @string || normalized_string if valid? end
|
|
584
613
|
|
|
585
614
|
# Returns an array with #normalized_string when valid and an empty array
|
|
586
615
|
# otherwise.
|
|
@@ -599,13 +628,18 @@ module Net
|
|
|
599
628
|
clear
|
|
600
629
|
elsif (str = String.try_convert(input))
|
|
601
630
|
modifying! # short-circuit before parsing the string
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
631
|
+
entries = each_parsed_entry(str).to_a
|
|
632
|
+
clear
|
|
633
|
+
if normalized_entries?(entries)
|
|
634
|
+
replace_minmaxes entries.map!(&:minmax)
|
|
635
|
+
else
|
|
636
|
+
add_minmaxes entries.map!(&:minmax)
|
|
637
|
+
@string = -str
|
|
638
|
+
end
|
|
605
639
|
else
|
|
606
640
|
raise ArgumentError, "expected a string or nil, got #{input.class}"
|
|
607
641
|
end
|
|
608
|
-
|
|
642
|
+
input
|
|
609
643
|
end
|
|
610
644
|
|
|
611
645
|
# Returns the \IMAP +sequence-set+ string representation, or an empty
|
|
@@ -618,8 +652,7 @@ module Net
|
|
|
618
652
|
# Freezes and returns the set. A frozen SequenceSet is Ractor-safe.
|
|
619
653
|
def freeze
|
|
620
654
|
return self if frozen?
|
|
621
|
-
|
|
622
|
-
@tuples.each(&:freeze).freeze
|
|
655
|
+
freeze_set_data
|
|
623
656
|
super
|
|
624
657
|
end
|
|
625
658
|
|
|
@@ -641,7 +674,7 @@ module Net
|
|
|
641
674
|
# Related: #eql?, #normalize
|
|
642
675
|
def ==(other)
|
|
643
676
|
self.class == other.class &&
|
|
644
|
-
(to_s == other.to_s ||
|
|
677
|
+
(to_s == other.to_s || set_data == other.set_data)
|
|
645
678
|
end
|
|
646
679
|
|
|
647
680
|
# :call-seq: eql?(other) -> true or false
|
|
@@ -682,7 +715,7 @@ module Net
|
|
|
682
715
|
# object that would be accepted by ::new.
|
|
683
716
|
#
|
|
684
717
|
# Related: #===, #include?, #include_star?, #intersect?
|
|
685
|
-
def cover?(other)
|
|
718
|
+
def cover?(other) import_runs(other).none? { !include_run?(_1) } end
|
|
686
719
|
|
|
687
720
|
# Returns +true+ when a given number or range is in +self+, and +false+
|
|
688
721
|
# otherwise. Returns +nil+ when +number+ isn't a valid SequenceSet
|
|
@@ -709,14 +742,14 @@ module Net
|
|
|
709
742
|
#
|
|
710
743
|
# Related: #include_star?, #cover?, #===, #intersect?
|
|
711
744
|
def include?(element)
|
|
712
|
-
|
|
713
|
-
!!
|
|
745
|
+
run = import_run element rescue nil
|
|
746
|
+
!!include_run?(run) if run
|
|
714
747
|
end
|
|
715
748
|
|
|
716
749
|
alias member? include?
|
|
717
750
|
|
|
718
751
|
# Returns +true+ when the set contains <tt>*</tt>.
|
|
719
|
-
def include_star?;
|
|
752
|
+
def include_star?; max_num == STAR_INT end
|
|
720
753
|
|
|
721
754
|
# Returns +true+ if the set and a given object have any common elements,
|
|
722
755
|
# +false+ otherwise.
|
|
@@ -726,7 +759,7 @@ module Net
|
|
|
726
759
|
#
|
|
727
760
|
# Related: #intersection, #disjoint?, #cover?, #include?
|
|
728
761
|
def intersect?(other)
|
|
729
|
-
valid? &&
|
|
762
|
+
valid? && import_runs(other).any? { intersect_run? _1 }
|
|
730
763
|
end
|
|
731
764
|
alias overlap? intersect?
|
|
732
765
|
|
|
@@ -738,7 +771,7 @@ module Net
|
|
|
738
771
|
#
|
|
739
772
|
# Related: #intersection, #intersect?
|
|
740
773
|
def disjoint?(other)
|
|
741
|
-
empty? ||
|
|
774
|
+
empty? || import_runs(other).none? { intersect_run? _1 }
|
|
742
775
|
end
|
|
743
776
|
|
|
744
777
|
# :call-seq:
|
|
@@ -755,14 +788,12 @@ module Net
|
|
|
755
788
|
# Related: #min, #minmax, #slice
|
|
756
789
|
def max(count = nil, star: :*)
|
|
757
790
|
if count
|
|
758
|
-
# n.b: #cardinality has not been backported to 0.5
|
|
759
|
-
cardinality = @tuples.sum(@tuples.count) { _2 - _1 }
|
|
760
791
|
if cardinality <= count
|
|
761
792
|
frozen? ? self : dup
|
|
762
793
|
else
|
|
763
794
|
slice(-count..) || remain_frozen_empty
|
|
764
795
|
end
|
|
765
|
-
elsif (val =
|
|
796
|
+
elsif (val = max_num)
|
|
766
797
|
val == STAR_INT ? star : val
|
|
767
798
|
end
|
|
768
799
|
end
|
|
@@ -782,7 +813,7 @@ module Net
|
|
|
782
813
|
def min(count = nil, star: :*)
|
|
783
814
|
if count
|
|
784
815
|
slice(0...count) || remain_frozen_empty
|
|
785
|
-
elsif (val =
|
|
816
|
+
elsif (val = min_num)
|
|
786
817
|
val != STAR_INT ? val : star
|
|
787
818
|
end
|
|
788
819
|
end
|
|
@@ -800,10 +831,10 @@ module Net
|
|
|
800
831
|
def valid?; !empty? end
|
|
801
832
|
|
|
802
833
|
# Returns true if the set contains no elements
|
|
803
|
-
def empty?;
|
|
834
|
+
def empty?; runs.empty? end
|
|
804
835
|
|
|
805
836
|
# Returns true if the set contains every possible element.
|
|
806
|
-
def full?;
|
|
837
|
+
def full?; set_data == FULL_SET_DATA end
|
|
807
838
|
|
|
808
839
|
# :call-seq:
|
|
809
840
|
# self + other -> sequence set
|
|
@@ -879,9 +910,7 @@ module Net
|
|
|
879
910
|
# * <tt>lhs - (lhs - rhs)</tt>
|
|
880
911
|
# * <tt>lhs - (lhs ^ rhs)</tt>
|
|
881
912
|
# * <tt>lhs ^ (lhs - rhs)</tt>
|
|
882
|
-
def &(other)
|
|
883
|
-
remain_frozen dup.subtract SequenceSet.new(other).complement!
|
|
884
|
-
end
|
|
913
|
+
def &(other) remain_frozen dup.intersect! other end
|
|
885
914
|
alias intersection :&
|
|
886
915
|
|
|
887
916
|
# :call-seq:
|
|
@@ -906,7 +935,7 @@ module Net
|
|
|
906
935
|
# * <tt>(lhs | rhs) - (lhs & rhs)</tt>
|
|
907
936
|
# * <tt>(lhs - rhs) | (rhs - lhs)</tt>
|
|
908
937
|
# * <tt>(lhs ^ other) ^ (other ^ rhs)</tt>
|
|
909
|
-
def ^(other) remain_frozen
|
|
938
|
+
def ^(other) remain_frozen dup.xor! other end
|
|
910
939
|
alias xor :^
|
|
911
940
|
|
|
912
941
|
# :call-seq:
|
|
@@ -945,8 +974,8 @@ module Net
|
|
|
945
974
|
#
|
|
946
975
|
# Related: #add?, #merge, #union, #append
|
|
947
976
|
def add(element)
|
|
948
|
-
modifying! # short-circuit before
|
|
949
|
-
|
|
977
|
+
modifying! # short-circuit before import_run
|
|
978
|
+
add_run import_run element
|
|
950
979
|
normalize!
|
|
951
980
|
end
|
|
952
981
|
alias << add
|
|
@@ -956,16 +985,55 @@ module Net
|
|
|
956
985
|
# Unlike #add, #merge, or #union, the new value is appended to #string.
|
|
957
986
|
# This may result in a #string which has duplicates or is out-of-order.
|
|
958
987
|
#
|
|
959
|
-
#
|
|
988
|
+
# set = Net::IMAP::SequenceSet.new
|
|
989
|
+
# set.append(1..2) # => Net::IMAP::SequenceSet("1:2")
|
|
990
|
+
# set.append(5) # => Net::IMAP::SequenceSet("1:2,5")
|
|
991
|
+
# set.append(4) # => Net::IMAP::SequenceSet("1:2,5,4")
|
|
992
|
+
# set.append(3) # => Net::IMAP::SequenceSet("1:2,5,4,3")
|
|
993
|
+
# set.append(2) # => Net::IMAP::SequenceSet("1:2,5,4,3,2")
|
|
994
|
+
#
|
|
995
|
+
# If +entry+ is a string, it will be converted into normal form.
|
|
996
|
+
#
|
|
997
|
+
# set = Net::IMAP::SequenceSet("4:5,1:2")
|
|
998
|
+
# set.append("6:6") # => Net::IMAP::SequenceSet("4:5,1:2,6")
|
|
999
|
+
# set.append("9:8") # => Net::IMAP::SequenceSet("4:5,1:2,6,8:9")
|
|
1000
|
+
#
|
|
1001
|
+
# If +entry+ adjacently follows the last entry, they will coalesced:
|
|
1002
|
+
# set = Net::IMAP::SequenceSet.new("2,1,9:10")
|
|
1003
|
+
# set.append(11..12) # => Net::IMAP::SequenceSet("2,1,9:12")
|
|
1004
|
+
#
|
|
1005
|
+
# Non-normalized sets store the string <em>in addition to</em> an internal
|
|
1006
|
+
# normalized uint32 set representation. This can more than double memory
|
|
1007
|
+
# usage, so large sets should avoid using #append unless preserving order
|
|
1008
|
+
# is required. See SequenceSet@Ordered+and+Normalized+sets.
|
|
960
1009
|
#
|
|
961
1010
|
# Related: #add, #merge, #union
|
|
962
1011
|
def append(entry)
|
|
963
|
-
modifying! # short-circuit before
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
string
|
|
967
|
-
|
|
968
|
-
|
|
1012
|
+
modifying! # short-circuit before import_minmax
|
|
1013
|
+
minmax = import_minmax entry
|
|
1014
|
+
adj = minmax.first - 1
|
|
1015
|
+
if @string.nil? && (runs.empty? || max_num <= adj)
|
|
1016
|
+
# append to elements or coalesce with last element
|
|
1017
|
+
add_minmax minmax
|
|
1018
|
+
return self
|
|
1019
|
+
elsif @string.nil?
|
|
1020
|
+
# generate string for out-of-order append
|
|
1021
|
+
head, comma = normalized_string, ","
|
|
1022
|
+
else
|
|
1023
|
+
# @string already exists... maybe coalesce with last entry
|
|
1024
|
+
head, comma, last_entry = @string.rpartition(",")
|
|
1025
|
+
last_min, last_max = import_minmax last_entry
|
|
1026
|
+
if last_max == adj
|
|
1027
|
+
# coalesce with last entry
|
|
1028
|
+
minmax[0] = last_min
|
|
1029
|
+
else
|
|
1030
|
+
# append to existing string
|
|
1031
|
+
head, comma = @string, ","
|
|
1032
|
+
end
|
|
1033
|
+
end
|
|
1034
|
+
entry = export_minmax minmax
|
|
1035
|
+
add_minmax minmax
|
|
1036
|
+
@string = -"#{head}#{comma}#{entry}"
|
|
969
1037
|
self
|
|
970
1038
|
end
|
|
971
1039
|
|
|
@@ -991,8 +1059,8 @@ module Net
|
|
|
991
1059
|
#
|
|
992
1060
|
# Related: #delete?, #delete_at, #subtract, #difference
|
|
993
1061
|
def delete(element)
|
|
994
|
-
modifying! # short-circuit before
|
|
995
|
-
|
|
1062
|
+
modifying! # short-circuit before import_run
|
|
1063
|
+
subtract_run import_run element
|
|
996
1064
|
normalize!
|
|
997
1065
|
end
|
|
998
1066
|
|
|
@@ -1029,17 +1097,17 @@ module Net
|
|
|
1029
1097
|
#
|
|
1030
1098
|
# Related: #delete, #delete_at, #subtract, #difference, #disjoint?
|
|
1031
1099
|
def delete?(element)
|
|
1032
|
-
modifying! # short-circuit before
|
|
1100
|
+
modifying! # short-circuit before import_minmax
|
|
1033
1101
|
element = input_try_convert(element)
|
|
1034
|
-
|
|
1102
|
+
minmax = import_minmax element
|
|
1035
1103
|
if number_input?(element)
|
|
1036
|
-
return unless
|
|
1037
|
-
|
|
1104
|
+
return unless include_minmax? minmax
|
|
1105
|
+
subtract_minmax minmax
|
|
1038
1106
|
normalize!
|
|
1039
|
-
|
|
1107
|
+
export_num minmax.first
|
|
1040
1108
|
else
|
|
1041
1109
|
copy = dup
|
|
1042
|
-
|
|
1110
|
+
subtract_minmax minmax
|
|
1043
1111
|
normalize!
|
|
1044
1112
|
copy if copy.subtract(self).valid?
|
|
1045
1113
|
end
|
|
@@ -1076,8 +1144,8 @@ module Net
|
|
|
1076
1144
|
deleted
|
|
1077
1145
|
end
|
|
1078
1146
|
|
|
1079
|
-
# Merges all of the elements that appear in any of
|
|
1080
|
-
# set, and returns +self+.
|
|
1147
|
+
# In-place set #union. Merges all of the elements that appear in any of
|
|
1148
|
+
# the +sets+ into this set, and returns +self+.
|
|
1081
1149
|
#
|
|
1082
1150
|
# The +sets+ may be any objects that would be accepted by ::new.
|
|
1083
1151
|
#
|
|
@@ -1085,19 +1153,20 @@ module Net
|
|
|
1085
1153
|
#
|
|
1086
1154
|
# Related: #add, #add?, #union
|
|
1087
1155
|
def merge(*sets)
|
|
1088
|
-
modifying! # short-circuit before
|
|
1089
|
-
|
|
1156
|
+
modifying! # short-circuit before import_runs
|
|
1157
|
+
add_runs import_runs sets
|
|
1090
1158
|
normalize!
|
|
1091
1159
|
end
|
|
1092
1160
|
|
|
1093
|
-
# Removes all of the elements that appear in
|
|
1094
|
-
# the set, and returns +self+.
|
|
1161
|
+
# In-place set #difference. Removes all of the elements that appear in
|
|
1162
|
+
# any of the given +sets+ from this set, and returns +self+.
|
|
1095
1163
|
#
|
|
1096
1164
|
# The +sets+ may be any objects that would be accepted by ::new.
|
|
1097
1165
|
#
|
|
1098
1166
|
# Related: #difference
|
|
1099
1167
|
def subtract(*sets)
|
|
1100
|
-
|
|
1168
|
+
modifying! # short-circuit before import_runs
|
|
1169
|
+
subtract_runs import_runs sets
|
|
1101
1170
|
normalize!
|
|
1102
1171
|
end
|
|
1103
1172
|
|
|
@@ -1189,7 +1258,7 @@ module Net
|
|
|
1189
1258
|
# Related: #entries, #each_element
|
|
1190
1259
|
def each_entry(&block) # :yields: integer or range or :*
|
|
1191
1260
|
return to_enum(__method__) unless block_given?
|
|
1192
|
-
|
|
1261
|
+
each_entry_run do yield export_run_entry _1 end
|
|
1193
1262
|
end
|
|
1194
1263
|
|
|
1195
1264
|
# Yields each number or range (or <tt>:*</tt>) in #elements to the block
|
|
@@ -1201,39 +1270,17 @@ module Net
|
|
|
1201
1270
|
# Related: #elements, #each_entry
|
|
1202
1271
|
def each_element # :yields: integer or range or :*
|
|
1203
1272
|
return to_enum(__method__) unless block_given?
|
|
1204
|
-
|
|
1205
|
-
self
|
|
1206
|
-
end
|
|
1207
|
-
|
|
1208
|
-
private
|
|
1209
|
-
|
|
1210
|
-
def each_entry_tuple(&block)
|
|
1211
|
-
return to_enum(__method__) unless block_given?
|
|
1212
|
-
if @string
|
|
1213
|
-
@string.split(",") do block.call str_to_tuple _1 end
|
|
1214
|
-
else
|
|
1215
|
-
@tuples.each(&block)
|
|
1216
|
-
end
|
|
1273
|
+
runs.each do yield export_run_entry _1 end
|
|
1217
1274
|
self
|
|
1218
1275
|
end
|
|
1219
1276
|
|
|
1220
|
-
def tuple_to_entry((min, max))
|
|
1221
|
-
if min == STAR_INT then :*
|
|
1222
|
-
elsif max == STAR_INT then min..
|
|
1223
|
-
elsif min == max then min
|
|
1224
|
-
else min..max
|
|
1225
|
-
end
|
|
1226
|
-
end
|
|
1227
|
-
|
|
1228
|
-
public
|
|
1229
|
-
|
|
1230
1277
|
# Yields each range in #ranges to the block and returns self.
|
|
1231
1278
|
# Returns an enumerator when called without a block.
|
|
1232
1279
|
#
|
|
1233
1280
|
# Related: #ranges
|
|
1234
1281
|
def each_range # :yields: range
|
|
1235
1282
|
return to_enum(__method__) unless block_given?
|
|
1236
|
-
|
|
1283
|
+
minmaxes.each do |min, max|
|
|
1237
1284
|
if min == STAR_INT then yield :*..
|
|
1238
1285
|
elsif max == STAR_INT then yield min..
|
|
1239
1286
|
else yield min..max
|
|
@@ -1252,7 +1299,7 @@ module Net
|
|
|
1252
1299
|
def each_number(&block) # :yields: integer
|
|
1253
1300
|
return to_enum(__method__) unless block_given?
|
|
1254
1301
|
raise RangeError, '%s contains "*"' % [self.class] if include_star?
|
|
1255
|
-
|
|
1302
|
+
minmaxes.each do each_number_in_minmax _1, _2, &block end
|
|
1256
1303
|
self
|
|
1257
1304
|
end
|
|
1258
1305
|
|
|
@@ -1266,16 +1313,7 @@ module Net
|
|
|
1266
1313
|
def each_ordered_number(&block)
|
|
1267
1314
|
return to_enum(__method__) unless block_given?
|
|
1268
1315
|
raise RangeError, '%s contains "*"' % [self.class] if include_star?
|
|
1269
|
-
|
|
1270
|
-
end
|
|
1271
|
-
|
|
1272
|
-
private def each_number_in_tuple(min, max, &block)
|
|
1273
|
-
if min == STAR_INT then yield :*
|
|
1274
|
-
elsif min == max then yield min
|
|
1275
|
-
elsif max != STAR_INT then (min..max).each(&block)
|
|
1276
|
-
else
|
|
1277
|
-
raise RangeError, "#{SequenceSet} cannot enumerate range with '*'"
|
|
1278
|
-
end
|
|
1316
|
+
each_entry_minmax do each_number_in_minmax _1, _2, &block end
|
|
1279
1317
|
end
|
|
1280
1318
|
|
|
1281
1319
|
# Returns a Set with all of the #numbers in the sequence set.
|
|
@@ -1287,35 +1325,103 @@ module Net
|
|
|
1287
1325
|
# Related: #elements, #ranges, #numbers
|
|
1288
1326
|
def to_set; Set.new(numbers) end
|
|
1289
1327
|
|
|
1290
|
-
# Returns the
|
|
1328
|
+
# Returns the number of members in the set.
|
|
1329
|
+
#
|
|
1330
|
+
# Unlike #count, <tt>"*"</tt> is considered to be distinct from
|
|
1331
|
+
# <tt>2³² - 1</tt> (the maximum 32-bit unsigned integer value).
|
|
1332
|
+
#
|
|
1333
|
+
# set = Net::IMAP::SequenceSet[1..10]
|
|
1334
|
+
# set.count #=> 10
|
|
1335
|
+
# set.cardinality #=> 10
|
|
1336
|
+
#
|
|
1337
|
+
# set = Net::IMAP::SequenceSet["4294967295,*"]
|
|
1338
|
+
# set.count #=> 1
|
|
1339
|
+
# set.cardinality #=> 2
|
|
1340
|
+
#
|
|
1341
|
+
# set = Net::IMAP::SequenceSet[1..]
|
|
1342
|
+
# set.count #=> 4294967295
|
|
1343
|
+
# set.cardinality #=> 4294967296
|
|
1344
|
+
#
|
|
1345
|
+
# Related: #count, #count_with_duplicates
|
|
1346
|
+
def cardinality = minmaxes.sum(runs.count) { _2 - _1 }
|
|
1347
|
+
|
|
1348
|
+
# Returns the count of distinct #numbers in the set.
|
|
1291
1349
|
#
|
|
1292
|
-
#
|
|
1293
|
-
# unsigned integer value).
|
|
1350
|
+
# Unlike #cardinality, <tt>"*"</tt> is considered to be equal to
|
|
1351
|
+
# <tt>2³² - 1</tt> (the maximum 32-bit unsigned integer value).
|
|
1294
1352
|
#
|
|
1295
|
-
#
|
|
1353
|
+
# set = Net::IMAP::SequenceSet[1..10]
|
|
1354
|
+
# set.count #=> 10
|
|
1355
|
+
# set.cardinality #=> 10
|
|
1356
|
+
#
|
|
1357
|
+
# set = Net::IMAP::SequenceSet["4294967295,*"]
|
|
1358
|
+
# set.count #=> 1
|
|
1359
|
+
# set.cardinality #=> 2
|
|
1360
|
+
#
|
|
1361
|
+
# set = Net::IMAP::SequenceSet[1..]
|
|
1362
|
+
# set.count #=> 4294967295
|
|
1363
|
+
# set.cardinality #=> 4294967296
|
|
1364
|
+
#
|
|
1365
|
+
# Related: #cardinality, #count_with_duplicates
|
|
1296
1366
|
def count
|
|
1297
|
-
|
|
1298
|
-
(include_star? && include?(UINT32_MAX) ? -1 : 0)
|
|
1367
|
+
cardinality + (include_star? && include?(UINT32_MAX) ? -1 : 0)
|
|
1299
1368
|
end
|
|
1300
1369
|
|
|
1301
|
-
alias size count
|
|
1302
|
-
|
|
1303
1370
|
# Returns the count of numbers in the ordered #entries, including any
|
|
1304
1371
|
# repeated numbers.
|
|
1305
1372
|
#
|
|
1306
|
-
#
|
|
1307
|
-
#
|
|
1308
|
-
#
|
|
1309
|
-
#
|
|
1310
|
-
#
|
|
1311
|
-
#
|
|
1373
|
+
# When #string is normalized, this returns the same as #count. Like
|
|
1374
|
+
# #count, <tt>"*"</tt> is considered to be equal to <tt>2³² - 1</tt> (the
|
|
1375
|
+
# maximum 32-bit unsigned integer value).
|
|
1376
|
+
#
|
|
1377
|
+
# In a range, <tt>"*"</tt> is _not_ considered a duplicate:
|
|
1378
|
+
# set = Net::IMAP::SequenceSet["4294967295:*"]
|
|
1379
|
+
# set.count_with_duplicates #=> 1
|
|
1380
|
+
# set.size #=> 2
|
|
1381
|
+
# set.count #=> 1
|
|
1382
|
+
# set.cardinality #=> 2
|
|
1383
|
+
#
|
|
1384
|
+
# In a separate entry, <tt>"*"</tt> _is_ considered a duplicate:
|
|
1385
|
+
# set = Net::IMAP::SequenceSet["4294967295,*"]
|
|
1386
|
+
# set.count_with_duplicates #=> 2
|
|
1387
|
+
# set.size #=> 2
|
|
1388
|
+
# set.count #=> 1
|
|
1389
|
+
# set.cardinality #=> 2
|
|
1390
|
+
#
|
|
1391
|
+
# Related: #count, #cardinality, #size, #count_duplicates,
|
|
1392
|
+
# #has_duplicates?, #entries
|
|
1312
1393
|
def count_with_duplicates
|
|
1313
1394
|
return count unless @string
|
|
1314
|
-
|
|
1395
|
+
each_entry_minmax.sum {|min, max|
|
|
1315
1396
|
max - min + ((max == STAR_INT && min != STAR_INT) ? 0 : 1)
|
|
1316
1397
|
}
|
|
1317
1398
|
end
|
|
1318
1399
|
|
|
1400
|
+
# Returns the combined size of the ordered #entries, including any
|
|
1401
|
+
# repeated numbers.
|
|
1402
|
+
#
|
|
1403
|
+
# When #string is normalized, this returns the same as #cardinality.
|
|
1404
|
+
# Like #cardinality, <tt>"*"</tt> is considered to be be distinct from
|
|
1405
|
+
# <tt>2³² - 1</tt> (the maximum 32-bit unsigned integer value).
|
|
1406
|
+
#
|
|
1407
|
+
# set = Net::IMAP::SequenceSet["4294967295:*"]
|
|
1408
|
+
# set.size #=> 2
|
|
1409
|
+
# set.count_with_duplicates #=> 1
|
|
1410
|
+
# set.count #=> 1
|
|
1411
|
+
# set.cardinality #=> 2
|
|
1412
|
+
#
|
|
1413
|
+
# set = Net::IMAP::SequenceSet["4294967295,*"]
|
|
1414
|
+
# set.size #=> 2
|
|
1415
|
+
# set.count_with_duplicates #=> 2
|
|
1416
|
+
# set.count #=> 1
|
|
1417
|
+
# set.cardinality #=> 2
|
|
1418
|
+
#
|
|
1419
|
+
# Related: #cardinality, #count_with_duplicates, #count, #entries
|
|
1420
|
+
def size
|
|
1421
|
+
return cardinality unless @string
|
|
1422
|
+
each_entry_minmax.sum {|min, max| max - min + 1 }
|
|
1423
|
+
end
|
|
1424
|
+
|
|
1319
1425
|
# Returns the count of repeated numbers in the ordered #entries, the
|
|
1320
1426
|
# difference between #count_with_duplicates and #count.
|
|
1321
1427
|
#
|
|
@@ -1333,7 +1439,7 @@ module Net
|
|
|
1333
1439
|
#
|
|
1334
1440
|
# Always returns +false+ when #string is normalized.
|
|
1335
1441
|
#
|
|
1336
|
-
# Related: #entries, #count_with_duplicates, #count_duplicates
|
|
1442
|
+
# Related: #entries, #count_with_duplicates, #count_duplicates
|
|
1337
1443
|
def has_duplicates?
|
|
1338
1444
|
return false unless @string
|
|
1339
1445
|
count_with_duplicates != count
|
|
@@ -1344,10 +1450,10 @@ module Net
|
|
|
1344
1450
|
#
|
|
1345
1451
|
# Related: #[], #at, #find_ordered_index
|
|
1346
1452
|
def find_index(number)
|
|
1347
|
-
number =
|
|
1348
|
-
|
|
1453
|
+
number = import_num number
|
|
1454
|
+
each_minmax_with_index(minmaxes) do |min, max, idx_min|
|
|
1349
1455
|
number < min and return nil
|
|
1350
|
-
number <= max and return
|
|
1456
|
+
number <= max and return export_num(idx_min + (number - min))
|
|
1351
1457
|
end
|
|
1352
1458
|
nil
|
|
1353
1459
|
end
|
|
@@ -1357,38 +1463,15 @@ module Net
|
|
|
1357
1463
|
#
|
|
1358
1464
|
# Related: #find_index
|
|
1359
1465
|
def find_ordered_index(number)
|
|
1360
|
-
number =
|
|
1361
|
-
|
|
1466
|
+
number = import_num number
|
|
1467
|
+
each_minmax_with_index(each_entry_minmax) do |min, max, idx_min|
|
|
1362
1468
|
if min <= number && number <= max
|
|
1363
|
-
return
|
|
1469
|
+
return export_num(idx_min + (number - min))
|
|
1364
1470
|
end
|
|
1365
1471
|
end
|
|
1366
1472
|
nil
|
|
1367
1473
|
end
|
|
1368
1474
|
|
|
1369
|
-
private
|
|
1370
|
-
|
|
1371
|
-
def each_tuple_with_index(tuples)
|
|
1372
|
-
idx_min = 0
|
|
1373
|
-
tuples.each do |min, max|
|
|
1374
|
-
idx_max = idx_min + (max - min)
|
|
1375
|
-
yield min, max, idx_min, idx_max
|
|
1376
|
-
idx_min = idx_max + 1
|
|
1377
|
-
end
|
|
1378
|
-
idx_min
|
|
1379
|
-
end
|
|
1380
|
-
|
|
1381
|
-
def reverse_each_tuple_with_index(tuples)
|
|
1382
|
-
idx_max = -1
|
|
1383
|
-
tuples.reverse_each do |min, max|
|
|
1384
|
-
yield min, max, (idx_min = idx_max - (max - min)), idx_max
|
|
1385
|
-
idx_max = idx_min - 1
|
|
1386
|
-
end
|
|
1387
|
-
idx_max
|
|
1388
|
-
end
|
|
1389
|
-
|
|
1390
|
-
public
|
|
1391
|
-
|
|
1392
1475
|
# :call-seq: at(index) -> integer or nil
|
|
1393
1476
|
#
|
|
1394
1477
|
# Returns the number at the given +index+ in the sorted set, without
|
|
@@ -1399,7 +1482,7 @@ module Net
|
|
|
1399
1482
|
#
|
|
1400
1483
|
# Related: #[], #slice, #ordered_at
|
|
1401
1484
|
def at(index)
|
|
1402
|
-
|
|
1485
|
+
seek_number_in_minmaxes(minmaxes, index)
|
|
1403
1486
|
end
|
|
1404
1487
|
|
|
1405
1488
|
# :call-seq: ordered_at(index) -> integer or nil
|
|
@@ -1412,21 +1495,7 @@ module Net
|
|
|
1412
1495
|
#
|
|
1413
1496
|
# Related: #[], #slice, #ordered_at
|
|
1414
1497
|
def ordered_at(index)
|
|
1415
|
-
|
|
1416
|
-
end
|
|
1417
|
-
|
|
1418
|
-
private def lookup_number_by_tuple_index(tuples, index)
|
|
1419
|
-
index = Integer(index.to_int)
|
|
1420
|
-
if index.negative?
|
|
1421
|
-
reverse_each_tuple_with_index(tuples) do |min, max, idx_min, idx_max|
|
|
1422
|
-
idx_min <= index and return from_tuple_int(min + (index - idx_min))
|
|
1423
|
-
end
|
|
1424
|
-
else
|
|
1425
|
-
each_tuple_with_index(tuples) do |min, _, idx_min, idx_max|
|
|
1426
|
-
index <= idx_max and return from_tuple_int(min + (index - idx_min))
|
|
1427
|
-
end
|
|
1428
|
-
end
|
|
1429
|
-
nil
|
|
1498
|
+
seek_number_in_minmaxes(each_entry_minmax, index)
|
|
1430
1499
|
end
|
|
1431
1500
|
|
|
1432
1501
|
# :call-seq:
|
|
@@ -1477,37 +1546,6 @@ module Net
|
|
|
1477
1546
|
|
|
1478
1547
|
alias slice :[]
|
|
1479
1548
|
|
|
1480
|
-
private
|
|
1481
|
-
|
|
1482
|
-
def slice_length(start, length)
|
|
1483
|
-
start = Integer(start.to_int)
|
|
1484
|
-
length = Integer(length.to_int)
|
|
1485
|
-
raise ArgumentError, "length must be positive" unless length.positive?
|
|
1486
|
-
last = start + length - 1 unless start.negative? && start.abs <= length
|
|
1487
|
-
slice_range(start..last)
|
|
1488
|
-
end
|
|
1489
|
-
|
|
1490
|
-
def slice_range(range)
|
|
1491
|
-
first = range.begin || 0
|
|
1492
|
-
last = range.end || -1
|
|
1493
|
-
if range.exclude_end?
|
|
1494
|
-
return remain_frozen_empty if last.zero?
|
|
1495
|
-
last -= 1 if range.end && last != STAR_INT
|
|
1496
|
-
end
|
|
1497
|
-
if (first * last).positive? && last < first
|
|
1498
|
-
remain_frozen_empty
|
|
1499
|
-
elsif (min = at(first))
|
|
1500
|
-
max = at(last)
|
|
1501
|
-
max = :* if max.nil?
|
|
1502
|
-
if max == :* then self & (min..)
|
|
1503
|
-
elsif min <= max then self & (min..max)
|
|
1504
|
-
else remain_frozen_empty
|
|
1505
|
-
end
|
|
1506
|
-
end
|
|
1507
|
-
end
|
|
1508
|
-
|
|
1509
|
-
public
|
|
1510
|
-
|
|
1511
1549
|
# Returns a copy of +self+ which only contains the numbers above +num+.
|
|
1512
1550
|
#
|
|
1513
1551
|
# Net::IMAP::SequenceSet["5,10:22,50"].above(10) # to_s => "11:22,50"
|
|
@@ -1579,7 +1617,7 @@ module Net
|
|
|
1579
1617
|
#
|
|
1580
1618
|
# Related: #limit!
|
|
1581
1619
|
def limit(max:)
|
|
1582
|
-
max =
|
|
1620
|
+
max = import_num(max)
|
|
1583
1621
|
if empty? then self.class.empty
|
|
1584
1622
|
elsif !include_star? && max < min then self.class.empty
|
|
1585
1623
|
elsif max(star: STAR_INT) <= max then frozen? ? self : dup.freeze
|
|
@@ -1592,53 +1630,134 @@ module Net
|
|
|
1592
1630
|
#
|
|
1593
1631
|
# Related: #limit
|
|
1594
1632
|
def limit!(max:)
|
|
1595
|
-
modifying! # short-circuit
|
|
1633
|
+
modifying! # short-circuit before querying
|
|
1596
1634
|
star = include_star?
|
|
1597
|
-
max =
|
|
1598
|
-
|
|
1599
|
-
|
|
1635
|
+
max = import_num(max)
|
|
1636
|
+
subtract_minmax [max + 1, STAR_INT]
|
|
1637
|
+
add_minmax [max, max ] if star
|
|
1600
1638
|
normalize!
|
|
1601
1639
|
end
|
|
1602
1640
|
|
|
1603
1641
|
# :call-seq: complement! -> self
|
|
1604
1642
|
#
|
|
1605
|
-
#
|
|
1606
|
-
# possible values _except_ for those
|
|
1643
|
+
# In-place set #complement. Replaces the contents of this set with its
|
|
1644
|
+
# own #complement. It will contain all possible values _except_ for those
|
|
1645
|
+
# currently in the set.
|
|
1607
1646
|
#
|
|
1608
1647
|
# Related: #complement
|
|
1609
1648
|
def complement!
|
|
1610
|
-
modifying! # short-circuit
|
|
1649
|
+
modifying! # short-circuit before querying
|
|
1611
1650
|
return replace(self.class.full) if empty?
|
|
1612
1651
|
return clear if full?
|
|
1613
|
-
flat =
|
|
1652
|
+
flat = minmaxes.flat_map { [_1 - 1, _2 + 1] }
|
|
1614
1653
|
if flat.first < 1 then flat.shift else flat.unshift 1 end
|
|
1615
1654
|
if STAR_INT < flat.last then flat.pop else flat.push STAR_INT end
|
|
1616
|
-
|
|
1655
|
+
replace_minmaxes flat.each_slice(2).to_a
|
|
1617
1656
|
normalize!
|
|
1618
1657
|
end
|
|
1619
1658
|
|
|
1620
|
-
#
|
|
1659
|
+
# In-place set #intersection. Removes any elements that are missing from
|
|
1660
|
+
# +other+ from this set, keeping only the #intersection, and returns
|
|
1661
|
+
# +self+.
|
|
1662
|
+
#
|
|
1663
|
+
# +other+ can be any object that would be accepted by ::new.
|
|
1664
|
+
#
|
|
1665
|
+
# set = Net::IMAP::SequenceSet.new(1..5)
|
|
1666
|
+
# set.intersect! [2, 4, 6]
|
|
1667
|
+
# set #=> Net::IMAP::SequenceSet("2,4")
|
|
1668
|
+
#
|
|
1669
|
+
# Related: #intersection, #intersect?
|
|
1670
|
+
def intersect!(other)
|
|
1671
|
+
modifying! # short-circuit before processing input
|
|
1672
|
+
subtract SequenceSet.new(other).complement!
|
|
1673
|
+
end
|
|
1674
|
+
|
|
1675
|
+
# In-place set #xor. Adds any numbers in +other+ that are missing from
|
|
1676
|
+
# this set, removes any numbers in +other+ that are already in this set,
|
|
1677
|
+
# and returns +self+.
|
|
1678
|
+
#
|
|
1679
|
+
# +other+ can be any object that would be accepted by ::new.
|
|
1680
|
+
#
|
|
1681
|
+
# set = Net::IMAP::SequenceSet.new(1..5)
|
|
1682
|
+
# set.xor! [2, 4, 6]
|
|
1683
|
+
# set #=> Net::IMAP::SequenceSet["1,3,5:6"]
|
|
1684
|
+
#
|
|
1685
|
+
# Related: #xor, #merge, #subtract
|
|
1686
|
+
def xor!(other)
|
|
1687
|
+
modifying! # short-circuit before processing input
|
|
1688
|
+
other = SequenceSet.new(other)
|
|
1689
|
+
copy = dup
|
|
1690
|
+
merge(other).subtract(other.subtract(copy.complement!))
|
|
1691
|
+
end
|
|
1692
|
+
|
|
1693
|
+
# Returns whether #string is fully normalized: entries have been sorted,
|
|
1694
|
+
# deduplicated, and coalesced, and all entries are in normal form. See
|
|
1695
|
+
# SequenceSet@Ordered+and+Normalized+sets.
|
|
1696
|
+
#
|
|
1697
|
+
# Net::IMAP::SequenceSet["1,3,5"].normalized? #=> true
|
|
1698
|
+
# Net::IMAP::SequenceSet["20:30"].normalized? #=> true
|
|
1699
|
+
#
|
|
1700
|
+
# Net::IMAP::SequenceSet["3,5,1"].normalized? #=> false, not sorted
|
|
1701
|
+
# Net::IMAP::SequenceSet["1,2,3"].normalized? #=> false, not coalesced
|
|
1702
|
+
# Net::IMAP::SequenceSet["1:5,2"].normalized? #=> false, repeated number
|
|
1703
|
+
#
|
|
1704
|
+
# Net::IMAP::SequenceSet["1:1"].normalized? #=> false, number as range
|
|
1705
|
+
# Net::IMAP::SequenceSet["5:1"].normalized? #=> false, backwards range
|
|
1706
|
+
#
|
|
1707
|
+
# Returns +true+ if (and only if) #string is equal to #normalized_string:
|
|
1708
|
+
# seqset = Net::IMAP::SequenceSet["1:3,5"]
|
|
1709
|
+
# seqset.string #=> "1:3,5"
|
|
1710
|
+
# seqset.normalized_string #=> "1:3,5"
|
|
1711
|
+
# seqset.entries #=> [1..3, 5]
|
|
1712
|
+
# seqset.elements #=> [1..3, 5]
|
|
1713
|
+
# seqset.normalized? #=> true
|
|
1714
|
+
#
|
|
1715
|
+
# seqset = Net::IMAP::SequenceSet["3,1,2"]
|
|
1716
|
+
# seqset.string #=> "3,1,2"
|
|
1717
|
+
# seqset.normalized_string #=> "1:3"
|
|
1718
|
+
# seqset.entries #=> [3, 1, 2]
|
|
1719
|
+
# seqset.elements #=> [1..3]
|
|
1720
|
+
# seqset.normalized? #=> false
|
|
1721
|
+
#
|
|
1722
|
+
# Can return +false+ even when #entries and #elements are the same:
|
|
1723
|
+
# seqset = Net::IMAP::SequenceSet["5:1"]
|
|
1724
|
+
# seqset.string #=> "5:1"
|
|
1725
|
+
# seqset.normalized_string #=> "1:5"
|
|
1726
|
+
# seqset.entries #=> [1..5]
|
|
1727
|
+
# seqset.elements #=> [1..5]
|
|
1728
|
+
# seqset.normalized? #=> false
|
|
1729
|
+
#
|
|
1730
|
+
# Note that empty sets are normalized, even though they are not #valid?:
|
|
1731
|
+
# seqset = Net::IMAP::SequenceSet.empty
|
|
1732
|
+
# seqset.normalized? #=> true
|
|
1733
|
+
# seqset.valid? #=> false
|
|
1734
|
+
#
|
|
1735
|
+
# Related: #normalize, #normalize!, #normalized_string
|
|
1736
|
+
def normalized?
|
|
1737
|
+
@string.nil? || normal_string?(@string)
|
|
1738
|
+
end
|
|
1739
|
+
|
|
1740
|
+
# Returns a SequenceSet with a normalized string representation: entries
|
|
1741
|
+
# have been sorted, deduplicated, and coalesced, and all entries
|
|
1742
|
+
# are in normal form. Returns +self+ for frozen normalized sets, and a
|
|
1743
|
+
# normalized duplicate otherwise.
|
|
1621
1744
|
#
|
|
1622
|
-
# The returned set's #string is sorted and deduplicated. Adjacent or
|
|
1623
|
-
# overlapping elements will be merged into a single larger range.
|
|
1624
1745
|
# See SequenceSet@Ordered+and+Normalized+sets.
|
|
1625
1746
|
#
|
|
1626
1747
|
# Net::IMAP::SequenceSet["1:5,3:7,10:9,10:11"].normalize
|
|
1627
1748
|
# #=> Net::IMAP::SequenceSet["1:7,9:11"]
|
|
1628
1749
|
#
|
|
1629
|
-
# Related: #normalize!, #normalized_string
|
|
1750
|
+
# Related: #normalize!, #normalized_string, #normalized?
|
|
1630
1751
|
def normalize
|
|
1631
|
-
|
|
1632
|
-
return self if frozen? && str == string
|
|
1633
|
-
remain_frozen dup.instance_exec { @string = str&.-@; self }
|
|
1752
|
+
frozen? && normalized? ? self : remain_frozen(dup.normalize!)
|
|
1634
1753
|
end
|
|
1635
1754
|
|
|
1636
1755
|
# Resets #string to be sorted, deduplicated, and coalesced. Returns
|
|
1637
1756
|
# +self+. See SequenceSet@Ordered+and+Normalized+sets.
|
|
1638
1757
|
#
|
|
1639
|
-
# Related: #normalize, #normalized_string
|
|
1758
|
+
# Related: #normalize, #normalized_string, #normalized?
|
|
1640
1759
|
def normalize!
|
|
1641
|
-
modifying! # redundant check
|
|
1760
|
+
modifying! # redundant check (normalizes the error message for JRuby)
|
|
1642
1761
|
@string = nil
|
|
1643
1762
|
self
|
|
1644
1763
|
end
|
|
@@ -1652,9 +1771,9 @@ module Net
|
|
|
1652
1771
|
#
|
|
1653
1772
|
# Returns +nil+ when the set is empty.
|
|
1654
1773
|
#
|
|
1655
|
-
# Related: #normalize!, #normalize, #string, #to_s
|
|
1774
|
+
# Related: #normalize!, #normalize, #string, #to_s, #normalized?
|
|
1656
1775
|
def normalized_string
|
|
1657
|
-
|
|
1776
|
+
export_runs(runs) unless runs.empty?
|
|
1658
1777
|
end
|
|
1659
1778
|
|
|
1660
1779
|
# Returns an inspection string for the SequenceSet.
|
|
@@ -1691,8 +1810,8 @@ module Net
|
|
|
1691
1810
|
head = @string[INSPECT_ABRIDGED_HEAD_RE]
|
|
1692
1811
|
tail = @string[INSPECT_ABRIDGED_TAIL_RE]
|
|
1693
1812
|
else
|
|
1694
|
-
head =
|
|
1695
|
-
tail = "," +
|
|
1813
|
+
head = export_runs(runs.first(INSPECT_TRUNCATE_LEN)) + ","
|
|
1814
|
+
tail = "," + export_runs(runs.last(INSPECT_TRUNCATE_LEN))
|
|
1696
1815
|
end
|
|
1697
1816
|
'#<%s %d entries "%s...(%d entries omitted)...%s"%s>' % [
|
|
1698
1817
|
self.class, count,
|
|
@@ -1702,10 +1821,6 @@ module Net
|
|
|
1702
1821
|
end
|
|
1703
1822
|
end
|
|
1704
1823
|
|
|
1705
|
-
private def count_entries
|
|
1706
|
-
@string ? @string.count(",") + 1 : @tuples.count
|
|
1707
|
-
end
|
|
1708
|
-
|
|
1709
1824
|
##
|
|
1710
1825
|
# :method: to_sequence_set
|
|
1711
1826
|
# :call-seq: to_sequence_set -> self
|
|
@@ -1736,15 +1851,17 @@ module Net
|
|
|
1736
1851
|
|
|
1737
1852
|
# For YAML deserialization
|
|
1738
1853
|
def init_with(coder) # :nodoc:
|
|
1739
|
-
@
|
|
1854
|
+
@set_data = new_set_data
|
|
1740
1855
|
self.string = coder['string']
|
|
1741
1856
|
end
|
|
1742
1857
|
|
|
1858
|
+
# :stopdoc:
|
|
1743
1859
|
protected
|
|
1744
1860
|
|
|
1745
|
-
attr_reader :
|
|
1861
|
+
attr_reader :set_data
|
|
1746
1862
|
|
|
1747
|
-
|
|
1863
|
+
alias runs set_data
|
|
1864
|
+
alias minmaxes runs
|
|
1748
1865
|
|
|
1749
1866
|
private
|
|
1750
1867
|
|
|
@@ -1753,38 +1870,42 @@ module Net
|
|
|
1753
1870
|
|
|
1754
1871
|
# frozen clones are shallow copied
|
|
1755
1872
|
def initialize_clone(other)
|
|
1756
|
-
@
|
|
1873
|
+
@set_data = other.dup_set_data unless other.frozen?
|
|
1757
1874
|
super
|
|
1758
1875
|
end
|
|
1759
1876
|
|
|
1760
1877
|
def initialize_dup(other)
|
|
1761
|
-
@
|
|
1878
|
+
@set_data = other.dup_set_data
|
|
1762
1879
|
super
|
|
1763
1880
|
end
|
|
1764
1881
|
|
|
1765
|
-
|
|
1766
|
-
|
|
1882
|
+
######################################################################{{{2
|
|
1883
|
+
# Import methods
|
|
1884
|
+
|
|
1885
|
+
def import_minmax(input)
|
|
1886
|
+
entry = input_try_convert input
|
|
1767
1887
|
case entry
|
|
1768
|
-
when *STARS, Integer then [int =
|
|
1769
|
-
when Range then
|
|
1770
|
-
when String then
|
|
1888
|
+
when *STARS, Integer then [int = import_num(entry), int]
|
|
1889
|
+
when Range then import_range_minmax(entry)
|
|
1890
|
+
when String then parse_minmax(entry)
|
|
1771
1891
|
else
|
|
1772
|
-
raise DataFormatError, "expected number or range, got %p" % [
|
|
1892
|
+
raise DataFormatError, "expected number or range, got %p" % [input]
|
|
1773
1893
|
end
|
|
1774
1894
|
end
|
|
1895
|
+
alias import_run import_minmax
|
|
1775
1896
|
|
|
1776
|
-
def
|
|
1777
|
-
set = input_try_convert
|
|
1897
|
+
def import_runs(input)
|
|
1898
|
+
set = input_try_convert input
|
|
1778
1899
|
case set
|
|
1779
|
-
when *STARS, Integer, Range then [
|
|
1780
|
-
when String then
|
|
1781
|
-
when SequenceSet then set.
|
|
1782
|
-
when Set then set.map { [
|
|
1783
|
-
when Array then set.flat_map {
|
|
1900
|
+
when *STARS, Integer, Range then [import_run(set)]
|
|
1901
|
+
when String then parse_runs set
|
|
1902
|
+
when SequenceSet then set.runs
|
|
1903
|
+
when Set then set.map { [import_num(_1)] * 2 }
|
|
1904
|
+
when Array then set.flat_map { import_runs _1 }
|
|
1784
1905
|
when nil then []
|
|
1785
1906
|
else
|
|
1786
1907
|
raise DataFormatError, "expected nz-number, range, '*', Set, Array; " \
|
|
1787
|
-
"got %p" % [
|
|
1908
|
+
"got %p" % [input]
|
|
1788
1909
|
end
|
|
1789
1910
|
end
|
|
1790
1911
|
|
|
@@ -1805,9 +1926,9 @@ module Net
|
|
|
1805
1926
|
end
|
|
1806
1927
|
end
|
|
1807
1928
|
|
|
1808
|
-
def
|
|
1809
|
-
first =
|
|
1810
|
-
last =
|
|
1929
|
+
def import_range_minmax(range)
|
|
1930
|
+
first = import_num(range.begin || 1)
|
|
1931
|
+
last = import_num(range.end || :*)
|
|
1811
1932
|
last -= 1 if range.exclude_end? && range.end && last != STAR_INT
|
|
1812
1933
|
unless first <= last
|
|
1813
1934
|
raise DataFormatError, "invalid range for sequence-set: %p" % [range]
|
|
@@ -1815,71 +1936,260 @@ module Net
|
|
|
1815
1936
|
[first, last]
|
|
1816
1937
|
end
|
|
1817
1938
|
|
|
1818
|
-
def
|
|
1819
|
-
def
|
|
1939
|
+
def import_num(obj) STARS.include?(obj) ? STAR_INT : nz_number(obj) end
|
|
1940
|
+
def nz_number(num) = NumValidator.coerce_nz_number(num)
|
|
1941
|
+
|
|
1942
|
+
######################################################################{{{2
|
|
1943
|
+
# Export methods
|
|
1944
|
+
|
|
1945
|
+
def export_num(num) num == STAR_INT ? :* : num end
|
|
1946
|
+
|
|
1947
|
+
def export_minmaxes(minmaxes)
|
|
1948
|
+
-minmaxes.map { export_minmax _1 }.join(",")
|
|
1949
|
+
end
|
|
1950
|
+
|
|
1951
|
+
def export_minmax(minmax) minmax.uniq.map { export_num _1 }.join(":") end
|
|
1820
1952
|
|
|
1821
|
-
|
|
1822
|
-
|
|
1953
|
+
alias export_runs export_minmaxes
|
|
1954
|
+
alias export_run export_minmax
|
|
1955
|
+
|
|
1956
|
+
def export_minmax_entry((min, max))
|
|
1957
|
+
if min == STAR_INT then :*
|
|
1958
|
+
elsif max == STAR_INT then min..
|
|
1959
|
+
elsif min == max then min
|
|
1960
|
+
else min..max
|
|
1961
|
+
end
|
|
1962
|
+
end
|
|
1963
|
+
alias export_run_entry export_minmax_entry
|
|
1964
|
+
|
|
1965
|
+
def each_number_in_minmax(min, max, &block)
|
|
1966
|
+
if min == STAR_INT then yield :*
|
|
1967
|
+
elsif min == max then yield min
|
|
1968
|
+
elsif max != STAR_INT then (min..max).each(&block)
|
|
1969
|
+
else
|
|
1970
|
+
raise RangeError, "#{SequenceSet} cannot enumerate range with '*'"
|
|
1971
|
+
end
|
|
1823
1972
|
end
|
|
1824
1973
|
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1974
|
+
######################################################################{{{2
|
|
1975
|
+
# Parse methods
|
|
1976
|
+
|
|
1977
|
+
def parse_runs(str) str.split(",", -1).map! { parse_run _1 } end
|
|
1978
|
+
def parse_minmax(str) parse_entry(str).minmax end
|
|
1979
|
+
alias parse_run parse_minmax
|
|
1980
|
+
|
|
1981
|
+
def parse_entry(str)
|
|
1828
1982
|
raise DataFormatError, "invalid sequence set string" if str.empty?
|
|
1829
|
-
str.split(":", 2).map! {
|
|
1983
|
+
str.split(":", 2).map! { import_num _1 }
|
|
1830
1984
|
end
|
|
1831
1985
|
|
|
1832
|
-
|
|
1986
|
+
# yields validated but unsorted [num] or [num, num]
|
|
1987
|
+
def each_parsed_entry(str)
|
|
1988
|
+
return to_enum(__method__, str) unless block_given?
|
|
1989
|
+
str&.split(",", -1) do |entry| yield parse_entry(entry) end
|
|
1990
|
+
end
|
|
1991
|
+
|
|
1992
|
+
def normal_string?(str) normalized_entries? each_parsed_entry str end
|
|
1993
|
+
|
|
1994
|
+
def normalized_entries?(entries)
|
|
1995
|
+
max = nil
|
|
1996
|
+
entries.each do |first, last|
|
|
1997
|
+
return false if last && last <= first # 1:1 or 2:1
|
|
1998
|
+
return false if max && first <= max + 1 # 2,1 or 1,1 or 1,2
|
|
1999
|
+
max = last || first
|
|
2000
|
+
end
|
|
2001
|
+
true
|
|
2002
|
+
end
|
|
2003
|
+
|
|
2004
|
+
######################################################################{{{2
|
|
2005
|
+
# Ordered entry methods
|
|
2006
|
+
|
|
2007
|
+
def count_entries
|
|
2008
|
+
@string ? @string.count(",") + 1 : runs.count
|
|
2009
|
+
end
|
|
2010
|
+
|
|
2011
|
+
def each_entry_minmax(&block)
|
|
2012
|
+
return to_enum(__method__) unless block_given?
|
|
2013
|
+
if @string
|
|
2014
|
+
@string.split(",") do block.call parse_minmax _1 end
|
|
2015
|
+
else
|
|
2016
|
+
minmaxes.each(&block)
|
|
2017
|
+
end
|
|
2018
|
+
self
|
|
2019
|
+
end
|
|
2020
|
+
alias each_entry_run each_entry_minmax
|
|
2021
|
+
|
|
2022
|
+
######################################################################{{{2
|
|
2023
|
+
# Search methods
|
|
1833
2024
|
|
|
1834
|
-
def
|
|
1835
|
-
|
|
2025
|
+
def include_minmax?((min, max)) bsearch_range(min)&.cover?(min..max) end
|
|
2026
|
+
|
|
2027
|
+
def intersect_minmax?((min, max))
|
|
2028
|
+
range = bsearch_range(min) and
|
|
1836
2029
|
range.include?(min) || range.include?(max) || (min..max).cover?(range)
|
|
1837
2030
|
end
|
|
1838
2031
|
|
|
2032
|
+
alias include_run? include_minmax?
|
|
2033
|
+
alias intersect_run? intersect_minmax?
|
|
2034
|
+
|
|
2035
|
+
def bsearch_index(num) = minmaxes.bsearch_index { _2 >= num }
|
|
2036
|
+
def bsearch_minmax(num) = minmaxes.bsearch { _2 >= num }
|
|
2037
|
+
def bsearch_range(num) = (min, max = bsearch_minmax(num)) && (min..max)
|
|
2038
|
+
|
|
2039
|
+
######################################################################{{{2
|
|
2040
|
+
# Number indexing methods
|
|
2041
|
+
|
|
2042
|
+
def seek_number_in_minmaxes(minmaxes, index)
|
|
2043
|
+
index = Integer(index.to_int)
|
|
2044
|
+
if index.negative?
|
|
2045
|
+
reverse_each_minmax_with_index(minmaxes) do |min, max, idx_min, idx_max|
|
|
2046
|
+
idx_min <= index and return export_num(min + (index - idx_min))
|
|
2047
|
+
end
|
|
2048
|
+
else
|
|
2049
|
+
each_minmax_with_index(minmaxes) do |min, _, idx_min, idx_max|
|
|
2050
|
+
index <= idx_max and return export_num(min + (index - idx_min))
|
|
2051
|
+
end
|
|
2052
|
+
end
|
|
2053
|
+
nil
|
|
2054
|
+
end
|
|
2055
|
+
|
|
2056
|
+
def each_minmax_with_index(minmaxes)
|
|
2057
|
+
idx_min = 0
|
|
2058
|
+
minmaxes.each do |min, max|
|
|
2059
|
+
idx_max = idx_min + (max - min)
|
|
2060
|
+
yield min, max, idx_min, idx_max
|
|
2061
|
+
idx_min = idx_max + 1
|
|
2062
|
+
end
|
|
2063
|
+
idx_min
|
|
2064
|
+
end
|
|
2065
|
+
|
|
2066
|
+
def reverse_each_minmax_with_index(minmaxes)
|
|
2067
|
+
idx_max = -1
|
|
2068
|
+
minmaxes.reverse_each do |min, max|
|
|
2069
|
+
yield min, max, (idx_min = idx_max - (max - min)), idx_max
|
|
2070
|
+
idx_max = idx_min - 1
|
|
2071
|
+
end
|
|
2072
|
+
idx_max
|
|
2073
|
+
end
|
|
2074
|
+
|
|
2075
|
+
def slice_length(start, length)
|
|
2076
|
+
start = Integer(start.to_int)
|
|
2077
|
+
length = Integer(length.to_int)
|
|
2078
|
+
raise ArgumentError, "length must be positive" unless length.positive?
|
|
2079
|
+
last = start + length - 1 unless start.negative? && start.abs <= length
|
|
2080
|
+
slice_range(start..last)
|
|
2081
|
+
end
|
|
2082
|
+
|
|
2083
|
+
def slice_range(range)
|
|
2084
|
+
first = range.begin || 0
|
|
2085
|
+
last = range.end || -1
|
|
2086
|
+
if range.exclude_end?
|
|
2087
|
+
return remain_frozen_empty if last.zero?
|
|
2088
|
+
last -= 1 if range.end && last != STAR_INT
|
|
2089
|
+
end
|
|
2090
|
+
if (first * last).positive? && last < first
|
|
2091
|
+
remain_frozen_empty
|
|
2092
|
+
elsif (min = at(first))
|
|
2093
|
+
max = at(last)
|
|
2094
|
+
max = :* if max.nil?
|
|
2095
|
+
if max == :* then self & (min..)
|
|
2096
|
+
elsif min <= max then self & (min..max)
|
|
2097
|
+
else remain_frozen_empty
|
|
2098
|
+
end
|
|
2099
|
+
end
|
|
2100
|
+
end
|
|
2101
|
+
|
|
2102
|
+
######################################################################{{{2
|
|
2103
|
+
# Core set data create/freeze/dup primitives
|
|
2104
|
+
|
|
2105
|
+
def new_set_data = []
|
|
2106
|
+
def freeze_set_data = set_data.each(&:freeze).freeze
|
|
2107
|
+
def dup_set_data = set_data.map { _1.dup }
|
|
2108
|
+
protected :dup_set_data
|
|
2109
|
+
|
|
2110
|
+
######################################################################{{{2
|
|
2111
|
+
# Core set data query/enumeration primitives
|
|
2112
|
+
|
|
2113
|
+
def min_num = minmaxes.first&.first
|
|
2114
|
+
def max_num = minmaxes.last&.last
|
|
2115
|
+
|
|
2116
|
+
def min_at(idx) = minmaxes[idx][0]
|
|
2117
|
+
def max_at(idx) = minmaxes[idx][1]
|
|
2118
|
+
|
|
2119
|
+
######################################################################{{{2
|
|
2120
|
+
# Core set data modification primitives
|
|
2121
|
+
|
|
2122
|
+
def set_min_at(idx, min) = minmaxes[idx][0] = min
|
|
2123
|
+
def set_max_at(idx, max) = minmaxes[idx][1] = max
|
|
2124
|
+
def replace_minmaxes(other) = minmaxes.replace(other)
|
|
2125
|
+
def append_minmax(min, max) = minmaxes << [min, max]
|
|
2126
|
+
def insert_minmax(idx, min, max) = minmaxes.insert idx, [min, max]
|
|
2127
|
+
def delete_run_at(idx) = runs.delete_at(idx)
|
|
2128
|
+
def slice_runs!(...) = runs.slice!(...)
|
|
2129
|
+
def truncate_runs!(idx) = runs.slice!(idx..)
|
|
2130
|
+
|
|
2131
|
+
######################################################################{{{2
|
|
2132
|
+
# Update methods
|
|
2133
|
+
|
|
1839
2134
|
def modifying!
|
|
1840
2135
|
if frozen?
|
|
1841
2136
|
raise FrozenError, "can't modify frozen #{self.class}: %p" % [self]
|
|
1842
2137
|
end
|
|
1843
2138
|
end
|
|
1844
2139
|
|
|
1845
|
-
def
|
|
1846
|
-
|
|
2140
|
+
def add_minmaxes(minmaxes)
|
|
2141
|
+
minmaxes.each do |minmax|
|
|
2142
|
+
add_minmax minmax
|
|
2143
|
+
end
|
|
2144
|
+
self
|
|
2145
|
+
end
|
|
2146
|
+
|
|
2147
|
+
def subtract_minmaxes(minmaxes)
|
|
2148
|
+
minmaxes.each do |minmax|
|
|
2149
|
+
subtract_minmax minmax
|
|
2150
|
+
end
|
|
2151
|
+
self
|
|
2152
|
+
end
|
|
1847
2153
|
|
|
1848
2154
|
#
|
|
1849
|
-
# --|=====| |=====new
|
|
1850
|
-
# ?????????-|=====new
|
|
2155
|
+
# --|=====| |=====new run=======| append
|
|
2156
|
+
# ?????????-|=====new run=======|-|===lower===|-- insert
|
|
1851
2157
|
#
|
|
1852
|
-
# |=====new
|
|
2158
|
+
# |=====new run=======|
|
|
1853
2159
|
# ---------??=======lower=======??--------------- noop
|
|
1854
2160
|
#
|
|
1855
2161
|
# ---------??===lower==|--|==| join remaining
|
|
1856
2162
|
# ---------??===lower==|--|==|----|===upper===|-- join until upper
|
|
1857
2163
|
# ---------??===lower==|--|==|--|=====upper===|-- join to upper
|
|
1858
|
-
def
|
|
2164
|
+
def add_minmax(minmax)
|
|
1859
2165
|
modifying!
|
|
1860
|
-
min, max
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2166
|
+
min, max = minmax
|
|
2167
|
+
lower_idx = bsearch_index(min - 1)
|
|
2168
|
+
lmin, lmax = min_at(lower_idx), max_at(lower_idx) if lower_idx
|
|
2169
|
+
if lmin.nil? then append_minmax min, max
|
|
2170
|
+
elsif (max + 1) < lmin then insert_minmax lower_idx, min, max
|
|
2171
|
+
else add_coalesced_minmax(lower_idx, lmin, lmax, min, max)
|
|
1865
2172
|
end
|
|
1866
2173
|
end
|
|
1867
2174
|
|
|
1868
|
-
def
|
|
1869
|
-
return if
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
lower_idx
|
|
1873
|
-
return if
|
|
1874
|
-
tmax_adj =
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
2175
|
+
def add_coalesced_minmax(lower_idx, lmin, lmax, min, max)
|
|
2176
|
+
return if lmin <= min && max <= lmax
|
|
2177
|
+
set_min_at lower_idx, (lmin = min) if min < lmin
|
|
2178
|
+
set_max_at lower_idx, (lmax = max) if lmax < max
|
|
2179
|
+
next_idx = lower_idx + 1
|
|
2180
|
+
return if next_idx == runs.count
|
|
2181
|
+
tmax_adj = lmax + 1
|
|
2182
|
+
if (upper_idx = bsearch_index(tmax_adj))
|
|
2183
|
+
if tmax_adj < min_at(upper_idx)
|
|
2184
|
+
upper_idx -= 1
|
|
2185
|
+
else
|
|
2186
|
+
set_max_at lower_idx, max_at(upper_idx)
|
|
2187
|
+
end
|
|
1878
2188
|
end
|
|
1879
|
-
|
|
2189
|
+
slice_runs! next_idx..upper_idx
|
|
1880
2190
|
end
|
|
1881
2191
|
|
|
1882
|
-
# |====
|
|
2192
|
+
# |====subtracted run=======|
|
|
1883
2193
|
# --|====| no more 1. noop
|
|
1884
2194
|
# --|====|---------------------------|====lower====|-- 2. noop
|
|
1885
2195
|
# -------|======lower================|---------------- 3. split
|
|
@@ -1892,61 +2202,59 @@ module Net
|
|
|
1892
2202
|
# -------??=====lower====|--|====| no more 6. delete rest
|
|
1893
2203
|
# -------??=====lower====|--|====|---|====upper====|-- 7. delete until
|
|
1894
2204
|
# -------??=====lower====|--|====|--|=====upper====|-- 8. delete and trim
|
|
1895
|
-
def
|
|
2205
|
+
def subtract_minmax(minmax)
|
|
1896
2206
|
modifying!
|
|
1897
|
-
min, max
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
elsif max <
|
|
1902
|
-
|
|
2207
|
+
min, max = minmax
|
|
2208
|
+
idx = bsearch_index(min)
|
|
2209
|
+
lmin, lmax = min_at(idx), max_at(idx) if idx
|
|
2210
|
+
if lmin.nil? then nil # case 1.
|
|
2211
|
+
elsif max < lmin then nil # case 2.
|
|
2212
|
+
elsif max < lmax then trim_or_split_minmax idx, lmin, min, max
|
|
2213
|
+
else trim_or_delete_minmax idx, lmin, lmax, min, max
|
|
1903
2214
|
end
|
|
1904
2215
|
end
|
|
1905
2216
|
|
|
1906
|
-
def
|
|
1907
|
-
|
|
1908
|
-
|
|
2217
|
+
def trim_or_split_minmax(idx, lmin, tmin, tmax)
|
|
2218
|
+
set_min_at idx, tmax + 1
|
|
2219
|
+
if lmin < tmin # split
|
|
2220
|
+
insert_minmax idx, lmin, tmin - 1
|
|
1909
2221
|
end
|
|
1910
|
-
lower[0] = tmax + 1
|
|
1911
2222
|
end
|
|
1912
2223
|
|
|
1913
|
-
def
|
|
1914
|
-
if
|
|
1915
|
-
|
|
2224
|
+
def trim_or_delete_minmax(lower_idx, lmin, lmax, tmin, tmax)
|
|
2225
|
+
if lmin < tmin # trim lower
|
|
2226
|
+
lmax = set_max_at lower_idx, tmin - 1
|
|
1916
2227
|
lower_idx += 1
|
|
1917
2228
|
end
|
|
1918
|
-
if tmax ==
|
|
1919
|
-
|
|
1920
|
-
elsif (
|
|
1921
|
-
upper_idx
|
|
1922
|
-
|
|
2229
|
+
if tmax == lmax # case 5
|
|
2230
|
+
delete_run_at lower_idx
|
|
2231
|
+
elsif (upper_idx = bsearch_index(tmax + 1))
|
|
2232
|
+
if min_at(upper_idx) <= tmax # case 8
|
|
2233
|
+
set_min_at upper_idx, tmax + 1
|
|
2234
|
+
end
|
|
2235
|
+
slice_runs! lower_idx..upper_idx - 1 # cases 7 and 8
|
|
2236
|
+
else # case 6
|
|
2237
|
+
truncate_runs! lower_idx
|
|
1923
2238
|
end
|
|
1924
|
-
tuples.slice!(lower_idx..upper_idx)
|
|
1925
|
-
end
|
|
1926
|
-
|
|
1927
|
-
def tuple_gte_with_index(num)
|
|
1928
|
-
idx = tuples.bsearch_index { _2 >= num } and [tuples[idx], idx]
|
|
1929
2239
|
end
|
|
1930
2240
|
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
def nz_number(num)
|
|
1937
|
-
String === num && !/\A[1-9]\d*\z/.match?(num) and
|
|
1938
|
-
raise DataFormatError, "%p is not a valid nz-number" % [num]
|
|
1939
|
-
NumValidator.ensure_nz_number Integer num
|
|
1940
|
-
rescue TypeError # To catch errors from Integer()
|
|
1941
|
-
raise DataFormatError, $!.message
|
|
1942
|
-
end
|
|
2241
|
+
alias add_runs add_minmaxes
|
|
2242
|
+
alias add_run add_minmax
|
|
2243
|
+
alias subtract_runs subtract_minmaxes
|
|
2244
|
+
alias subtract_run subtract_minmax
|
|
1943
2245
|
|
|
2246
|
+
######################################################################{{{2
|
|
1944
2247
|
# intentionally defined after the class implementation
|
|
1945
2248
|
|
|
2249
|
+
FULL_SET_DATA = [[1, STAR_INT].freeze].freeze
|
|
2250
|
+
private_constant :FULL_SET_DATA
|
|
2251
|
+
|
|
1946
2252
|
EMPTY = new.freeze
|
|
1947
2253
|
FULL = self["1:*"]
|
|
1948
2254
|
private_constant :EMPTY, :FULL
|
|
1949
2255
|
|
|
2256
|
+
# }}}
|
|
2257
|
+
# vim:foldmethod=marker
|
|
1950
2258
|
end
|
|
1951
2259
|
end
|
|
1952
2260
|
end
|