couchbase 3.0.0.alpha.1-universal-darwin-19 → 3.0.0.alpha.2-universal-darwin-19

Sign up to get free protection for your applications and to get access to all the features.
Files changed (176) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/tests-6.0.3.yml +49 -0
  3. data/.github/workflows/tests.yml +47 -0
  4. data/.gitmodules +3 -0
  5. data/.idea/dictionaries/gem_terms.xml +5 -0
  6. data/.idea/inspectionProfiles/Project_Default.xml +1 -0
  7. data/.idea/vcs.xml +1 -0
  8. data/Gemfile +1 -0
  9. data/README.md +55 -2
  10. data/Rakefile +18 -0
  11. data/bin/init-cluster +62 -0
  12. data/bin/setup +1 -0
  13. data/couchbase.gemspec +3 -2
  14. data/examples/crud.rb +1 -2
  15. data/examples/managing_buckets.rb +47 -0
  16. data/examples/managing_collections.rb +58 -0
  17. data/examples/managing_query_indexes.rb +63 -0
  18. data/examples/query.rb +3 -2
  19. data/examples/query_with_consistency.rb +76 -0
  20. data/examples/subdocument.rb +23 -1
  21. data/ext/.clang-format +1 -1
  22. data/ext/.idea/dictionaries/couchbase_terms.xml +2 -0
  23. data/ext/.idea/vcs.xml +1 -0
  24. data/ext/CMakeLists.txt +30 -12
  25. data/ext/build_version.hxx.in +26 -0
  26. data/ext/couchbase/bucket.hxx +69 -8
  27. data/ext/couchbase/cluster.hxx +70 -54
  28. data/ext/couchbase/collections_manifest.hxx +3 -3
  29. data/ext/couchbase/configuration.hxx +14 -0
  30. data/ext/couchbase/couchbase.cxx +2044 -383
  31. data/ext/couchbase/{operations/document_id.hxx → document_id.hxx} +5 -4
  32. data/ext/couchbase/io/http_message.hxx +5 -1
  33. data/ext/couchbase/io/http_parser.hxx +2 -1
  34. data/ext/couchbase/io/http_session.hxx +6 -3
  35. data/ext/couchbase/io/{binary_message.hxx → mcbp_message.hxx} +15 -12
  36. data/ext/couchbase/io/mcbp_parser.hxx +99 -0
  37. data/ext/couchbase/io/{key_value_session.hxx → mcbp_session.hxx} +200 -95
  38. data/ext/couchbase/io/session_manager.hxx +37 -22
  39. data/ext/couchbase/mutation_token.hxx +2 -1
  40. data/ext/couchbase/operations.hxx +38 -8
  41. data/ext/couchbase/operations/bucket_create.hxx +138 -0
  42. data/ext/couchbase/operations/bucket_drop.hxx +65 -0
  43. data/ext/couchbase/operations/bucket_flush.hxx +65 -0
  44. data/ext/couchbase/operations/bucket_get.hxx +69 -0
  45. data/ext/couchbase/operations/bucket_get_all.hxx +62 -0
  46. data/ext/couchbase/operations/bucket_settings.hxx +111 -0
  47. data/ext/couchbase/operations/bucket_update.hxx +115 -0
  48. data/ext/couchbase/operations/cluster_developer_preview_enable.hxx +60 -0
  49. data/ext/couchbase/operations/collection_create.hxx +86 -0
  50. data/ext/couchbase/operations/collection_drop.hxx +82 -0
  51. data/ext/couchbase/operations/command.hxx +10 -10
  52. data/ext/couchbase/operations/document_decrement.hxx +80 -0
  53. data/ext/couchbase/operations/document_exists.hxx +80 -0
  54. data/ext/couchbase/operations/{get.hxx → document_get.hxx} +4 -2
  55. data/ext/couchbase/operations/document_get_and_lock.hxx +64 -0
  56. data/ext/couchbase/operations/document_get_and_touch.hxx +64 -0
  57. data/ext/couchbase/operations/document_increment.hxx +80 -0
  58. data/ext/couchbase/operations/document_insert.hxx +74 -0
  59. data/ext/couchbase/operations/{lookup_in.hxx → document_lookup_in.hxx} +2 -2
  60. data/ext/couchbase/operations/{mutate_in.hxx → document_mutate_in.hxx} +11 -2
  61. data/ext/couchbase/operations/{query.hxx → document_query.hxx} +101 -6
  62. data/ext/couchbase/operations/document_remove.hxx +67 -0
  63. data/ext/couchbase/operations/document_replace.hxx +76 -0
  64. data/ext/couchbase/operations/{upsert.hxx → document_touch.hxx} +14 -14
  65. data/ext/couchbase/operations/{remove.hxx → document_unlock.hxx} +12 -10
  66. data/ext/couchbase/operations/document_upsert.hxx +74 -0
  67. data/ext/couchbase/operations/query_index_build_deferred.hxx +85 -0
  68. data/ext/couchbase/operations/query_index_create.hxx +134 -0
  69. data/ext/couchbase/operations/query_index_drop.hxx +108 -0
  70. data/ext/couchbase/operations/query_index_get_all.hxx +106 -0
  71. data/ext/couchbase/operations/scope_create.hxx +81 -0
  72. data/ext/couchbase/operations/scope_drop.hxx +79 -0
  73. data/ext/couchbase/operations/scope_get_all.hxx +72 -0
  74. data/ext/couchbase/protocol/client_opcode.hxx +35 -0
  75. data/ext/couchbase/protocol/client_request.hxx +56 -9
  76. data/ext/couchbase/protocol/client_response.hxx +52 -15
  77. data/ext/couchbase/protocol/cmd_cluster_map_change_notification.hxx +81 -0
  78. data/ext/couchbase/protocol/cmd_decrement.hxx +187 -0
  79. data/ext/couchbase/protocol/cmd_exists.hxx +171 -0
  80. data/ext/couchbase/protocol/cmd_get.hxx +31 -8
  81. data/ext/couchbase/protocol/cmd_get_and_lock.hxx +142 -0
  82. data/ext/couchbase/protocol/cmd_get_and_touch.hxx +142 -0
  83. data/ext/couchbase/protocol/cmd_get_cluster_config.hxx +16 -3
  84. data/ext/couchbase/protocol/cmd_get_collections_manifest.hxx +16 -3
  85. data/ext/couchbase/protocol/cmd_get_error_map.hxx +16 -3
  86. data/ext/couchbase/protocol/cmd_hello.hxx +24 -8
  87. data/ext/couchbase/protocol/cmd_increment.hxx +187 -0
  88. data/ext/couchbase/protocol/cmd_info.hxx +1 -0
  89. data/ext/couchbase/protocol/cmd_insert.hxx +172 -0
  90. data/ext/couchbase/protocol/cmd_lookup_in.hxx +28 -13
  91. data/ext/couchbase/protocol/cmd_mutate_in.hxx +65 -13
  92. data/ext/couchbase/protocol/cmd_remove.hxx +59 -4
  93. data/ext/couchbase/protocol/cmd_replace.hxx +172 -0
  94. data/ext/couchbase/protocol/cmd_sasl_auth.hxx +15 -3
  95. data/ext/couchbase/protocol/cmd_sasl_list_mechs.hxx +15 -3
  96. data/ext/couchbase/protocol/cmd_sasl_step.hxx +15 -3
  97. data/ext/couchbase/protocol/cmd_select_bucket.hxx +14 -2
  98. data/ext/couchbase/protocol/cmd_touch.hxx +102 -0
  99. data/ext/couchbase/protocol/cmd_unlock.hxx +95 -0
  100. data/ext/couchbase/protocol/cmd_upsert.hxx +50 -14
  101. data/ext/couchbase/protocol/durability_level.hxx +67 -0
  102. data/ext/couchbase/protocol/frame_info_id.hxx +187 -0
  103. data/ext/couchbase/protocol/hello_feature.hxx +137 -0
  104. data/ext/couchbase/protocol/server_opcode.hxx +57 -0
  105. data/ext/couchbase/protocol/server_request.hxx +122 -0
  106. data/ext/couchbase/protocol/unsigned_leb128.h +15 -15
  107. data/ext/couchbase/utils/byteswap.hxx +1 -2
  108. data/ext/couchbase/utils/url_codec.hxx +225 -0
  109. data/ext/couchbase/version.hxx +3 -1
  110. data/ext/extconf.rb +4 -1
  111. data/ext/test/main.cxx +37 -113
  112. data/ext/third_party/snappy/.appveyor.yml +36 -0
  113. data/ext/third_party/snappy/.gitignore +8 -0
  114. data/ext/third_party/snappy/.travis.yml +98 -0
  115. data/ext/third_party/snappy/AUTHORS +1 -0
  116. data/ext/third_party/snappy/CMakeLists.txt +345 -0
  117. data/ext/third_party/snappy/CONTRIBUTING.md +26 -0
  118. data/ext/third_party/snappy/COPYING +54 -0
  119. data/ext/third_party/snappy/NEWS +188 -0
  120. data/ext/third_party/snappy/README.md +148 -0
  121. data/ext/third_party/snappy/cmake/SnappyConfig.cmake.in +33 -0
  122. data/ext/third_party/snappy/cmake/config.h.in +59 -0
  123. data/ext/third_party/snappy/docs/README.md +72 -0
  124. data/ext/third_party/snappy/format_description.txt +110 -0
  125. data/ext/third_party/snappy/framing_format.txt +135 -0
  126. data/ext/third_party/snappy/snappy-c.cc +90 -0
  127. data/ext/third_party/snappy/snappy-c.h +138 -0
  128. data/ext/third_party/snappy/snappy-internal.h +315 -0
  129. data/ext/third_party/snappy/snappy-sinksource.cc +121 -0
  130. data/ext/third_party/snappy/snappy-sinksource.h +182 -0
  131. data/ext/third_party/snappy/snappy-stubs-internal.cc +42 -0
  132. data/ext/third_party/snappy/snappy-stubs-internal.h +493 -0
  133. data/ext/third_party/snappy/snappy-stubs-public.h.in +63 -0
  134. data/ext/third_party/snappy/snappy-test.cc +613 -0
  135. data/ext/third_party/snappy/snappy-test.h +526 -0
  136. data/ext/third_party/snappy/snappy.cc +1770 -0
  137. data/ext/third_party/snappy/snappy.h +209 -0
  138. data/ext/third_party/snappy/snappy_compress_fuzzer.cc +60 -0
  139. data/ext/third_party/snappy/snappy_uncompress_fuzzer.cc +58 -0
  140. data/ext/third_party/snappy/snappy_unittest.cc +1512 -0
  141. data/ext/third_party/snappy/testdata/alice29.txt +3609 -0
  142. data/ext/third_party/snappy/testdata/asyoulik.txt +4122 -0
  143. data/ext/third_party/snappy/testdata/baddata1.snappy +0 -0
  144. data/ext/third_party/snappy/testdata/baddata2.snappy +0 -0
  145. data/ext/third_party/snappy/testdata/baddata3.snappy +0 -0
  146. data/ext/third_party/snappy/testdata/fireworks.jpeg +0 -0
  147. data/ext/third_party/snappy/testdata/geo.protodata +0 -0
  148. data/ext/third_party/snappy/testdata/html +1 -0
  149. data/ext/third_party/snappy/testdata/html_x_4 +1 -0
  150. data/ext/third_party/snappy/testdata/kppkn.gtb +0 -0
  151. data/ext/third_party/snappy/testdata/lcet10.txt +7519 -0
  152. data/ext/third_party/snappy/testdata/paper-100k.pdf +600 -2
  153. data/ext/third_party/snappy/testdata/plrabn12.txt +10699 -0
  154. data/ext/third_party/snappy/testdata/urls.10K +10000 -0
  155. data/lib/couchbase/binary_collection.rb +33 -76
  156. data/lib/couchbase/binary_collection_options.rb +94 -0
  157. data/lib/couchbase/bucket.rb +9 -3
  158. data/lib/couchbase/cluster.rb +161 -23
  159. data/lib/couchbase/collection.rb +108 -191
  160. data/lib/couchbase/collection_options.rb +430 -0
  161. data/lib/couchbase/errors.rb +136 -134
  162. data/lib/couchbase/json_transcoder.rb +32 -0
  163. data/lib/couchbase/management/analytics_index_manager.rb +185 -9
  164. data/lib/couchbase/management/bucket_manager.rb +84 -33
  165. data/lib/couchbase/management/collection_manager.rb +166 -1
  166. data/lib/couchbase/management/query_index_manager.rb +261 -0
  167. data/lib/couchbase/management/search_index_manager.rb +291 -0
  168. data/lib/couchbase/management/user_manager.rb +12 -10
  169. data/lib/couchbase/management/view_index_manager.rb +151 -1
  170. data/lib/couchbase/mutation_state.rb +11 -1
  171. data/lib/couchbase/scope.rb +4 -4
  172. data/lib/couchbase/version.rb +1 -1
  173. metadata +113 -18
  174. data/.travis.yml +0 -7
  175. data/ext/couchbase/io/binary_parser.hxx +0 -64
  176. data/lib/couchbase/results.rb +0 -307
