couchbase 3.4.1 → 3.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (278) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -2
  3. data/ext/couchbase/CMakeLists.txt +59 -7
  4. data/ext/couchbase/cmake/Documentation.cmake +0 -1
  5. data/ext/couchbase/cmake/OpenSSL.cmake +98 -3
  6. data/ext/couchbase/cmake/Testing.cmake +12 -4
  7. data/ext/couchbase/cmake/ThirdPartyDependencies.cmake +4 -0
  8. data/ext/couchbase/cmake/build_config.hxx.in +3 -0
  9. data/ext/couchbase/core/bucket.cxx +3 -2
  10. data/ext/couchbase/core/bucket.hxx +9 -0
  11. data/ext/couchbase/core/cluster.hxx +17 -0
  12. data/ext/couchbase/core/cluster_options.cxx +2 -2
  13. data/ext/couchbase/core/cluster_options.hxx +4 -7
  14. data/ext/couchbase/core/{config_profile.cxx → cluster_options_fwd.hxx} +7 -6
  15. data/ext/couchbase/core/config_profile.hxx +2 -65
  16. data/ext/couchbase/core/config_profiles.cxx +79 -0
  17. data/ext/couchbase/core/config_profiles.hxx +56 -0
  18. data/ext/couchbase/core/error_context/search.hxx +1 -1
  19. data/ext/couchbase/core/impl/analytics.cxx +237 -0
  20. data/ext/couchbase/core/impl/boolean_field_query.cxx +40 -0
  21. data/ext/couchbase/core/impl/boolean_query.cxx +62 -0
  22. data/ext/couchbase/core/impl/cluster.cxx +2 -1
  23. data/ext/couchbase/core/impl/conjunction_query.cxx +51 -0
  24. data/ext/couchbase/core/impl/date_range.cxx +89 -0
  25. data/ext/couchbase/core/impl/date_range_facet.cxx +54 -0
  26. data/ext/couchbase/core/impl/date_range_facet_result.cxx +64 -0
  27. data/ext/couchbase/core/impl/date_range_query.cxx +125 -0
  28. data/ext/couchbase/core/impl/disjunction_query.cxx +51 -0
  29. data/ext/couchbase/core/impl/dns_srv_tracker.cxx +5 -3
  30. data/ext/couchbase/core/impl/encoded_search_facet.hxx +29 -0
  31. data/ext/couchbase/core/impl/encoded_search_query.hxx +29 -0
  32. data/ext/couchbase/core/impl/encoded_search_sort.hxx +29 -0
  33. data/ext/couchbase/core/impl/geo_bounding_box_query.cxx +46 -0
  34. data/ext/couchbase/core/impl/geo_distance_query.cxx +43 -0
  35. data/ext/couchbase/core/impl/geo_polygon_query.cxx +46 -0
  36. data/ext/couchbase/core/impl/internal_date_range_facet_result.cxx +80 -0
  37. data/ext/couchbase/core/impl/internal_date_range_facet_result.hxx +48 -0
  38. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.cxx +80 -0
  39. data/ext/couchbase/core/impl/internal_numeric_range_facet_result.hxx +48 -0
  40. data/ext/couchbase/core/impl/internal_search_error_context.cxx +141 -0
  41. data/ext/couchbase/core/impl/internal_search_error_context.hxx +61 -0
  42. data/ext/couchbase/core/impl/internal_search_meta_data.cxx +60 -0
  43. data/ext/couchbase/core/impl/internal_search_meta_data.hxx +41 -0
  44. data/ext/couchbase/core/impl/internal_search_result.cxx +84 -0
  45. data/ext/couchbase/core/impl/internal_search_result.hxx +43 -0
  46. data/ext/couchbase/core/impl/internal_search_row.cxx +82 -0
  47. data/ext/couchbase/core/impl/internal_search_row.hxx +56 -0
  48. data/ext/couchbase/core/impl/internal_search_row_location.hxx +32 -0
  49. data/ext/couchbase/core/impl/internal_search_row_locations.cxx +137 -0
  50. data/ext/couchbase/core/impl/internal_search_row_locations.hxx +45 -0
  51. data/ext/couchbase/core/impl/internal_term_facet_result.cxx +80 -0
  52. data/ext/couchbase/core/impl/internal_term_facet_result.hxx +48 -0
  53. data/ext/couchbase/core/impl/match_all_query.cxx +35 -0
  54. data/ext/couchbase/core/impl/match_none_query.cxx +35 -0
  55. data/ext/couchbase/core/impl/match_phrase_query.cxx +43 -0
  56. data/ext/couchbase/core/impl/match_query.cxx +59 -0
  57. data/ext/couchbase/core/impl/numeric_range.cxx +49 -0
  58. data/ext/couchbase/core/impl/numeric_range_facet.cxx +54 -0
  59. data/ext/couchbase/core/impl/numeric_range_facet_result.cxx +64 -0
  60. data/ext/couchbase/core/impl/numeric_range_query.cxx +56 -0
  61. data/ext/couchbase/core/impl/phrase_query.cxx +42 -0
  62. data/ext/couchbase/core/impl/prefix_query.cxx +40 -0
  63. data/ext/couchbase/core/impl/query.cxx +5 -5
  64. data/ext/couchbase/core/impl/query_string_query.cxx +37 -0
  65. data/ext/couchbase/core/impl/regexp_query.cxx +40 -0
  66. data/ext/couchbase/core/impl/search.cxx +191 -0
  67. data/ext/couchbase/core/impl/search_error_context.cxx +147 -0
  68. data/ext/couchbase/core/impl/search_meta_data.cxx +46 -0
  69. data/ext/couchbase/core/impl/search_result.cxx +66 -0
  70. data/ext/couchbase/core/impl/search_row.cxx +74 -0
  71. data/ext/couchbase/core/impl/search_row_location.cxx +64 -0
  72. data/ext/couchbase/core/impl/search_row_locations.cxx +66 -0
  73. data/ext/couchbase/core/impl/search_sort_field.cxx +104 -0
  74. data/ext/couchbase/core/impl/search_sort_id.cxx +43 -0
  75. data/ext/couchbase/core/impl/search_sort_score.cxx +43 -0
  76. data/ext/couchbase/core/impl/term_facet.cxx +36 -0
  77. data/ext/couchbase/core/impl/term_facet_result.cxx +64 -0
  78. data/ext/couchbase/core/impl/term_query.cxx +56 -0
  79. data/ext/couchbase/core/impl/term_range_query.cxx +57 -0
  80. data/ext/couchbase/core/impl/wildcard_query.cxx +40 -0
  81. data/ext/couchbase/core/io/dns_client.cxx +225 -0
  82. data/ext/couchbase/core/io/dns_client.hxx +19 -188
  83. data/ext/couchbase/core/io/http_context.hxx +1 -1
  84. data/ext/couchbase/core/io/http_session.hxx +10 -0
  85. data/ext/couchbase/core/io/http_session_manager.hxx +5 -3
  86. data/ext/couchbase/core/io/mcbp_session.cxx +28 -1
  87. data/ext/couchbase/core/io/retry_orchestrator.hxx +3 -2
  88. data/ext/couchbase/core/json_string.hxx +5 -0
  89. data/ext/couchbase/core/meta/version.cxx +18 -4
  90. data/ext/couchbase/core/mozilla_ca_bundle.hxx +39 -0
  91. data/ext/couchbase/core/operations/document_analytics.cxx +1 -0
  92. data/ext/couchbase/core/operations/document_analytics.hxx +1 -0
  93. data/ext/couchbase/core/operations/document_append.hxx +1 -1
  94. data/ext/couchbase/core/operations/document_decrement.hxx +1 -1
  95. data/ext/couchbase/core/operations/document_exists.hxx +1 -1
  96. data/ext/couchbase/core/operations/document_get.hxx +1 -1
  97. data/ext/couchbase/core/operations/document_get_and_lock.hxx +1 -1
  98. data/ext/couchbase/core/operations/document_get_and_touch.hxx +1 -1
  99. data/ext/couchbase/core/operations/document_get_projected.hxx +1 -1
  100. data/ext/couchbase/core/operations/document_increment.hxx +1 -1
  101. data/ext/couchbase/core/operations/document_insert.hxx +1 -1
  102. data/ext/couchbase/core/operations/document_lookup_in.hxx +1 -1
  103. data/ext/couchbase/core/operations/document_mutate_in.hxx +1 -1
  104. data/ext/couchbase/core/operations/document_prepend.hxx +1 -1
  105. data/ext/couchbase/core/operations/document_query.cxx +2 -0
  106. data/ext/couchbase/core/operations/document_query.hxx +6 -0
  107. data/ext/couchbase/core/operations/document_remove.hxx +1 -1
  108. data/ext/couchbase/core/operations/document_replace.hxx +1 -1
  109. data/ext/couchbase/core/operations/document_search.cxx +4 -1
  110. data/ext/couchbase/core/operations/document_search.hxx +2 -1
  111. data/ext/couchbase/core/operations/document_touch.hxx +1 -1
  112. data/ext/couchbase/core/operations/document_unlock.hxx +1 -1
  113. data/ext/couchbase/core/operations/document_upsert.hxx +1 -1
  114. data/ext/couchbase/core/operations/document_view.hxx +1 -0
  115. data/ext/couchbase/core/protocol/client_request.hxx +11 -2
  116. data/ext/couchbase/core/public_fwd.hxx +21 -0
  117. data/ext/couchbase/core/tls_verify_mode.hxx +26 -0
  118. data/ext/couchbase/core/topology/configuration.cxx +15 -2
  119. data/ext/couchbase/core/topology/configuration.hxx +5 -1
  120. data/ext/couchbase/core/transactions/active_transaction_record.hxx +2 -2
  121. data/ext/couchbase/core/transactions/attempt_context_impl.cxx +3 -0
  122. data/ext/couchbase/core/transactions/attempt_context_impl.hxx +1 -1
  123. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.cxx +93 -0
  124. data/ext/couchbase/core/transactions/attempt_context_testing_hooks.hxx +48 -75
  125. data/ext/couchbase/core/transactions/cleanup_testing_hooks.cxx +52 -0
  126. data/ext/couchbase/core/transactions/cleanup_testing_hooks.hxx +17 -31
  127. data/ext/couchbase/core/transactions/exceptions.hxx +12 -9
  128. data/ext/couchbase/core/transactions/internal/transaction_context.hxx +12 -12
  129. data/ext/couchbase/core/transactions/internal/transactions_cleanup.hxx +7 -1
  130. data/ext/couchbase/core/transactions/transaction_context.cxx +1 -0
  131. data/ext/couchbase/core/transactions/transactions_cleanup.cxx +144 -155
  132. data/ext/couchbase/core/utils/connection_string.cxx +27 -3
  133. data/ext/couchbase/core/utils/connection_string.hxx +3 -3
  134. data/ext/couchbase/core/utils/json.cxx +4 -1
  135. data/ext/couchbase/couchbase/analytics_error_context.hxx +143 -0
  136. data/ext/couchbase/couchbase/analytics_meta_data.hxx +155 -0
  137. data/ext/couchbase/couchbase/analytics_metrics.hxx +163 -0
  138. data/ext/couchbase/couchbase/analytics_options.hxx +359 -0
  139. data/ext/couchbase/couchbase/analytics_result.hxx +102 -0
  140. data/ext/couchbase/couchbase/analytics_scan_consistency.hxx +46 -0
  141. data/ext/couchbase/couchbase/analytics_status.hxx +41 -0
  142. data/ext/couchbase/couchbase/analytics_warning.hxx +85 -0
  143. data/ext/couchbase/couchbase/behavior_options.hxx +10 -1
  144. data/ext/couchbase/couchbase/boolean_field_query.hxx +77 -0
  145. data/ext/couchbase/couchbase/boolean_query.hxx +223 -0
  146. data/ext/couchbase/couchbase/cluster.hxx +75 -1
  147. data/ext/couchbase/couchbase/conjunction_query.hxx +88 -0
  148. data/ext/couchbase/couchbase/date_range.hxx +69 -0
  149. data/ext/couchbase/couchbase/date_range_facet.hxx +56 -0
  150. data/ext/couchbase/couchbase/date_range_facet_result.hxx +55 -0
  151. data/ext/couchbase/couchbase/date_range_query.hxx +265 -0
  152. data/ext/couchbase/couchbase/disjunction_query.hxx +109 -0
  153. data/ext/couchbase/couchbase/doc_id_query.hxx +111 -0
  154. data/ext/couchbase/couchbase/error_context.hxx +7 -6
  155. data/ext/couchbase/couchbase/fmt/analytics_scan_consistency.hxx +52 -0
  156. data/ext/couchbase/couchbase/fmt/analytics_status.hxx +76 -0
  157. data/ext/couchbase/couchbase/fmt/search_scan_consistency.hxx +49 -0
  158. data/ext/couchbase/couchbase/geo_bounding_box_query.hxx +107 -0
  159. data/ext/couchbase/couchbase/geo_distance_query.hxx +109 -0
  160. data/ext/couchbase/couchbase/geo_point.hxx +32 -0
  161. data/ext/couchbase/couchbase/geo_polygon_query.hxx +85 -0
  162. data/ext/couchbase/couchbase/highlight_style.hxx +45 -0
  163. data/ext/couchbase/couchbase/match_all_query.hxx +43 -0
  164. data/ext/couchbase/couchbase/match_none_query.hxx +43 -0
  165. data/ext/couchbase/couchbase/match_operator.hxx +45 -0
  166. data/ext/couchbase/couchbase/match_phrase_query.hxx +108 -0
  167. data/ext/couchbase/couchbase/match_query.hxx +163 -0
  168. data/ext/couchbase/couchbase/numeric_range.hxx +58 -0
  169. data/ext/couchbase/couchbase/numeric_range_facet.hxx +56 -0
  170. data/ext/couchbase/couchbase/numeric_range_facet_result.hxx +55 -0
  171. data/ext/couchbase/couchbase/numeric_range_query.hxx +143 -0
  172. data/ext/couchbase/couchbase/phrase_query.hxx +93 -0
  173. data/ext/couchbase/couchbase/prefix_query.hxx +82 -0
  174. data/ext/couchbase/couchbase/query_options.hxx +0 -1
  175. data/ext/couchbase/couchbase/query_string_query.hxx +72 -0
  176. data/ext/couchbase/couchbase/regexp_query.hxx +82 -0
  177. data/ext/couchbase/couchbase/scope.hxx +73 -0
  178. data/ext/couchbase/couchbase/search_date_range.hxx +68 -0
  179. data/ext/couchbase/couchbase/search_error_context.hxx +138 -0
  180. data/ext/couchbase/couchbase/search_facet.hxx +60 -0
  181. data/ext/couchbase/couchbase/search_facet_result.hxx +50 -0
  182. data/ext/couchbase/couchbase/search_meta_data.hxx +85 -0
  183. data/ext/couchbase/couchbase/search_metrics.hxx +127 -0
  184. data/ext/couchbase/couchbase/search_numeric_range.hxx +69 -0
  185. data/ext/couchbase/couchbase/search_options.hxx +509 -0
  186. data/ext/couchbase/couchbase/search_query.hxx +69 -0
  187. data/ext/couchbase/couchbase/search_result.hxx +77 -0
  188. data/ext/couchbase/couchbase/search_row.hxx +104 -0
  189. data/ext/couchbase/couchbase/search_row_location.hxx +55 -0
  190. data/ext/couchbase/couchbase/search_row_locations.hxx +86 -0
  191. data/ext/couchbase/couchbase/search_scan_consistency.hxx +34 -0
  192. data/ext/couchbase/couchbase/search_sort.hxx +58 -0
  193. data/ext/couchbase/couchbase/search_sort_field.hxx +117 -0
  194. data/ext/couchbase/couchbase/search_sort_field_missing.hxx +26 -0
  195. data/ext/couchbase/couchbase/search_sort_field_mode.hxx +27 -0
  196. data/ext/couchbase/couchbase/search_sort_field_type.hxx +28 -0
  197. data/ext/couchbase/couchbase/search_sort_id.hxx +60 -0
  198. data/ext/couchbase/couchbase/search_sort_score.hxx +60 -0
  199. data/ext/couchbase/couchbase/search_term_range.hxx +51 -0
  200. data/ext/couchbase/couchbase/security_options.hxx +3 -0
  201. data/ext/couchbase/couchbase/term_facet.hxx +48 -0
  202. data/ext/couchbase/couchbase/term_facet_result.hxx +55 -0
  203. data/ext/couchbase/couchbase/term_query.hxx +151 -0
  204. data/ext/couchbase/couchbase/term_range_query.hxx +142 -0
  205. data/ext/couchbase/couchbase/tracing/request_span.hxx +63 -0
  206. data/ext/couchbase/couchbase/tracing/request_tracer.hxx +2 -40
  207. data/ext/couchbase/couchbase/transactions/async_attempt_context.hxx +83 -4
  208. data/ext/couchbase/couchbase/transactions/attempt_context.hxx +68 -1
  209. data/ext/couchbase/couchbase/transactions/transaction_get_result.hxx +2 -0
  210. data/ext/couchbase/couchbase/transactions/transaction_keyspace.hxx +11 -1
  211. data/ext/couchbase/couchbase/transactions/transaction_options.hxx +79 -8
  212. data/ext/couchbase/couchbase/transactions/transaction_query_options.hxx +128 -15
  213. data/ext/couchbase/couchbase/transactions/transaction_query_result.hxx +4 -0
  214. data/ext/couchbase/couchbase/transactions/transaction_result.hxx +1 -1
  215. data/ext/couchbase/couchbase/transactions/transactions_cleanup_config.hxx +5 -3
  216. data/ext/couchbase/couchbase/transactions/transactions_config.hxx +9 -5
  217. data/ext/couchbase/couchbase/transactions/transactions_query_config.hxx +6 -3
  218. data/ext/couchbase/couchbase/transactions.hxx +34 -1
  219. data/ext/couchbase/couchbase/wildcard_query.hxx +83 -0
  220. data/ext/couchbase/test/CMakeLists.txt +8 -7
  221. data/ext/couchbase/test/benchmark_helper_integration.hxx +2 -2
  222. data/ext/couchbase/test/test_helper.hxx +6 -6
  223. data/ext/couchbase/test/test_integration_analytics.cxx +314 -16
  224. data/ext/couchbase/test/test_integration_collections.cxx +7 -3
  225. data/ext/couchbase/test/test_integration_connect.cxx +7 -3
  226. data/ext/couchbase/test/test_integration_crud.cxx +19 -2
  227. data/ext/couchbase/test/test_integration_diagnostics.cxx +11 -5
  228. data/ext/couchbase/test/test_integration_durability.cxx +12 -7
  229. data/ext/couchbase/test/test_integration_examples.cxx +324 -11
  230. data/ext/couchbase/test/test_integration_management.cxx +162 -94
  231. data/ext/couchbase/test/test_integration_query.cxx +68 -10
  232. data/ext/couchbase/test/test_integration_range_scan.cxx +12 -12
  233. data/ext/couchbase/test/test_integration_read_replica.cxx +48 -11
  234. data/ext/couchbase/test/test_integration_search.cxx +621 -0
  235. data/ext/couchbase/test/test_integration_subdoc.cxx +62 -11
  236. data/ext/couchbase/test/test_integration_tracer.cxx +5 -0
  237. data/ext/couchbase/test/test_integration_transcoders.cxx +13 -5
  238. data/ext/couchbase/test/{test_transaction_transaction_context.cxx → test_transaction_context.cxx} +1 -1
  239. data/ext/couchbase/test/test_transaction_examples.cxx +195 -0
  240. data/ext/couchbase/test/{test_transaction_transaction_simple.cxx → test_transaction_simple.cxx} +90 -5
  241. data/ext/couchbase/test/{test_transaction_transaction_simple_async.cxx → test_transaction_simple_async.cxx} +19 -21
  242. data/ext/couchbase/test/test_unit_config_profiles.cxx +13 -13
  243. data/ext/couchbase/test/test_unit_connection_string.cxx +35 -0
  244. data/ext/couchbase/test/test_unit_json_transcoder.cxx +4 -0
  245. data/ext/couchbase/test/test_unit_search.cxx +427 -0
  246. data/ext/couchbase/test/test_unit_transaction_utils.cxx +10 -1
  247. data/ext/couchbase/test/test_unit_utils.cxx +8 -4
  248. data/ext/couchbase/third_party/snappy/CMakeLists.txt +150 -27
  249. data/ext/couchbase/third_party/snappy/cmake/config.h.in +28 -24
  250. data/ext/couchbase/third_party/snappy/snappy-internal.h +189 -25
  251. data/ext/couchbase/third_party/snappy/snappy-sinksource.cc +26 -9
  252. data/ext/couchbase/third_party/snappy/snappy-sinksource.h +11 -11
  253. data/ext/couchbase/third_party/snappy/snappy-stubs-internal.cc +1 -1
  254. data/ext/couchbase/third_party/snappy/snappy-stubs-internal.h +227 -308
  255. data/ext/couchbase/third_party/snappy/snappy-stubs-public.h.in +0 -11
  256. data/ext/couchbase/third_party/snappy/snappy.cc +1176 -410
  257. data/ext/couchbase/third_party/snappy/snappy.h +19 -4
  258. data/ext/couchbase.cxx +85 -22
  259. data/ext/revisions.rb +3 -3
  260. data/lib/couchbase/authenticator.rb +0 -1
  261. data/lib/couchbase/cluster.rb +13 -13
  262. data/lib/couchbase/cluster_registry.rb +7 -2
  263. data/lib/couchbase/config_profiles.rb +1 -1
  264. data/lib/couchbase/configuration.rb +3 -4
  265. data/lib/couchbase/json_transcoder.rb +12 -5
  266. data/lib/couchbase/management/collection_query_index_manager.rb +54 -15
  267. data/lib/couchbase/management/query_index_manager.rb +70 -5
  268. data/lib/couchbase/options.rb +85 -2
  269. data/lib/couchbase/raw_binary_transcoder.rb +37 -0
  270. data/lib/couchbase/raw_json_transcoder.rb +38 -0
  271. data/lib/couchbase/raw_string_transcoder.rb +40 -0
  272. data/lib/couchbase/search_options.rb +163 -240
  273. data/lib/couchbase/transcoder_flags.rb +62 -0
  274. data/lib/couchbase/version.rb +1 -1
  275. metadata +151 -12
  276. data/ext/couchbase/core/CMakeLists.txt +0 -0
  277. /data/ext/couchbase/test/{test_transaction_transaction_public_async_api.cxx → test_transaction_public_async_api.cxx} +0 -0
  278. /data/ext/couchbase/test/{test_transaction_transaction_public_blocking_api.cxx → test_transaction_public_blocking_api.cxx} +0 -0
