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

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.
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_