@@ -0,0 +1,138 @@
1
+ /*
2
+ * Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
3
+ *
4
+ * Redistribution and use in source and binary forms, with or without
5
+ * modification, are permitted provided that the following conditions are
6
+ * met:
7
+ *
8
+ * * Redistributions of source code must retain the above copyright
9
+ * notice, this list of conditions and the following disclaimer.
10
+ * * Redistributions in binary form must reproduce the above
11
+ * copyright notice, this list of conditions and the following disclaimer
12
+ * in the documentation and/or other materials provided with the
13
+ * distribution.
14
+ * * Neither the name of Google Inc. nor the names of its
15
+ * contributors may be used to endorse or promote products derived from
16
+ * this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+ *
30
+ * Plain C interface (a wrapper around the C++ implementation).
31
+ */
32
+
33
+ #ifndef THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_
34
+ #define THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_
35
+
36
+ #ifdef __cplusplus
37
+ extern "C" {
38
+ #endif
39
+
40
+ #include <stddef.h>
41
+
42
+ /*
43
+ * Return values; see the documentation for each function to know
44
+ * what each can return.
45
+ */
46
+ typedef enum {
47
+ SNAPPY_OK = 0,
48
+ SNAPPY_INVALID_INPUT = 1,
49
+ SNAPPY_BUFFER_TOO_SMALL = 2
50
+ } snappy_status;
51
+
52
+ /*
53
+ * Takes the data stored in "input[0..input_length-1]" and stores
54
+ * it in the array pointed to by "compressed".
55
+ *
56
+ * <compressed_length> signals the space available in "compressed".
57
+ * If it is not at least equal to "snappy_max_compressed_length(input_length)",
58
+ * SNAPPY_BUFFER_TOO_SMALL is returned. After successful compression,
59
+ * <compressed_length> contains the true length of the compressed output,
60
+ * and SNAPPY_OK is returned.
61
+ *
62
+ * Example:
63
+ * size_t output_length = snappy_max_compressed_length(input_length);
64
+ * char* output = (char*)malloc(output_length);
65
+ * if (snappy_compress(input, input_length, output, &output_length)
66
+ * == SNAPPY_OK) {
67
+ * ... Process(output, output_length) ...
68
+ * }
69
+ * free(output);
70
+ */
71
+ snappy_status snappy_compress(const char* input,
72
+ size_t input_length,
73
+ char* compressed,
74
+ size_t* compressed_length);
75
+
76
+ /*
77
+ * Given data in "compressed[0..compressed_length-1]" generated by
78
+ * calling the snappy_compress routine, this routine stores
79
+ * the uncompressed data to
80
+ * uncompressed[0..uncompressed_length-1].
81
+ * Returns failure (a value not equal to SNAPPY_OK) if the message
82
+ * is corrupted and could not be decrypted.
83
+ *
84
+ * <uncompressed_length> signals the space available in "uncompressed".
85
+ * If it is not at least equal to the value returned by
86
+ * snappy_uncompressed_length for this stream, SNAPPY_BUFFER_TOO_SMALL
87
+ * is returned. After successful decompression, <uncompressed_length>
88
+ * contains the true length of the decompressed output.
89
+ *
90
+ * Example:
91
+ * size_t output_length;
92
+ * if (snappy_uncompressed_length(input, input_length, &output_length)
93
+ * != SNAPPY_OK) {
94
+ * ... fail ...
95
+ * }
96
+ * char* output = (char*)malloc(output_length);
97
+ * if (snappy_uncompress(input, input_length, output, &output_length)
98
+ * == SNAPPY_OK) {
99
+ * ... Process(output, output_length) ...
100
+ * }
101
+ * free(output);
102
+ */
103
+ snappy_status snappy_uncompress(const char* compressed,
104
+ size_t compressed_length,
105
+ char* uncompressed,
106
+ size_t* uncompressed_length);
107
+
108
+ /*
109
+ * Returns the maximal size of the compressed representation of
110
+ * input data that is "source_length" bytes in length.
111
+ */
112
+ size_t snappy_max_compressed_length(size_t source_length);
113
+
114
+ /*
115
+ * REQUIRES: "compressed[]" was produced by snappy_compress()
116
+ * Returns SNAPPY_OK and stores the length of the uncompressed data in
117
+ * *result normally. Returns SNAPPY_INVALID_INPUT on parsing error.
118
+ * This operation takes O(1) time.
119
+ */
120
+ snappy_status snappy_uncompressed_length(const char* compressed,
121
+ size_t compressed_length,
122
+ size_t* result);
123
+
124
+ /*
125
+ * Check if the contents of "compressed[]" can be uncompressed successfully.
126
+ * Does not return the uncompressed data; if so, returns SNAPPY_OK,
127
+ * or if not, returns SNAPPY_INVALID_INPUT.
128
+ * Takes time proportional to compressed_length, but is usually at least a
129
+ * factor of four faster than actual decompression.
130
+ */
131
+ snappy_status snappy_validate_compressed_buffer(const char* compressed,
132
+ size_t compressed_length);
133
+
134
+ #ifdef __cplusplus
135
+ } // extern "C"
136
+ #endif
137
+
138
+ #endif /* THIRD_PARTY_SNAPPY_OPENSOURCE_SNAPPY_C_H_ */
@@ -0,0 +1,315 @@
1
+ // Copyright 2008 Google Inc. All Rights Reserved.
2
+ //
3
+ // Redistribution and use in source and binary forms, with or without
4
+ // modification, are permitted provided that the following conditions are
5
+ // met:
6
+ //
7
+ // * Redistributions of source code must retain the above copyright
8
+ // notice, this list of conditions and the following disclaimer.
9
+ // * Redistributions in binary form must reproduce the above
10
+ // copyright notice, this list of conditions and the following disclaimer
11
+ // in the documentation and/or other materials provided with the
12
+ // distribution.
13
+ // * Neither the name of Google Inc. nor the names of its
14
+ // contributors may be used to endorse or promote products derived from
15
+ // this software without specific prior written permission.
16
+ //
17
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ //
29
+ // Internals shared between the Snappy implementation and its unittest.
30
+
31
+ #ifndef THIRD_PARTY_SNAPPY_SNAPPY_INTERNAL_H_
32
+ #define THIRD_PARTY_SNAPPY_SNAPPY_INTERNAL_H_
33
+
34
+ #include "snappy-stubs-internal.h"
35
+
36
+ namespace snappy {
37
+ namespace internal {
38
+
39
+ // Working memory performs a single allocation to hold all scratch space
40
+ // required for compression.
41
+ class WorkingMemory {
42
+ public:
43
+ explicit WorkingMemory(size_t input_size);
44
+ ~WorkingMemory();
45
+
46
+ // Allocates and clears a hash table using memory in "*this",
47
+ // stores the number of buckets in "*table_size" and returns a pointer to
48
+ // the base of the hash table.
49
+ uint16_t* GetHashTable(size_t fragment_size, int* table_size) const;
50
+ char* GetScratchInput() const { return input_; }
51
+ char* GetScratchOutput() const { return output_; }
52
+
53
+ private:
54
+ char* mem_; // the allocated memory, never nullptr
55
+ size_t size_; // the size of the allocated memory, never 0
56
+ uint16_t* 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
59
+
60
+ // No copying
61
+ WorkingMemory(const WorkingMemory&);
62
+ void operator=(const WorkingMemory&);
63
+ };
64
+
65
+ // Flat array compression that does not emit the "uncompressed length"
66
+ // prefix. Compresses "input" string to the "*op" buffer.
67
+ //
68
+ // REQUIRES: "input_length <= kBlockSize"
69
+ // REQUIRES: "op" points to an array of memory that is at least
70
+ // "MaxCompressedLength(input_length)" in size.
71
+ // REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
72
+ // REQUIRES: "table_size" is a power of two
73
+ //
74
+ // Returns an "end" pointer into "op" buffer.
75
+ // "end - op" is the compressed size of "input".
76
+ char* CompressFragment(const char* input,
77
+ size_t input_length,
78
+ char* op,
79
+ uint16_t* table,
80
+ const int table_size);
81
+
82
+ // Find the largest n such that
83
+ //
84
+ // s1[0,n-1] == s2[0,n-1]
85
+ // and n <= (s2_limit - s2).
86
+ //
87
+ // Return make_pair(n, n < 8).
88
+ // Does not read *s2_limit or beyond.
89
+ // Does not read *(s1 + (s2_limit - s2)) or beyond.
90
+ // Requires that s2_limit >= s2.
91
+ //
92
+ // In addition populate *data with the next 5 bytes from the end of the match.
93
+ // This is only done if 8 bytes are available (s2_limit - s2 >= 8). The point is
94
+ // that on some arch's this can be done faster in this routine than subsequent
95
+ // loading from s2 + n.
96
+ //
97
+ // Separate implementation for 64-bit, little-endian cpus.
98
+ #if !defined(SNAPPY_IS_BIG_ENDIAN) && \
99
+ (defined(ARCH_K8) || defined(ARCH_PPC) || defined(ARCH_ARM))
100
+ static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
101
+ const char* s2,
102
+ const char* s2_limit,
103
+ uint64_t* data) {
104
+ assert(s2_limit >= s2);
105
+ size_t matched = 0;
106
+
107
+ // This block isn't necessary for correctness; we could just start looping
108
+ // immediately. As an optimization though, it is useful. It creates some not
109
+ // uncommon code paths that determine, without extra effort, whether the match
110
+ // length is less than 8. In short, we are hoping to avoid a conditional
111
+ // branch, and perhaps get better code layout from the C++ compiler.
112
+ if (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 16)) {
113
+ uint64_t a1 = UNALIGNED_LOAD64(s1);
114
+ uint64_t a2 = UNALIGNED_LOAD64(s2);
115
+ if (SNAPPY_PREDICT_TRUE(a1 != a2)) {
116
+ // This code is critical for performance. The reason is that it determines
117
+ // how much to advance `ip` (s2). This obviously depends on both the loads
118
+ // from the `candidate` (s1) and `ip`. Furthermore the next `candidate`
119
+ // depends on the advanced `ip` calculated here through a load, hash and
120
+ // new candidate hash lookup (a lot of cycles). This makes s1 (ie.
121
+ // `candidate`) the variable that limits throughput. This is the reason we
122
+ // go through hoops to have this function update `data` for the next iter.
123
+ // The straightforward code would use *data, given by
124
+ //
125
+ // *data = UNALIGNED_LOAD64(s2 + matched_bytes) (Latency of 5 cycles),
126
+ //
127
+ // as input for the hash table lookup to find next candidate. However
128
+ // this forces the load on the data dependency chain of s1, because
129
+ // matched_bytes directly depends on s1. However matched_bytes is 0..7, so
130
+ // we can also calculate *data by
131
+ //
132
+ // *data = AlignRight(UNALIGNED_LOAD64(s2), UNALIGNED_LOAD64(s2 + 8),
133
+ // matched_bytes);
134
+ //
135
+ // The loads do not depend on s1 anymore and are thus off the bottleneck.
136
+ // The straightforward implementation on x86_64 would be to use
137
+ //
138
+ // shrd rax, rdx, cl (cl being matched_bytes * 8)
139
+ //
140
+ // unfortunately shrd with a variable shift has a 4 cycle latency. So this
141
+ // only wins 1 cycle. The BMI2 shrx instruction is a 1 cycle variable
142
+ // shift instruction but can only shift 64 bits. If we focus on just
143
+ // obtaining the least significant 4 bytes, we can obtain this by
144
+ //
145
+ // *data = ConditionalMove(matched_bytes < 4, UNALIGNED_LOAD64(s2),
146
+ // UNALIGNED_LOAD64(s2 + 4) >> ((matched_bytes & 3) * 8);
147
+ //
148
+ // Writen like above this is not a big win, the conditional move would be
149
+ // a cmp followed by a cmov (2 cycles) followed by a shift (1 cycle).
150
+ // However matched_bytes < 4 is equal to
151
+ // static_cast<uint32_t>(xorval) != 0. Writen that way, the conditional
152
+ // move (2 cycles) can execute in parallel with FindLSBSetNonZero64
153
+ // (tzcnt), which takes 3 cycles.
154
+ uint64_t xorval = a1 ^ a2;
155
+ int shift = Bits::FindLSBSetNonZero64(xorval);
156
+ size_t matched_bytes = shift >> 3;
157
+ #ifndef __x86_64__
158
+ *data = UNALIGNED_LOAD64(s2 + matched_bytes);
159
+ #else
160
+ // Ideally this would just be
161
+ //
162
+ // a2 = static_cast<uint32_t>(xorval) == 0 ? a3 : a2;
163
+ //
164
+ // However clang correctly infers that the above statement participates on
165
+ // a critical data dependency chain and thus, unfortunately, refuses to
166
+ // use a conditional move (it's tuned to cut data dependencies). In this
167
+ // case there is a longer parallel chain anyway AND this will be fairly
168
+ // unpredictable.
169
+ uint64_t a3 = UNALIGNED_LOAD64(s2 + 4);
170
+ asm("testl %k2, %k2\n\t"
171
+ "cmovzq %1, %0\n\t"
172
+ : "+r"(a2)
173
+ : "r"(a3), "r"(xorval));
174
+ *data = a2 >> (shift & (3 * 8));
175
+ #endif
176
+ return std::pair<size_t, bool>(matched_bytes, true);
177
+ } else {
178
+ matched = 8;
179
+ s2 += 8;
180
+ }
181
+ }
182
+
183
+ // Find out how long the match is. We loop over the data 64 bits at a
184
+ // time until we find a 64-bit block that doesn't match; then we find
185
+ // the first non-matching bit and use that to calculate the total
186
+ // length of the match.
187
+ while (SNAPPY_PREDICT_TRUE(s2 <= s2_limit - 16)) {
188
+ uint64_t a1 = UNALIGNED_LOAD64(s1 + matched);
189
+ uint64_t a2 = UNALIGNED_LOAD64(s2);
190
+ if (a1 == a2) {
191
+ s2 += 8;
192
+ matched += 8;
193
+ } else {
194
+ uint64_t xorval = a1 ^ a2;
195
+ int shift = Bits::FindLSBSetNonZero64(xorval);
196
+ size_t matched_bytes = shift >> 3;
197
+ #ifndef __x86_64__
198
+ *data = UNALIGNED_LOAD64(s2 + matched_bytes);
199
+ #else
200
+ uint64_t a3 = UNALIGNED_LOAD64(s2 + 4);
201
+ asm("testl %k2, %k2\n\t"
202
+ "cmovzq %1, %0\n\t"
203
+ : "+r"(a2)
204
+ : "r"(a3), "r"(xorval));
205
+ *data = a2 >> (shift & (3 * 8));
206
+ #endif
207
+ matched += matched_bytes;
208
+ assert(matched >= 8);
209
+ return std::pair<size_t, bool>(matched, false);
210
+ }
211
+ }
212
+ while (SNAPPY_PREDICT_TRUE(s2 < s2_limit)) {
213
+ if (s1[matched] == *s2) {
214
+ ++s2;
215
+ ++matched;
216
+ } else {
217
+ if (s2 <= s2_limit - 8) {
218
+ *data = UNALIGNED_LOAD64(s2);
219
+ }
220
+ return std::pair<size_t, bool>(matched, matched < 8);
221
+ }
222
+ }
223
+ return std::pair<size_t, bool>(matched, matched < 8);
224
+ }
225
+ #else
226
+ static inline std::pair<size_t, bool> FindMatchLength(const char* s1,
227
+ const char* s2,
228
+ const char* s2_limit,
229
+ uint64_t* data) {
230
+ // Implementation based on the x86-64 version, above.
231
+ assert(s2_limit >= s2);
232
+ int matched = 0;
233
+
234
+ while (s2 <= s2_limit - 4 &&
235
+ UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) {
236
+ s2 += 4;
237
+ matched += 4;
238
+ }
239
+ if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {
240
+ uint32_t x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
241
+ int matching_bits = Bits::FindLSBSetNonZero(x);
242
+ matched += matching_bits >> 3;
243
+ s2 += matching_bits >> 3;
244
+ } else {
245
+ while ((s2 < s2_limit) && (s1[matched] == *s2)) {
246
+ ++s2;
247
+ ++matched;
248
+ }
249
+ }
250
+ if (s2 <= s2_limit - 8) *data = LittleEndian::Load64(s2);
251
+ return std::pair<size_t, bool>(matched, matched < 8);
252
+ }
253
+ #endif
254
+
255
+ // Lookup tables for decompression code. Give --snappy_dump_decompression_table
256
+ // to the unit test to recompute char_table.
257
+
258
+ enum {
259
+ LITERAL = 0,
260
+ COPY_1_BYTE_OFFSET = 1, // 3 bit length + 3 bits of offset in opcode
261
+ COPY_2_BYTE_OFFSET = 2,
262
+ COPY_4_BYTE_OFFSET = 3
263
+ };
264
+ static const int kMaximumTagLength = 5; // COPY_4_BYTE_OFFSET plus the actual offset.
265
+
266
+ // Data stored per entry in lookup table:
267
+ // Range Bits-used Description
268
+ // ------------------------------------
269
+ // 1..64 0..7 Literal/copy length encoded in opcode byte
270
+ // 0..7 8..10 Copy offset encoded in opcode byte / 256
271
+ // 0..4 11..13 Extra bytes after opcode
272
+ //
273
+ // We use eight bits for the length even though 7 would have sufficed
274
+ // because of efficiency reasons:
275
+ // (1) Extracting a byte is faster than a bit-field
276
+ // (2) It properly aligns copy offset so we do not need a <<8
277
+ static const uint16_t char_table[256] = {
278
+ 0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002,
279
+ 0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004,
280
+ 0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006,
281
+ 0x0007, 0x080a, 0x1007, 0x2007, 0x0008, 0x080b, 0x1008, 0x2008,
282
+ 0x0009, 0x0904, 0x1009, 0x2009, 0x000a, 0x0905, 0x100a, 0x200a,
283
+ 0x000b, 0x0906, 0x100b, 0x200b, 0x000c, 0x0907, 0x100c, 0x200c,
284
+ 0x000d, 0x0908, 0x100d, 0x200d, 0x000e, 0x0909, 0x100e, 0x200e,
285
+ 0x000f, 0x090a, 0x100f, 0x200f, 0x0010, 0x090b, 0x1010, 0x2010,
286
+ 0x0011, 0x0a04, 0x1011, 0x2011, 0x0012, 0x0a05, 0x1012, 0x2012,
287
+ 0x0013, 0x0a06, 0x1013, 0x2013, 0x0014, 0x0a07, 0x1014, 0x2014,
288
+ 0x0015, 0x0a08, 0x1015, 0x2015, 0x0016, 0x0a09, 0x1016, 0x2016,
289
+ 0x0017, 0x0a0a, 0x1017, 0x2017, 0x0018, 0x0a0b, 0x1018, 0x2018,
290
+ 0x0019, 0x0b04, 0x1019, 0x2019, 0x001a, 0x0b05, 0x101a, 0x201a,
291
+ 0x001b, 0x0b06, 0x101b, 0x201b, 0x001c, 0x0b07, 0x101c, 0x201c,
292
+ 0x001d, 0x0b08, 0x101d, 0x201d, 0x001e, 0x0b09, 0x101e, 0x201e,
293
+ 0x001f, 0x0b0a, 0x101f, 0x201f, 0x0020, 0x0b0b, 0x1020, 0x2020,
294
+ 0x0021, 0x0c04, 0x1021, 0x2021, 0x0022, 0x0c05, 0x1022, 0x2022,
295
+ 0x0023, 0x0c06, 0x1023, 0x2023, 0x0024, 0x0c07, 0x1024, 0x2024,
296
+ 0x0025, 0x0c08, 0x1025, 0x2025, 0x0026, 0x0c09, 0x1026, 0x2026,
297
+ 0x0027, 0x0c0a, 0x1027, 0x2027, 0x0028, 0x0c0b, 0x1028, 0x2028,
298
+ 0x0029, 0x0d04, 0x1029, 0x2029, 0x002a, 0x0d05, 0x102a, 0x202a,
299
+ 0x002b, 0x0d06, 0x102b, 0x202b, 0x002c, 0x0d07, 0x102c, 0x202c,
300
+ 0x002d, 0x0d08, 0x102d, 0x202d, 0x002e, 0x0d09, 0x102e, 0x202e,
301
+ 0x002f, 0x0d0a, 0x102f, 0x202f, 0x0030, 0x0d0b, 0x1030, 0x2030,
302
+ 0x0031, 0x0e04, 0x1031, 0x2031, 0x0032, 0x0e05, 0x1032, 0x2032,
303
+ 0x0033, 0x0e06, 0x1033, 0x2033, 0x0034, 0x0e07, 0x1034, 0x2034,
304
+ 0x0035, 0x0e08, 0x1035, 0x2035, 0x0036, 0x0e09, 0x1036, 0x2036,
305
+ 0x0037, 0x0e0a, 0x1037, 0x2037, 0x0038, 0x0e0b, 0x1038, 0x2038,
306
+ 0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a,
307
+ 0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c,
308
+ 0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e,
309
+ 0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040
310
+ };
311
+
312
+ } // end namespace internal
313
+ } // end namespace snappy
314
+
315
+ #endif // THIRD_PARTY_SNAPPY_SNAPPY_INTERNAL_H_