@@ -27,7 +27,7 @@
27
27
  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
28
 
29
29
  cmake_minimum_required(VERSION 3.1)
30
- project(Snappy VERSION 1.1.8 LANGUAGES C CXX)
30
+ project(Snappy VERSION 1.1.10 LANGUAGES C CXX)
31
31
 
32
32
  # C++ standard can be overridden when this is used as a sub-project.
33
33
  if(NOT CMAKE_CXX_STANDARD)
@@ -37,12 +37,59 @@ if(NOT CMAKE_CXX_STANDARD)
37
37
  set(CMAKE_CXX_EXTENSIONS OFF)
38
38
  endif(NOT CMAKE_CXX_STANDARD)
39
39
 
40
+ # https://github.com/izenecloud/cmake/blob/master/SetCompilerWarningAll.cmake
41
+ if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
42
+ # Use the highest warning level for Visual Studio.
43
+ set(CMAKE_CXX_WARNING_LEVEL 4)
44
+ if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
45
+ string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
46
+ else(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
47
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
48
+ endif(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
49
+
50
+ # Disable C++ exceptions.
51
+ string(REGEX REPLACE "/EH[a-z]+" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
52
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /EHs-c-")
53
+ add_definitions(-D_HAS_EXCEPTIONS=0)
54
+
55
+ # Disable RTTI.
56
+ string(REGEX REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
57
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GR-")
58
+ else(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
59
+ # Use -Wall for clang and gcc.
60
+ if(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
61
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
62
+ endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wall")
63
+
64
+ # Use -Wextra for clang and gcc.
65
+ if(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
66
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wextra")
67
+ endif(NOT CMAKE_CXX_FLAGS MATCHES "-Wextra")
68
+
69
+ # Use -Werror for clang only.
70
+ if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
71
+ if(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
72
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
73
+ endif(NOT CMAKE_CXX_FLAGS MATCHES "-Werror")
74
+ endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
75
+
76
+ # Disable C++ exceptions.
77
+ string(REGEX REPLACE "-fexceptions" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
78
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
79
+
80
+ # Disable RTTI.
81
+ string(REGEX REPLACE "-frtti" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
82
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti")
83
+ endif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
84
+
40
85
  # BUILD_SHARED_LIBS is a standard CMake variable, but we declare it here to make
41
86
  # it prominent in the GUI.
42
87
  option(BUILD_SHARED_LIBS "Build shared libraries(DLLs)." OFF)
43
88
 
44
89
  option(SNAPPY_BUILD_TESTS "Build Snappy's own tests." ON)
45
90
 
91
+ option(SNAPPY_BUILD_BENCHMARKS "Build Snappy's benchmarks" ON)
92
+
46
93
  option(SNAPPY_FUZZING_BUILD "Build Snappy for fuzzing." OFF)
47
94
 
48
95
  option(SNAPPY_REQUIRE_AVX "Target processors with AVX support." OFF)
@@ -55,8 +102,6 @@ include(TestBigEndian)
55
102
  test_big_endian(SNAPPY_IS_BIG_ENDIAN)
56
103
 
57
104
  include(CheckIncludeFile)
58
- check_include_file("byteswap.h" HAVE_BYTESWAP_H)
59
- check_include_file("sys/endian.h" HAVE_SYS_ENDIAN_H)
60
105
  check_include_file("sys/mman.h" HAVE_SYS_MMAN_H)
61
106
  check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H)
62
107
  check_include_file("sys/time.h" HAVE_SYS_TIME_H)
@@ -67,6 +112,7 @@ check_include_file("windows.h" HAVE_WINDOWS_H)
67
112
  include(CheckLibraryExists)
68
113
  check_library_exists(z zlibVersion "" HAVE_LIBZ)
69
114
  check_library_exists(lzo2 lzo1x_1_15_compress "" HAVE_LIBLZO2)
115
+ check_library_exists(lz4 LZ4_compress_default "" HAVE_LIBLZ4)
70
116
 
71
117
  include(CheckCXXCompilerFlag)
72
118
  CHECK_CXX_COMPILER_FLAG("/arch:AVX" HAVE_VISUAL_STUDIO_ARCH_AVX)
@@ -92,6 +138,10 @@ elseif (SNAPPY_REQUIRE_AVX)
92
138
  endif(HAVE_CLANG_MAVX)
93
139
  endif(SNAPPY_REQUIRE_AVX2)
94
140
 
141
+ # Used by googletest.
142
+ check_cxx_compiler_flag(-Wno-missing-field-initializers
143
+ SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
144
+
95
145
  include(CheckCXXSourceCompiles)
96
146
  check_cxx_source_compiles("
97
147
  int main() {
@@ -103,6 +153,13 @@ int main() {
103
153
  return __builtin_ctzll(0);
104
154
  }" HAVE_BUILTIN_CTZ)
105
155
 
156
+ check_cxx_source_compiles("
157
+ __attribute__((always_inline)) int zero() { return 0; }
158
+
159
+ int main() {
160
+ return zero();
161
+ }" HAVE_ATTRIBUTE_ALWAYS_INLINE)
162
+
106
163
  check_cxx_source_compiles("
107
164
  #include <tmmintrin.h>
108
165
 
@@ -115,26 +172,38 @@ int main() {
115
172
  return 0;
116
173
  }" SNAPPY_HAVE_SSSE3)
117
174
 
175
+ check_cxx_source_compiles("
176
+ #include <immintrin.h>
177
+ int main() {
178
+ return _mm_crc32_u32(0, 1);
179
+ }" SNAPPY_HAVE_X86_CRC32)
180
+
181
+ check_cxx_source_compiles("
182
+ #include <arm_neon.h>
183
+ #include <arm_acle.h>
184
+ int main() {
185
+ return __crc32cw(0, 1);
186
+ }" SNAPPY_HAVE_NEON_CRC32)
187
+
118
188
  check_cxx_source_compiles("
119
189
  #include <immintrin.h>
120
190
  int main() {
121
191
  return _bzhi_u32(0, 1);
122
192
  }" SNAPPY_HAVE_BMI2)
123
193
 
194
+ check_cxx_source_compiles("
195
+ #include <arm_neon.h>
196
+ int main() {
197
+ uint8_t val = 3, dup[8];
198
+ uint8x16_t v = vld1q_dup_u8(&val);
199
+ vst1q_u8(dup, v);
200
+ return 0;
201
+ }" SNAPPY_HAVE_NEON)
202
+
124
203
  include(CheckSymbolExists)
125
204
  check_symbol_exists("mmap" "sys/mman.h" HAVE_FUNC_MMAP)
126
205
  check_symbol_exists("sysconf" "unistd.h" HAVE_FUNC_SYSCONF)
127
206
 
128
- find_package(GTest QUIET)
129
- if(GTEST_FOUND)
130
- set(HAVE_GTEST 1)
131
- endif(GTEST_FOUND)
132
-
133
- find_package(Gflags QUIET)
134
- if(GFLAGS_FOUND)
135
- set(HAVE_GFLAGS 1)
136
- endif(GFLAGS_FOUND)
137
-
138
207
  configure_file(
139
208
  "cmake/config.h.in"
140
209
  "${PROJECT_BINARY_DIR}/config.h"
@@ -202,38 +271,92 @@ if(BUILD_SHARED_LIBS)
202
271
  set_target_properties(snappy PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
203
272
  endif(BUILD_SHARED_LIBS)
204
273
 
205
- if(SNAPPY_BUILD_TESTS)
206
- enable_testing()
207
-
208
- add_executable(snappy_unittest "")
209
- target_sources(snappy_unittest
274
+ if(SNAPPY_BUILD_TESTS OR SNAPPY_BUILD_BENCHMARKS)
275
+ add_library(snappy_test_support "")
276
+ target_sources(snappy_test_support
210
277
  PRIVATE
211
- "snappy_unittest.cc"
212
278
  "snappy-test.cc"
279
+ "snappy-test.h"
280
+ "snappy_test_data.cc"
281
+ "snappy_test_data.h"
282
+ "${PROJECT_BINARY_DIR}/config.h"
213
283
  )
214
- target_compile_definitions(snappy_unittest PRIVATE -DHAVE_CONFIG_H)
215
- target_link_libraries(snappy_unittest snappy ${GFLAGS_LIBRARIES})
284
+
285
+ # Test files include snappy-test.h, HAVE_CONFIG_H must be defined.
286
+ target_compile_definitions(snappy_test_support PUBLIC -DHAVE_CONFIG_H)
287
+
288
+ target_link_libraries(snappy_test_support snappy)
216
289
 
217
290
  if(HAVE_LIBZ)
218
- target_link_libraries(snappy_unittest z)
291
+ target_link_libraries(snappy_test_support z)
219
292
  endif(HAVE_LIBZ)
220
293
  if(HAVE_LIBLZO2)
221
- target_link_libraries(snappy_unittest lzo2)
294
+ target_link_libraries(snappy_test_support lzo2)
222
295
  endif(HAVE_LIBLZO2)
296
+ if(HAVE_LIBLZ4)
297
+ target_link_libraries(snappy_test_support lz4)
298
+ endif(HAVE_LIBLZ4)
223
299
 
224
- target_include_directories(snappy_unittest
225
- BEFORE PRIVATE
300
+ target_include_directories(snappy_test_support
301
+ BEFORE PUBLIC
226
302
  "${PROJECT_SOURCE_DIR}"
227
- "${GTEST_INCLUDE_DIRS}"
228
- "${GFLAGS_INCLUDE_DIRS}"
229
303
  )
304
+ endif(SNAPPY_BUILD_TESTS OR SNAPPY_BUILD_BENCHMARKS)
305
+
306
+ if(SNAPPY_BUILD_TESTS)
307
+ enable_testing()
308
+
309
+ # Prevent overriding the parent project's compiler/linker settings on Windows.
310
+ set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
311
+ set(install_gtest OFF)
312
+ set(install_gmock OFF)
313
+ set(build_gmock ON)
314
+
315
+ # This project is tested using GoogleTest.
316
+ add_subdirectory("third_party/googletest")
317
+
318
+ # GoogleTest triggers a missing field initializers warning.
319
+ if(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
320
+ set_property(TARGET gtest
321
+ APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
322
+ set_property(TARGET gmock
323
+ APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
324
+ endif(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
325
+
326
+ add_executable(snappy_unittest "")
327
+ target_sources(snappy_unittest
328
+ PRIVATE
329
+ "snappy_unittest.cc"
330
+ )
331
+ target_link_libraries(snappy_unittest snappy_test_support gmock_main gtest)
230
332
 
231
333
  add_test(
232
334
  NAME snappy_unittest
233
335
  WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}"
234
336
  COMMAND "${PROJECT_BINARY_DIR}/snappy_unittest")
337
+
338
+ add_executable(snappy_test_tool "")
339
+ target_sources(snappy_test_tool
340
+ PRIVATE
341
+ "snappy_test_tool.cc"
342
+ )
343
+ target_link_libraries(snappy_test_tool snappy_test_support)
235
344
  endif(SNAPPY_BUILD_TESTS)
236
345
 
346
+ if(SNAPPY_BUILD_BENCHMARKS)
347
+ add_executable(snappy_benchmark "")
348
+ target_sources(snappy_benchmark
349
+ PRIVATE
350
+ "snappy_benchmark.cc"
351
+ )
352
+ target_link_libraries(snappy_benchmark snappy_test_support benchmark_main)
353
+
354
+ # This project uses Google benchmark for benchmarking.
355
+ set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
356
+ set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE)
357
+ add_subdirectory("third_party/benchmark")
358
+ endif(SNAPPY_BUILD_BENCHMARKS)
359
+
237
360
  if(SNAPPY_FUZZING_BUILD)
238
361
  add_executable(snappy_compress_fuzzer "")
239
362
  target_sources(snappy_compress_fuzzer
@@ -1,62 +1,66 @@
1
1
  #ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_
2
2
  #define THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_
3
3
 
4
+ /* Define to 1 if the compiler supports __attribute__((always_inline)). */
5
+ #cmakedefine01 HAVE_ATTRIBUTE_ALWAYS_INLINE
6
+
4
7
  /* Define to 1 if the compiler supports __builtin_ctz and friends. */
5
- #cmakedefine HAVE_BUILTIN_CTZ 1
8
+ #cmakedefine01 HAVE_BUILTIN_CTZ
6
9
 
7
10
  /* Define to 1 if the compiler supports __builtin_expect. */
8
- #cmakedefine HAVE_BUILTIN_EXPECT 1
9
-
10
- /* Define to 1 if you have the <byteswap.h> header file. */
11
- #cmakedefine HAVE_BYTESWAP_H 1
11
+ #cmakedefine01 HAVE_BUILTIN_EXPECT
12
12
 
13
13
  /* Define to 1 if you have a definition for mmap() in <sys/mman.h>. */
14
- #cmakedefine HAVE_FUNC_MMAP 1
14
+ #cmakedefine01 HAVE_FUNC_MMAP
15
15
 
16
16
  /* Define to 1 if you have a definition for sysconf() in <unistd.h>. */
17
- #cmakedefine HAVE_FUNC_SYSCONF 1
18
-
19
- /* Define to 1 to use the gflags package for command-line parsing. */
20
- #cmakedefine HAVE_GFLAGS 1
21
-
22
- /* Define to 1 if you have Google Test. */
23
- #cmakedefine HAVE_GTEST 1
17
+ #cmakedefine01 HAVE_FUNC_SYSCONF
24
18
 
25
19
  /* Define to 1 if you have the `lzo2' library (-llzo2). */
26
- #cmakedefine HAVE_LIBLZO2 1
20
+ #cmakedefine01 HAVE_LIBLZO2
27
21
 
28
22
  /* Define to 1 if you have the `z' library (-lz). */
29
- #cmakedefine HAVE_LIBZ 1
23
+ #cmakedefine01 HAVE_LIBZ
30
24
 
31
- /* Define to 1 if you have the <sys/endian.h> header file. */
32
- #cmakedefine HAVE_SYS_ENDIAN_H 1
25
+ /* Define to 1 if you have the `lz4' library (-llz4). */
26
+ #cmakedefine01 HAVE_LIBLZ4
33
27
 
34
28
  /* Define to 1 if you have the <sys/mman.h> header file. */
35
- #cmakedefine HAVE_SYS_MMAN_H 1
29
+ #cmakedefine01 HAVE_SYS_MMAN_H
36
30
 
37
31
  /* Define to 1 if you have the <sys/resource.h> header file. */
38
- #cmakedefine HAVE_SYS_RESOURCE_H 1
32
+ #cmakedefine01 HAVE_SYS_RESOURCE_H
39
33
 
40
34
  /* Define to 1 if you have the <sys/time.h> header file. */
41
- #cmakedefine HAVE_SYS_TIME_H 1
35
+ #cmakedefine01 HAVE_SYS_TIME_H
42
36
 
43
37
  /* Define to 1 if you have the <sys/uio.h> header file. */
44
- #cmakedefine HAVE_SYS_UIO_H 1
38
+ #cmakedefine01 HAVE_SYS_UIO_H
45
39
 
46
40
  /* Define to 1 if you have the <unistd.h> header file. */
47
- #cmakedefine HAVE_UNISTD_H 1
41
+ #cmakedefine01 HAVE_UNISTD_H
48
42
 
49
43
  /* Define to 1 if you have the <windows.h> header file. */
50
- #cmakedefine HAVE_WINDOWS_H 1
44
+ #cmakedefine01 HAVE_WINDOWS_H
51
45
 
52
46
  /* Define to 1 if you target processors with SSSE3+ and have <tmmintrin.h>. */
53
47
  #cmakedefine01 SNAPPY_HAVE_SSSE3
54
48
 
49
+ /* Define to 1 if you target processors with SSE4.2 and have <crc32intrin.h>. */
50
+ #cmakedefine01 SNAPPY_HAVE_X86_CRC32
51
+
55
52
  /* Define to 1 if you target processors with BMI2+ and have <bmi2intrin.h>. */
56
53
  #cmakedefine01 SNAPPY_HAVE_BMI2
57
54
 
55
+ /* Define to 1 if you target processors with NEON and have <arm_neon.h>. */
56
+ #cmakedefine01 SNAPPY_HAVE_NEON
57
+
58
+ /* Define to 1 if you have <arm_neon.h> and <arm_acle.h> and want to optimize
59
+ compression speed by using __crc32cw from <arm_acle.h>. */
60
+ #cmakedefine01 SNAPPY_HAVE_NEON_CRC32
61
+
58
62
  /* Define to 1 if your processor stores words with the most significant byte
59
63
  first (like Motorola and SPARC, unlike Intel and VAX). */
60
- #cmakedefine SNAPPY_IS_BIG_ENDIAN 1
64
+ #cmakedefine01 SNAPPY_IS_BIG_ENDIAN
61
65
 
62
66
  #endif // THIRD_PARTY_SNAPPY_OPENSOURCE_CMAKE_CONFIG_H_
@@ -33,9 +33,84 @@
33
33
 
34
34
  #include "snappy-stubs-internal.h"
35
35
 
36
+ #if SNAPPY_HAVE_SSSE3
37
+ // Please do not replace with <x86intrin.h> or with headers that assume more
38
+ // advanced SSE versions without checking with all the OWNERS.
39
+ #include <emmintrin.h>
40
+ #include <tmmintrin.h>
41
+ #endif
42
+
43
+ #if SNAPPY_HAVE_NEON
44
+ #include <arm_neon.h>
45
+ #endif
46
+
47
+ #if SNAPPY_HAVE_SSSE3 || SNAPPY_HAVE_NEON
48
+ #define SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE 1
49
+ #else
50
+ #define SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE 0
51
+ #endif
52
+
36
53
  namespace snappy {
37
54
  namespace internal {
38
55
 
56
+ #if SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
57
+ #if SNAPPY_HAVE_SSSE3
58
+ using V128 = __m128i;
59
+ #elif SNAPPY_HAVE_NEON
60
+ using V128 = uint8x16_t;
61
+ #endif
62
+
63
+ // Load 128 bits of integer data. `src` must be 16-byte aligned.
64
+ inline V128 V128_Load(const V128* src);
65
+
66
+ // Load 128 bits of integer data. `src` does not need to be aligned.
67
+ inline V128 V128_LoadU(const V128* src);
68
+
69
+ // Store 128 bits of integer data. `dst` does not need to be aligned.
70
+ inline void V128_StoreU(V128* dst, V128 val);
71
+
72
+ // Shuffle packed 8-bit integers using a shuffle mask.
73
+ // Each packed integer in the shuffle mask must be in [0,16).
74
+ inline V128 V128_Shuffle(V128 input, V128 shuffle_mask);
75
+
76
+ // Constructs V128 with 16 chars |c|.
77
+ inline V128 V128_DupChar(char c);
78
+
79
+ #if SNAPPY_HAVE_SSSE3
80
+ inline V128 V128_Load(const V128* src) { return _mm_load_si128(src); }
81
+
82
+ inline V128 V128_LoadU(const V128* src) { return _mm_loadu_si128(src); }
83
+
84
+ inline void V128_StoreU(V128* dst, V128 val) { _mm_storeu_si128(dst, val); }
85
+
86
+ inline V128 V128_Shuffle(V128 input, V128 shuffle_mask) {
87
+ return _mm_shuffle_epi8(input, shuffle_mask);
88
+ }
89
+
90
+ inline V128 V128_DupChar(char c) { return _mm_set1_epi8(c); }
91
+
92
+ #elif SNAPPY_HAVE_NEON
93
+ inline V128 V128_Load(const V128* src) {
94
+ return vld1q_u8(reinterpret_cast<const uint8_t*>(src));
95
+ }
96
+
97
+ inline V128 V128_LoadU(const V128* src) {
98
+ return vld1q_u8(reinterpret_cast<const uint8_t*>(src));
99
+ }
100
+
101
+ inline void V128_StoreU(V128* dst, V128 val) {
102
+ vst1q_u8(reinterpret_cast<uint8_t*>(dst), val);
103
+ }
104
+
105
+ inline V128 V128_Shuffle(V128 input, V128 shuffle_mask) {
106
+ assert(vminvq_u8(shuffle_mask) >= 0 && vmaxvq_u8(shuffle_mask) <= 15);
107
+ return vqtbl1q_u8(input, shuffle_mask);
108
+ }
109
+
110
+ inline V128 V128_DupChar(char c) { return vdupq_n_u8(c); }
111
+ #endif
112
+ #endif // SNAPPY_HAVE_VECTOR_BYTE_SHUFFLE
113
+
39
114
  // Working memory performs a single allocation to hold all scratch space
40
115
  // required for compression.
41
116
  class WorkingMemory {
@@ -46,16 +121,16 @@ class WorkingMemory {
46
121
  // Allocates and clears a hash table using memory in "*this",
47
122
  // stores the number of buckets in "*table_size" and returns a pointer to
48
123
  // the base of the hash table.
49
- uint16* GetHashTable(size_t fragment_size, int* table_size) const;
124
+ uint16_t* GetHashTable(size_t fragment_size, int* table_size) const;
50
125
  char* GetScratchInput() const { return input_; }
51
126
  char* GetScratchOutput() const { return output_; }
52
127
 
53
128
  private:
54
- char* mem_; // the allocated memory, never nullptr
55
- size_t size_; // the size of the allocated memory, never 0
56
- uint16* table_; // the pointer to the hashtable
57
- char* input_; // the pointer to the input scratch buffer
58
- char* output_; // the pointer to the output scratch buffer
129
+ char* mem_; // the allocated memory, never nullptr
130
+ size_t size_; // the size of the allocated memory, never 0
131
+ uint16_t* table_; // the pointer to the hashtable
132
+ char* input_; // the pointer to the input scratch buffer
133
+ char* output_; // the pointer to the output scratch buffer
59
134
 
60
135
  // No copying
61
136
  WorkingMemory(const WorkingMemory&);
@@ -76,7 +151,7 @@ class WorkingMemory {
76
151
  char* CompressFragment(const char* input,
77
152
  size_t input_length,
78
153
  char* op,
79
- uint16* table,
154
+ uint16_t* table,
80
155
  const int table_size);
81
156
 
82
157
  // Find the largest n such that
@@ -89,12 +164,19 @@ char* CompressFragment(const char* input,
89
164
  // Does not read *(s1 + (s2_limit - s2)) or beyond.
90
165
  // Requires that s2_limit >= s2.
91
166
  //
167
+ // In addition populate *data with the next 5 bytes from the end of the match.
168
+ // This is only done if 8 bytes are available (s2_limit - s2 >= 8). The point is
169
+ // that on some arch's this can be done faster in this routine than subsequent
170
+ // loading from s2 + n.
171
+ //
92
172
  // Separate implementation for 64-bit, little-endian cpus.
93
- #if !defined(SNAPPY_IS_BIG_ENDIAN) && \
94
- (defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM))
173
+ #if !SNAPPY_IS_BIG_ENDIAN && \
174
+ (defined(__x86_64__) || defined(_M_X64) || defined(ARCH_PPC) || \
175
+ defined(ARCH_ARM))
95
176
  static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
96
177
  const char* s2,
97
- const char* s2_limit) {
178
+ const char* s2_limit,
179
+ uint64_t* data) {
98
180
  assert(s2_limit >= s2);
99
181
  size_t matched = 0;
100
182
 
@@ -103,12 +185,72 @@ static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
103
185
  // uncommon code paths that determine, without extra effort, whether the match
104
186
  // length is less than 8. In short, we are hoping to avoid a conditional
105
187
  // branch, and perhaps get better code layout from the C++ compiler.
106
- if (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 8)) {
107
- uint64 a1 = UNALIGNED_LOAD64(s1);
108
- uint64 a2 = UNALIGNED_LOAD64(s2);
109
- if (a1 != a2) {
110
- return std::pair<size_t, bool>(Bits::FindLSBSetNonZero64(a1 ^ a2) >> 3,
111
- true);
188
+ if (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 16)) {
189
+ uint64_t a1 = UNALIGNED_LOAD64(s1);
190
+ uint64_t a2 = UNALIGNED_LOAD64(s2);
191
+ if (SNAPPY_PREDICT_TRUE(a1 != a2)) {
192
+ // This code is critical for performance. The reason is that it determines
193
+ // how much to advance `ip` (s2). This obviously depends on both the loads
194
+ // from the `candidate` (s1) and `ip`. Furthermore the next `candidate`
195
+ // depends on the advanced `ip` calculated here through a load, hash and
196
+ // new candidate hash lookup (a lot of cycles). This makes s1 (ie.
197
+ // `candidate`) the variable that limits throughput. This is the reason we
198
+ // go through hoops to have this function update `data` for the next iter.
199
+ // The straightforward code would use *data, given by
200
+ //
201
+ // *data = UNALIGNED_LOAD64(s2 + matched_bytes) (Latency of 5 cycles),
202
+ //
203
+ // as input for the hash table lookup to find next candidate. However
204
+ // this forces the load on the data dependency chain of s1, because
205
+ // matched_bytes directly depends on s1. However matched_bytes is 0..7, so
206
+ // we can also calculate *data by
207
+ //
208
+ // *data = AlignRight(UNALIGNED_LOAD64(s2), UNALIGNED_LOAD64(s2 + 8),
209
+ // matched_bytes);
210
+ //
211
+ // The loads do not depend on s1 anymore and are thus off the bottleneck.
212
+ // The straightforward implementation on x86_64 would be to use
213
+ //
214
+ // shrd rax, rdx, cl (cl being matched_bytes * 8)
215
+ //
216
+ // unfortunately shrd with a variable shift has a 4 cycle latency. So this
217
+ // only wins 1 cycle. The BMI2 shrx instruction is a 1 cycle variable
218
+ // shift instruction but can only shift 64 bits. If we focus on just
219
+ // obtaining the least significant 4 bytes, we can obtain this by
220
+ //
221
+ // *data = ConditionalMove(matched_bytes < 4, UNALIGNED_LOAD64(s2),
222
+ // UNALIGNED_LOAD64(s2 + 4) >> ((matched_bytes & 3) * 8);
223
+ //
224
+ // Writen like above this is not a big win, the conditional move would be
225
+ // a cmp followed by a cmov (2 cycles) followed by a shift (1 cycle).
226
+ // However matched_bytes < 4 is equal to
227
+ // static_cast<uint32_t>(xorval) != 0. Writen that way, the conditional
228
+ // move (2 cycles) can execute in parallel with FindLSBSetNonZero64
229
+ // (tzcnt), which takes 3 cycles.
230
+ uint64_t xorval = a1 ^ a2;
231
+ int shift = Bits::FindLSBSetNonZero64(xorval);
232
+ size_t matched_bytes = shift >> 3;
233
+ uint64_t a3 = UNALIGNED_LOAD64(s2 + 4);
234
+ #ifndef __x86_64__
235
+ a2 = static_cast<uint32_t>(xorval) == 0 ? a3 : a2;
236
+ #else
237
+ // Ideally this would just be
238
+ //
239
+ // a2 = static_cast<uint32_t>(xorval) == 0 ? a3 : a2;
240
+ //
241
+ // However clang correctly infers that the above statement participates on
242
+ // a critical data dependency chain and thus, unfortunately, refuses to
243
+ // use a conditional move (it's tuned to cut data dependencies). In this
244
+ // case there is a longer parallel chain anyway AND this will be fairly
245
+ // unpredictable.
246
+ asm("testl %k2, %k2\n\t"
247
+ "cmovzq %1, %0\n\t"
248
+ : "+r"(a2)
249
+ : "r"(a3), "r"(xorval)
250
+ : "cc");
251
+ #endif
252
+ *data = a2 >> (shift & (3 * 8));
253
+ return std::pair<size_t, bool>(matched_bytes, true);
112
254
  } else {
113
255
  matched = 8;
114
256
  s2 += 8;
@@ -119,14 +261,28 @@ static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
119
261
  // time until we find a 64-bit block that doesn't match; then we find
120
262
  // the first non-matching bit and use that to calculate the total
121
263
  // length of the match.
122
- while (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 8)) {
123
- if (UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched)) {
264
+ while (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 16)) {
265
+ uint64_t a1 = UNALIGNED_LOAD64(s1 + matched);
266
+ uint64_t a2 = UNALIGNED_LOAD64(s2);
267
+ if (a1 == a2) {
124
268
  s2 += 8;
125
269
  matched += 8;
126
270
  } else {
127
- uint64 x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched);
128
- int matching_bits = Bits::FindLSBSetNonZero64(x);
129
- matched += matching_bits >> 3;
271
+ uint64_t xorval = a1 ^ a2;
272
+ int shift = Bits::FindLSBSetNonZero64(xorval);
273
+ size_t matched_bytes = shift >> 3;
274
+ uint64_t a3 = UNALIGNED_LOAD64(s2 + 4);
275
+ #ifndef __x86_64__
276
+ a2 = static_cast<uint32_t>(xorval) == 0 ? a3 : a2;
277
+ #else
278
+ asm("testl %k2, %k2\n\t"
279
+ "cmovzq %1, %0\n\t"
280
+ : "+r"(a2)
281
+ : "r"(a3), "r"(xorval)
282
+ : "cc");
283
+ #endif
284
+ *data = a2 >> (shift & (3 * 8));
285
+ matched += matched_bytes;
130
286
  assert(matched >= 8);
131
287
  return std::pair<size_t, bool>(matched, false);
132
288
  }
@@ -136,6 +292,9 @@ static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
136
292
  ++s2;
137
293
  ++matched;
138
294
  } else {
295
+ if (s2 <= s2_limit - 8) {
296
+ *data = UNALIGNED_LOAD64(s2);
297
+ }
139
298
  return std::pair<size_t, bool>(matched, matched < 8);
140
299
  }
141
300
  }
@@ -144,7 +303,8 @@ static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
144
303
  #else
145
304
  static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
146
305
  const char* s2,
147
- const char* s2_limit) {
306
+ const char* s2_limit,
307
+ uint64_t* data) {
148
308
  // Implementation based on the x86-64 version, above.
149
309
  assert(s2_limit >= s2);
150
310
  int matched = 0;
@@ -155,15 +315,17 @@ static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
155
315
  matched += 4;
156
316
  }
157
317
  if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {
158
- uint32 x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
318
+ uint32_t x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
159
319
  int matching_bits = Bits::FindLSBSetNonZero(x);
160
320
  matched += matching_bits >> 3;
321
+ s2 += matching_bits >> 3;
161
322
  } else {
162
323
  while ((s2 < s2_limit) && (s1[matched] == *s2)) {
163
324
  ++s2;
164
325
  ++matched;
165
326
  }
166
327
  }
328
+ if (s2 <= s2_limit - 8) *data = LittleEndian::Load64(s2);
167
329
  return std::pair<size_t, bool>(matched, matched < 8);
168
330
  }
169
331
  #endif
@@ -190,7 +352,8 @@ static const int kMaximumTagLength = 5; // COPY_4_BYTE_OFFSET plus the actual o
190
352
  // because of efficiency reasons:
191
353
  // (1) Extracting a byte is faster than a bit-field
192
354
  // (2) It properly aligns copy offset so we do not need a <<8
193
- static const uint16 char_table[256] = {
355
+ static constexpr uint16_t char_table[256] = {
356
+ // clang-format off
194
357
  0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002,
195
358
  0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004,
196
359
  0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006,
@@ -222,7 +385,8 @@ static const uint16 char_table[256] = {
222
385
  0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a,
223
386
  0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c,
224
387
  0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e,
225
- 0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040
388
+ 0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040,
389
+ // clang-format on
226
390
  };
227
391
 
228
392
  } // end namespace internal