libcouchbase 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (561) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +35 -0
  6. data/Gemfile +4 -0
  7. data/LICENSE +24 -0
  8. data/README.md +389 -0
  9. data/Rakefile +75 -0
  10. data/ext/README.md +6 -0
  11. data/ext/Rakefile +20 -0
  12. data/ext/libcouchbase/.gitignore +130 -0
  13. data/ext/libcouchbase/.travis.yml +19 -0
  14. data/ext/libcouchbase/CMakeLists.txt +429 -0
  15. data/ext/libcouchbase/CONTRIBUTING.md +124 -0
  16. data/ext/libcouchbase/LICENSE +202 -0
  17. data/ext/libcouchbase/README.markdown +163 -0
  18. data/ext/libcouchbase/RELEASE_NOTES.markdown +2691 -0
  19. data/ext/libcouchbase/cmake/Modules/ConfigureDtrace.cmake +27 -0
  20. data/ext/libcouchbase/cmake/Modules/CopyPDB.cmake +42 -0
  21. data/ext/libcouchbase/cmake/Modules/DistScript.cmake +17 -0
  22. data/ext/libcouchbase/cmake/Modules/DownloadLcbDep.cmake +20 -0
  23. data/ext/libcouchbase/cmake/Modules/FindCouchbaseHdrHistogram.cmake +15 -0
  24. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibev.cmake +73 -0
  25. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibevent.cmake +52 -0
  26. data/ext/libcouchbase/cmake/Modules/FindCouchbaseLibuv.cmake +56 -0
  27. data/ext/libcouchbase/cmake/Modules/FindCouchbaseSnappy.cmake +11 -0
  28. data/ext/libcouchbase/cmake/Modules/GenerateConfigDotH.cmake +29 -0
  29. data/ext/libcouchbase/cmake/Modules/GetLibcouchbaseFlags.cmake +133 -0
  30. data/ext/libcouchbase/cmake/Modules/GetPlatformCCInfo.cmake +45 -0
  31. data/ext/libcouchbase/cmake/Modules/GetVersionInfo.cmake +70 -0
  32. data/ext/libcouchbase/cmake/config-cmake.h.in +60 -0
  33. data/ext/libcouchbase/cmake/configure +357 -0
  34. data/ext/libcouchbase/cmake/defs.mk.in +8 -0
  35. data/ext/libcouchbase/cmake/dtrace-instr-link.pl +38 -0
  36. data/ext/libcouchbase/cmake/source_files.cmake +73 -0
  37. data/ext/libcouchbase/configure.pl +1 -0
  38. data/ext/libcouchbase/contrib/cJSON/cJSON.c +624 -0
  39. data/ext/libcouchbase/contrib/cJSON/cJSON.h +158 -0
  40. data/ext/libcouchbase/contrib/cbsasl/CMakeLists.txt +9 -0
  41. data/ext/libcouchbase/contrib/cbsasl/COPYING +202 -0
  42. data/ext/libcouchbase/contrib/cbsasl/include/cbsasl/cbsasl.h +217 -0
  43. data/ext/libcouchbase/contrib/cbsasl/src/client.c +205 -0
  44. data/ext/libcouchbase/contrib/cbsasl/src/common.c +46 -0
  45. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/hmac.c +67 -0
  46. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/hmac.h +33 -0
  47. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/md5.c +296 -0
  48. data/ext/libcouchbase/contrib/cbsasl/src/cram-md5/md5.h +45 -0
  49. data/ext/libcouchbase/contrib/cbsasl/src/hash.c +573 -0
  50. data/ext/libcouchbase/contrib/cbsasl/src/hash.h +15 -0
  51. data/ext/libcouchbase/contrib/cbsasl/src/util.h +31 -0
  52. data/ext/libcouchbase/contrib/cliopts/CMakeLists.txt +2 -0
  53. data/ext/libcouchbase/contrib/cliopts/cliopts.c +747 -0
  54. data/ext/libcouchbase/contrib/cliopts/cliopts.h +493 -0
  55. data/ext/libcouchbase/contrib/genhash/genhash.c +372 -0
  56. data/ext/libcouchbase/contrib/genhash/genhash.h +235 -0
  57. data/ext/libcouchbase/contrib/gtest-1.7.0/CHANGES +157 -0
  58. data/ext/libcouchbase/contrib/gtest-1.7.0/CMakeLists.txt +252 -0
  59. data/ext/libcouchbase/contrib/gtest-1.7.0/CONTRIBUTORS +37 -0
  60. data/ext/libcouchbase/contrib/gtest-1.7.0/LICENSE +28 -0
  61. data/ext/libcouchbase/contrib/gtest-1.7.0/MINIFY.sh +15 -0
  62. data/ext/libcouchbase/contrib/gtest-1.7.0/README +435 -0
  63. data/ext/libcouchbase/contrib/gtest-1.7.0/cmake/internal_utils.cmake +227 -0
  64. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-death-test.h +294 -0
  65. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-message.h +250 -0
  66. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-param-test.h +1421 -0
  67. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-param-test.h.pump +487 -0
  68. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-printers.h +855 -0
  69. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-spi.h +232 -0
  70. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-test-part.h +179 -0
  71. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest-typed-test.h +259 -0
  72. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest.h +2291 -0
  73. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest_pred_impl.h +358 -0
  74. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/gtest_prod.h +58 -0
  75. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-death-test-internal.h +319 -0
  76. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-filepath.h +206 -0
  77. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-internal.h +1158 -0
  78. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-linked_ptr.h +233 -0
  79. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h +5143 -0
  80. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util-generated.h.pump +301 -0
  81. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-param-util.h +619 -0
  82. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-port.h +1947 -0
  83. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-string.h +167 -0
  84. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-tuple.h +1012 -0
  85. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-tuple.h.pump +339 -0
  86. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h +3331 -0
  87. data/ext/libcouchbase/contrib/gtest-1.7.0/include/gtest/internal/gtest-type-util.h.pump +297 -0
  88. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-all.cc +48 -0
  89. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-death-test.cc +1344 -0
  90. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-filepath.cc +382 -0
  91. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-internal-inl.h +1218 -0
  92. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-port.cc +805 -0
  93. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-printers.cc +363 -0
  94. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-test-part.cc +110 -0
  95. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest-typed-test.cc +110 -0
  96. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest.cc +5015 -0
  97. data/ext/libcouchbase/contrib/gtest-1.7.0/src/gtest_main.cc +38 -0
  98. data/ext/libcouchbase/contrib/http_parser/LICENSE-MIT +23 -0
  99. data/ext/libcouchbase/contrib/http_parser/README.md +178 -0
  100. data/ext/libcouchbase/contrib/http_parser/http_parser.c +2060 -0
  101. data/ext/libcouchbase/contrib/http_parser/http_parser.h +321 -0
  102. data/ext/libcouchbase/contrib/jsonsl/LICENSE +20 -0
  103. data/ext/libcouchbase/contrib/jsonsl/jsonsl.c +1452 -0
  104. data/ext/libcouchbase/contrib/jsonsl/jsonsl.h +971 -0
  105. data/ext/libcouchbase/contrib/lcb-jsoncpp/CMakeLists.txt +6 -0
  106. data/ext/libcouchbase/contrib/lcb-jsoncpp/LICENSE +55 -0
  107. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp-forwards.h +255 -0
  108. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.cpp +4892 -0
  109. data/ext/libcouchbase/contrib/lcb-jsoncpp/lcb-jsoncpp.h +1961 -0
  110. data/ext/libcouchbase/contrib/snappy/CMakeLists.txt +8 -0
  111. data/ext/libcouchbase/contrib/snappy/COPYING +28 -0
  112. data/ext/libcouchbase/contrib/snappy/snappy-c.cc +90 -0
  113. data/ext/libcouchbase/contrib/snappy/snappy-c.h +138 -0
  114. data/ext/libcouchbase/contrib/snappy/snappy-internal.h +150 -0
  115. data/ext/libcouchbase/contrib/snappy/snappy-lcb-msvc.h +5 -0
  116. data/ext/libcouchbase/contrib/snappy/snappy-sinksource.cc +71 -0
  117. data/ext/libcouchbase/contrib/snappy/snappy-sinksource.h +137 -0
  118. data/ext/libcouchbase/contrib/snappy/snappy-stubs-internal.cc +42 -0
  119. data/ext/libcouchbase/contrib/snappy/snappy-stubs-internal.h +491 -0
  120. data/ext/libcouchbase/contrib/snappy/snappy-stubs-public.h +98 -0
  121. data/ext/libcouchbase/contrib/snappy/snappy.cc +1307 -0
  122. data/ext/libcouchbase/contrib/snappy/snappy.h +184 -0
  123. data/ext/libcouchbase/contrib/win32-defs/iocpdefs.h +133 -0
  124. data/ext/libcouchbase/contrib/win32-defs/mingwdefs.h +4396 -0
  125. data/ext/libcouchbase/contrib/win32-defs/win_stdint.h +258 -0
  126. data/ext/libcouchbase/example/CMakeLists.txt +37 -0
  127. data/ext/libcouchbase/example/README.markdown +47 -0
  128. data/ext/libcouchbase/example/db/db.c +167 -0
  129. data/ext/libcouchbase/example/db/vb.c +227 -0
  130. data/ext/libcouchbase/example/instancepool/main.cc +102 -0
  131. data/ext/libcouchbase/example/instancepool/pool.cc +102 -0
  132. data/ext/libcouchbase/example/instancepool/pool.h +69 -0
  133. data/ext/libcouchbase/example/libeventdirect/main.c +148 -0
  134. data/ext/libcouchbase/example/mcc/mcc.cc +246 -0
  135. data/ext/libcouchbase/example/minimal/minimal.c +130 -0
  136. data/ext/libcouchbase/example/observe/observe.c +146 -0
  137. data/ext/libcouchbase/example/subdoc/subdoc-multi.cc +132 -0
  138. data/ext/libcouchbase/example/subdoc/subdoc-simple.cc +191 -0
  139. data/ext/libcouchbase/example/tick/tick.c +119 -0
  140. data/ext/libcouchbase/example/views/views-example.cc +83 -0
  141. data/ext/libcouchbase/include/libcouchbase/_cxxwrap.h +150 -0
  142. data/ext/libcouchbase/include/libcouchbase/api-legacy.h +1689 -0
  143. data/ext/libcouchbase/include/libcouchbase/api3.h +2 -0
  144. data/ext/libcouchbase/include/libcouchbase/assert.h +44 -0
  145. data/ext/libcouchbase/include/libcouchbase/cbft.h +109 -0
  146. data/ext/libcouchbase/include/libcouchbase/cntl-private.h +356 -0
  147. data/ext/libcouchbase/include/libcouchbase/cntl.h +937 -0
  148. data/ext/libcouchbase/include/libcouchbase/configuration.h.in +23 -0
  149. data/ext/libcouchbase/include/libcouchbase/couchbase.h +3677 -0
  150. data/ext/libcouchbase/include/libcouchbase/deprecated.h +300 -0
  151. data/ext/libcouchbase/include/libcouchbase/error.h +595 -0
  152. data/ext/libcouchbase/include/libcouchbase/http.h +1 -0
  153. data/ext/libcouchbase/include/libcouchbase/iops.h +1050 -0
  154. data/ext/libcouchbase/include/libcouchbase/ixmgmt.h +263 -0
  155. data/ext/libcouchbase/include/libcouchbase/kvbuf.h +132 -0
  156. data/ext/libcouchbase/include/libcouchbase/n1ql.h +364 -0
  157. data/ext/libcouchbase/include/libcouchbase/pktfwd.h +270 -0
  158. data/ext/libcouchbase/include/libcouchbase/plugins/io/bsdio-inl.c +367 -0
  159. data/ext/libcouchbase/include/libcouchbase/plugins/io/wsaerr-inl.c +76 -0
  160. data/ext/libcouchbase/include/libcouchbase/plugins/io/wsaerr.h +199 -0
  161. data/ext/libcouchbase/include/libcouchbase/subdoc.h +312 -0
  162. data/ext/libcouchbase/include/libcouchbase/sysdefs.h +98 -0
  163. data/ext/libcouchbase/include/libcouchbase/vbucket.h +643 -0
  164. data/ext/libcouchbase/include/libcouchbase/views.h +298 -0
  165. data/ext/libcouchbase/include/libcouchbase/visibility.h +65 -0
  166. data/ext/libcouchbase/include/memcached/COPYING +30 -0
  167. data/ext/libcouchbase/include/memcached/README +10 -0
  168. data/ext/libcouchbase/include/memcached/protocol_binary.h +1916 -0
  169. data/ext/libcouchbase/include/memcached/vbucket.h +42 -0
  170. data/ext/libcouchbase/packaging/README +7 -0
  171. data/ext/libcouchbase/packaging/abicheck/.gitignore +4 -0
  172. data/ext/libcouchbase/packaging/abicheck/Makefile +17 -0
  173. data/ext/libcouchbase/packaging/abicheck/README.md +27 -0
  174. data/ext/libcouchbase/packaging/abicheck/template.xml +3 -0
  175. data/ext/libcouchbase/packaging/deb/compat +1 -0
  176. data/ext/libcouchbase/packaging/deb/control +73 -0
  177. data/ext/libcouchbase/packaging/deb/copyright +10 -0
  178. data/ext/libcouchbase/packaging/deb/libcouchbase-dev.docs +3 -0
  179. data/ext/libcouchbase/packaging/deb/package.mk +31 -0
  180. data/ext/libcouchbase/packaging/deb/rules +46 -0
  181. data/ext/libcouchbase/packaging/deb/source/format +1 -0
  182. data/ext/libcouchbase/packaging/distinfo/README +1 -0
  183. data/ext/libcouchbase/packaging/distinfo/distinfo.cmake.in +4 -0
  184. data/ext/libcouchbase/packaging/dllversion.rc.in +39 -0
  185. data/ext/libcouchbase/packaging/libcouchbase.pc.in +10 -0
  186. data/ext/libcouchbase/packaging/nuget/libcouchbase.autopkg +76 -0
  187. data/ext/libcouchbase/packaging/parse-git-describe.pl +166 -0
  188. data/ext/libcouchbase/packaging/rpm/libcouchbase.spec.in +108 -0
  189. data/ext/libcouchbase/packaging/rpm/package.mk +40 -0
  190. data/ext/libcouchbase/plugins/io/iocp/CMakeLists.txt +9 -0
  191. data/ext/libcouchbase/plugins/io/iocp/iocp_iops.c +466 -0
  192. data/ext/libcouchbase/plugins/io/iocp/iocp_iops.h +217 -0
  193. data/ext/libcouchbase/plugins/io/iocp/iocp_loop.c +295 -0
  194. data/ext/libcouchbase/plugins/io/iocp/iocp_timer.c +79 -0
  195. data/ext/libcouchbase/plugins/io/iocp/iocp_util.c +229 -0
  196. data/ext/libcouchbase/plugins/io/libev/CMakeLists.txt +29 -0
  197. data/ext/libcouchbase/plugins/io/libev/libev_io_opts.h +65 -0
  198. data/ext/libcouchbase/plugins/io/libev/plugin-libev.c +289 -0
  199. data/ext/libcouchbase/plugins/io/libevent/CMakeLists.txt +29 -0
  200. data/ext/libcouchbase/plugins/io/libevent/libevent_io_opts.h +67 -0
  201. data/ext/libcouchbase/plugins/io/libevent/plugin-libevent.c +292 -0
  202. data/ext/libcouchbase/plugins/io/libuv/CMakeLists.txt +42 -0
  203. data/ext/libcouchbase/plugins/io/libuv/libuv_compat.h +212 -0
  204. data/ext/libcouchbase/plugins/io/libuv/libuv_io_opts.h +118 -0
  205. data/ext/libcouchbase/plugins/io/libuv/plugin-internal.h +148 -0
  206. data/ext/libcouchbase/plugins/io/libuv/plugin-libuv.c +648 -0
  207. data/ext/libcouchbase/plugins/io/select/CMakeLists.txt +11 -0
  208. data/ext/libcouchbase/plugins/io/select/plugin-select.c +448 -0
  209. data/ext/libcouchbase/plugins/io/select/select_io_opts.h +39 -0
  210. data/ext/libcouchbase/src/README.md +103 -0
  211. data/ext/libcouchbase/src/aspend.h +106 -0
  212. data/ext/libcouchbase/src/auth.cc +74 -0
  213. data/ext/libcouchbase/src/auth.h +54 -0
  214. data/ext/libcouchbase/src/bootstrap.c +269 -0
  215. data/ext/libcouchbase/src/bootstrap.h +129 -0
  216. data/ext/libcouchbase/src/bucketconfig/bc_cccp.c +495 -0
  217. data/ext/libcouchbase/src/bucketconfig/bc_file.c +347 -0
  218. data/ext/libcouchbase/src/bucketconfig/bc_http.c +630 -0
  219. data/ext/libcouchbase/src/bucketconfig/bc_http.h +82 -0
  220. data/ext/libcouchbase/src/bucketconfig/bc_mcraw.c +150 -0
  221. data/ext/libcouchbase/src/bucketconfig/clconfig.h +681 -0
  222. data/ext/libcouchbase/src/bucketconfig/confmon.c +474 -0
  223. data/ext/libcouchbase/src/callbacks.c +378 -0
  224. data/ext/libcouchbase/src/cbft.cc +210 -0
  225. data/ext/libcouchbase/src/cntl.cc +847 -0
  226. data/ext/libcouchbase/src/config_static.h +159 -0
  227. data/ext/libcouchbase/src/connspec.cc +462 -0
  228. data/ext/libcouchbase/src/connspec.h +105 -0
  229. data/ext/libcouchbase/src/ctx-log-inl.h +27 -0
  230. data/ext/libcouchbase/src/dump.c +98 -0
  231. data/ext/libcouchbase/src/getconfig.c +100 -0
  232. data/ext/libcouchbase/src/gethrtime.c +109 -0
  233. data/ext/libcouchbase/src/handler.c +922 -0
  234. data/ext/libcouchbase/src/hashset.c +164 -0
  235. data/ext/libcouchbase/src/hashset.h +86 -0
  236. data/ext/libcouchbase/src/hashtable.c +75 -0
  237. data/ext/libcouchbase/src/hdr_timings.c +92 -0
  238. data/ext/libcouchbase/src/hostlist.cc +301 -0
  239. data/ext/libcouchbase/src/hostlist.h +171 -0
  240. data/ext/libcouchbase/src/http/http-priv.h +307 -0
  241. data/ext/libcouchbase/src/http/http.cc +633 -0
  242. data/ext/libcouchbase/src/http/http.h +34 -0
  243. data/ext/libcouchbase/src/http/http_io.cc +307 -0
  244. data/ext/libcouchbase/src/instance.cc +722 -0
  245. data/ext/libcouchbase/src/internal.h +244 -0
  246. data/ext/libcouchbase/src/iofactory.c +575 -0
  247. data/ext/libcouchbase/src/jsparse/parser.cc +519 -0
  248. data/ext/libcouchbase/src/jsparse/parser.h +173 -0
  249. data/ext/libcouchbase/src/lcbht/lcbht.c +282 -0
  250. data/ext/libcouchbase/src/lcbht/lcbht.h +199 -0
  251. data/ext/libcouchbase/src/lcbio/connect.c +557 -0
  252. data/ext/libcouchbase/src/lcbio/connect.h +364 -0
  253. data/ext/libcouchbase/src/lcbio/ctx.c +611 -0
  254. data/ext/libcouchbase/src/lcbio/ctx.h +405 -0
  255. data/ext/libcouchbase/src/lcbio/iotable.c +290 -0
  256. data/ext/libcouchbase/src/lcbio/iotable.h +84 -0
  257. data/ext/libcouchbase/src/lcbio/ioutils.c +350 -0
  258. data/ext/libcouchbase/src/lcbio/ioutils.h +203 -0
  259. data/ext/libcouchbase/src/lcbio/lcbio.h +51 -0
  260. data/ext/libcouchbase/src/lcbio/manager.c +584 -0
  261. data/ext/libcouchbase/src/lcbio/manager.h +156 -0
  262. data/ext/libcouchbase/src/lcbio/protoctx.c +84 -0
  263. data/ext/libcouchbase/src/lcbio/rw-inl.h +115 -0
  264. data/ext/libcouchbase/src/lcbio/ssl.h +149 -0
  265. data/ext/libcouchbase/src/lcbio/timer-ng.h +179 -0
  266. data/ext/libcouchbase/src/lcbio/timer.c +132 -0
  267. data/ext/libcouchbase/src/legacy.c +430 -0
  268. data/ext/libcouchbase/src/list.c +144 -0
  269. data/ext/libcouchbase/src/list.h +127 -0
  270. data/ext/libcouchbase/src/logging.c +244 -0
  271. data/ext/libcouchbase/src/logging.h +86 -0
  272. data/ext/libcouchbase/src/mc/compress.c +90 -0
  273. data/ext/libcouchbase/src/mc/compress.h +61 -0
  274. data/ext/libcouchbase/src/mc/forward.c +186 -0
  275. data/ext/libcouchbase/src/mc/forward.h +90 -0
  276. data/ext/libcouchbase/src/mc/iovcursor-inl.h +279 -0
  277. data/ext/libcouchbase/src/mc/iovcursor.h +66 -0
  278. data/ext/libcouchbase/src/mc/mcreq-flush-inl.h +111 -0
  279. data/ext/libcouchbase/src/mc/mcreq.c +954 -0
  280. data/ext/libcouchbase/src/mc/mcreq.h +977 -0
  281. data/ext/libcouchbase/src/mcserver/mcserver.c +784 -0
  282. data/ext/libcouchbase/src/mcserver/mcserver.h +121 -0
  283. data/ext/libcouchbase/src/mcserver/negotiate.c +656 -0
  284. data/ext/libcouchbase/src/mcserver/negotiate.h +119 -0
  285. data/ext/libcouchbase/src/n1ql/ixmgmt.cc +860 -0
  286. data/ext/libcouchbase/src/n1ql/n1ql-internal.h +22 -0
  287. data/ext/libcouchbase/src/n1ql/n1ql.cc +729 -0
  288. data/ext/libcouchbase/src/n1ql/params.cc +215 -0
  289. data/ext/libcouchbase/src/netbuf/netbuf-defs.h +89 -0
  290. data/ext/libcouchbase/src/netbuf/netbuf-mblock.h +235 -0
  291. data/ext/libcouchbase/src/netbuf/netbuf.c +929 -0
  292. data/ext/libcouchbase/src/netbuf/netbuf.h +452 -0
  293. data/ext/libcouchbase/src/newconfig.c +385 -0
  294. data/ext/libcouchbase/src/nodeinfo.cc +194 -0
  295. data/ext/libcouchbase/src/operations/cbflush.c +71 -0
  296. data/ext/libcouchbase/src/operations/counter.c +116 -0
  297. data/ext/libcouchbase/src/operations/durability-cas.c +224 -0
  298. data/ext/libcouchbase/src/operations/durability-seqno.c +157 -0
  299. data/ext/libcouchbase/src/operations/durability.c +668 -0
  300. data/ext/libcouchbase/src/operations/durability_internal.h +199 -0
  301. data/ext/libcouchbase/src/operations/get.c +409 -0
  302. data/ext/libcouchbase/src/operations/observe-seqno.c +96 -0
  303. data/ext/libcouchbase/src/operations/observe.c +340 -0
  304. data/ext/libcouchbase/src/operations/pktfwd.c +86 -0
  305. data/ext/libcouchbase/src/operations/remove.c +83 -0
  306. data/ext/libcouchbase/src/operations/stats.c +461 -0
  307. data/ext/libcouchbase/src/operations/store.c +360 -0
  308. data/ext/libcouchbase/src/operations/subdoc.cc +510 -0
  309. data/ext/libcouchbase/src/operations/touch.c +81 -0
  310. data/ext/libcouchbase/src/packetutils.c +60 -0
  311. data/ext/libcouchbase/src/packetutils.h +147 -0
  312. data/ext/libcouchbase/src/probes.d +211 -0
  313. data/ext/libcouchbase/src/rdb/bigalloc.c +225 -0
  314. data/ext/libcouchbase/src/rdb/bigalloc.h +73 -0
  315. data/ext/libcouchbase/src/rdb/chunkalloc.c +174 -0
  316. data/ext/libcouchbase/src/rdb/libcalloc.c +94 -0
  317. data/ext/libcouchbase/src/rdb/rope.c +419 -0
  318. data/ext/libcouchbase/src/rdb/rope.h +488 -0
  319. data/ext/libcouchbase/src/retrychk.c +113 -0
  320. data/ext/libcouchbase/src/retryq.c +424 -0
  321. data/ext/libcouchbase/src/retryq.h +157 -0
  322. data/ext/libcouchbase/src/ringbuffer.c +442 -0
  323. data/ext/libcouchbase/src/ringbuffer.h +100 -0
  324. data/ext/libcouchbase/src/settings.c +95 -0
  325. data/ext/libcouchbase/src/settings.h +188 -0
  326. data/ext/libcouchbase/src/simplestring.c +211 -0
  327. data/ext/libcouchbase/src/simplestring.h +228 -0
  328. data/ext/libcouchbase/src/sllist-inl.h +197 -0
  329. data/ext/libcouchbase/src/sllist.h +76 -0
  330. data/ext/libcouchbase/src/ssl/CMakeLists.txt +23 -0
  331. data/ext/libcouchbase/src/ssl/ssl_c.c +415 -0
  332. data/ext/libcouchbase/src/ssl/ssl_common.c +454 -0
  333. data/ext/libcouchbase/src/ssl/ssl_e.c +408 -0
  334. data/ext/libcouchbase/src/ssl/ssl_iot_common.h +180 -0
  335. data/ext/libcouchbase/src/ssobuf.h +82 -0
  336. data/ext/libcouchbase/src/strcodecs/base64.c +123 -0
  337. data/ext/libcouchbase/src/strcodecs/strcodecs.h +285 -0
  338. data/ext/libcouchbase/src/timings.c +208 -0
  339. data/ext/libcouchbase/src/trace.h +105 -0
  340. data/ext/libcouchbase/src/utilities.c +171 -0
  341. data/ext/libcouchbase/src/vbucket/CMakeLists.txt +2 -0
  342. data/ext/libcouchbase/src/vbucket/aliases.h +35 -0
  343. data/ext/libcouchbase/src/vbucket/crc32.h +83 -0
  344. data/ext/libcouchbase/src/vbucket/hash.h +30 -0
  345. data/ext/libcouchbase/src/vbucket/json-inl.h +112 -0
  346. data/ext/libcouchbase/src/vbucket/ketama.c +66 -0
  347. data/ext/libcouchbase/src/vbucket/rfc1321/global.h +32 -0
  348. data/ext/libcouchbase/src/vbucket/rfc1321/md5.h +35 -0
  349. data/ext/libcouchbase/src/vbucket/rfc1321/md5c-inl.h +335 -0
  350. data/ext/libcouchbase/src/vbucket/vbucket.c +1543 -0
  351. data/ext/libcouchbase/src/views/docreq.c +194 -0
  352. data/ext/libcouchbase/src/views/docreq.h +83 -0
  353. data/ext/libcouchbase/src/views/viewreq.c +358 -0
  354. data/ext/libcouchbase/src/views/viewreq.h +36 -0
  355. data/ext/libcouchbase/src/wait.c +161 -0
  356. data/ext/libcouchbase/tests/CMakeLists.txt +140 -0
  357. data/ext/libcouchbase/tests/basic/t_base64.cc +81 -0
  358. data/ext/libcouchbase/tests/basic/t_ccbc103.cc +95 -0
  359. data/ext/libcouchbase/tests/basic/t_connstr.cc +404 -0
  360. data/ext/libcouchbase/tests/basic/t_creds.cc +32 -0
  361. data/ext/libcouchbase/tests/basic/t_ctlcodes.cc +92 -0
  362. data/ext/libcouchbase/tests/basic/t_hashset.cc +262 -0
  363. data/ext/libcouchbase/tests/basic/t_host.cc +198 -0
  364. data/ext/libcouchbase/tests/basic/t_jsparse.cc +137 -0
  365. data/ext/libcouchbase/tests/basic/t_jsparse.h +589 -0
  366. data/ext/libcouchbase/tests/basic/t_list.cc +155 -0
  367. data/ext/libcouchbase/tests/basic/t_logger.cc +65 -0
  368. data/ext/libcouchbase/tests/basic/t_misc.cc +24 -0
  369. data/ext/libcouchbase/tests/basic/t_n1qlstrings.cc +18 -0
  370. data/ext/libcouchbase/tests/basic/t_netbuf.cc +446 -0
  371. data/ext/libcouchbase/tests/basic/t_packet.cc +222 -0
  372. data/ext/libcouchbase/tests/basic/t_ringbuffer.cc +278 -0
  373. data/ext/libcouchbase/tests/basic/t_slist.cc +429 -0
  374. data/ext/libcouchbase/tests/basic/t_strerror.cc +64 -0
  375. data/ext/libcouchbase/tests/basic/t_string.cc +112 -0
  376. data/ext/libcouchbase/tests/basic/t_urlencode.cc +132 -0
  377. data/ext/libcouchbase/tests/check-all.cc +608 -0
  378. data/ext/libcouchbase/tests/htparse/t_basic.cc +193 -0
  379. data/ext/libcouchbase/tests/ioserver/connection.cc +166 -0
  380. data/ext/libcouchbase/tests/ioserver/future.cc +50 -0
  381. data/ext/libcouchbase/tests/ioserver/ioserver.cc +104 -0
  382. data/ext/libcouchbase/tests/ioserver/ioserver.h +478 -0
  383. data/ext/libcouchbase/tests/ioserver/socket.cc +88 -0
  384. data/ext/libcouchbase/tests/ioserver/ssl_connection.cc +145 -0
  385. data/ext/libcouchbase/tests/ioserver/threads-pthreads.cc +119 -0
  386. data/ext/libcouchbase/tests/ioserver/threads-win32.cc +117 -0
  387. data/ext/libcouchbase/tests/ioserver/threads.h +66 -0
  388. data/ext/libcouchbase/tests/iotests/iotests.h +15 -0
  389. data/ext/libcouchbase/tests/iotests/mock-environment.cc +524 -0
  390. data/ext/libcouchbase/tests/iotests/mock-environment.h +385 -0
  391. data/ext/libcouchbase/tests/iotests/mock-unit-test.cc +67 -0
  392. data/ext/libcouchbase/tests/iotests/mock-unit-test.h +61 -0
  393. data/ext/libcouchbase/tests/iotests/serverparams.h +76 -0
  394. data/ext/libcouchbase/tests/iotests/t_arithmetic.cc +143 -0
  395. data/ext/libcouchbase/tests/iotests/t_behavior.cc +226 -0
  396. data/ext/libcouchbase/tests/iotests/t_configcache.cc +117 -0
  397. data/ext/libcouchbase/tests/iotests/t_confmon.cc +241 -0
  398. data/ext/libcouchbase/tests/iotests/t_durability.cc +1059 -0
  399. data/ext/libcouchbase/tests/iotests/t_forward.cc +110 -0
  400. data/ext/libcouchbase/tests/iotests/t_get.cc +512 -0
  401. data/ext/libcouchbase/tests/iotests/t_http.cc +438 -0
  402. data/ext/libcouchbase/tests/iotests/t_iops.cc +175 -0
  403. data/ext/libcouchbase/tests/iotests/t_lock.cc +275 -0
  404. data/ext/libcouchbase/tests/iotests/t_misc.cc +713 -0
  405. data/ext/libcouchbase/tests/iotests/t_mutate.cc +609 -0
  406. data/ext/libcouchbase/tests/iotests/t_n1ql.cc +270 -0
  407. data/ext/libcouchbase/tests/iotests/t_netfail.cc +654 -0
  408. data/ext/libcouchbase/tests/iotests/t_obseqno.cc +157 -0
  409. data/ext/libcouchbase/tests/iotests/t_regression.cc +321 -0
  410. data/ext/libcouchbase/tests/iotests/t_sched.cc +88 -0
  411. data/ext/libcouchbase/tests/iotests/t_serverops.cc +230 -0
  412. data/ext/libcouchbase/tests/iotests/t_smoke.cc +528 -0
  413. data/ext/libcouchbase/tests/iotests/t_subdoc.cc +822 -0
  414. data/ext/libcouchbase/tests/iotests/t_syncmode.cc +64 -0
  415. data/ext/libcouchbase/tests/iotests/t_views.cc +405 -0
  416. data/ext/libcouchbase/tests/iotests/testutil.cc +250 -0
  417. data/ext/libcouchbase/tests/iotests/testutil.h +163 -0
  418. data/ext/libcouchbase/tests/mc/mctest.h +119 -0
  419. data/ext/libcouchbase/tests/mc/pktmaker.h +101 -0
  420. data/ext/libcouchbase/tests/mc/t_alloc.cc +269 -0
  421. data/ext/libcouchbase/tests/mc/t_context.cc +100 -0
  422. data/ext/libcouchbase/tests/mc/t_flush.cc +185 -0
  423. data/ext/libcouchbase/tests/mc/t_forward.cc +239 -0
  424. data/ext/libcouchbase/tests/mc/t_ioflush.cc +102 -0
  425. data/ext/libcouchbase/tests/mc/t_iovcursor.cc +173 -0
  426. data/ext/libcouchbase/tests/mocksupport/procutil.c +305 -0
  427. data/ext/libcouchbase/tests/mocksupport/procutil.h +89 -0
  428. data/ext/libcouchbase/tests/mocksupport/server.c +391 -0
  429. data/ext/libcouchbase/tests/mocksupport/server.h +72 -0
  430. data/ext/libcouchbase/tests/mocksupport/timeout.c +69 -0
  431. data/ext/libcouchbase/tests/nonio_tests.cc +23 -0
  432. data/ext/libcouchbase/tests/rdb/rdbtest.h +133 -0
  433. data/ext/libcouchbase/tests/rdb/t_basic.cc +128 -0
  434. data/ext/libcouchbase/tests/rdb/t_bigalloc.cc +93 -0
  435. data/ext/libcouchbase/tests/rdb/t_refs.cc +112 -0
  436. data/ext/libcouchbase/tests/socktests/socktest.cc +347 -0
  437. data/ext/libcouchbase/tests/socktests/socktest.h +448 -0
  438. data/ext/libcouchbase/tests/socktests/t_basic.cc +143 -0
  439. data/ext/libcouchbase/tests/socktests/t_ctx.cc +73 -0
  440. data/ext/libcouchbase/tests/socktests/t_manager.cc +179 -0
  441. data/ext/libcouchbase/tests/socktests/t_putex.cc +256 -0
  442. data/ext/libcouchbase/tests/socktests/t_read.cc +187 -0
  443. data/ext/libcouchbase/tests/socktests/t_reentrant.cc +143 -0
  444. data/ext/libcouchbase/tests/socktests/t_ssl.cc +80 -0
  445. data/ext/libcouchbase/tests/socktests/t_write.cc +95 -0
  446. data/ext/libcouchbase/tests/start_mock.bat +15 -0
  447. data/ext/libcouchbase/tests/start_mock.sh +42 -0
  448. data/ext/libcouchbase/tests/unit_tests.cc +43 -0
  449. data/ext/libcouchbase/tests/vbucket/confdata/bad.json +101 -0
  450. data/ext/libcouchbase/tests/vbucket/confdata/full_25.json +363 -0
  451. data/ext/libcouchbase/tests/vbucket/confdata/memd_25.json +90 -0
  452. data/ext/libcouchbase/tests/vbucket/confdata/memd_30.json +1 -0
  453. data/ext/libcouchbase/tests/vbucket/confdata/memd_45.json +1 -0
  454. data/ext/libcouchbase/tests/vbucket/confdata/terse_25.json +291 -0
  455. data/ext/libcouchbase/tests/vbucket/confdata/terse_30.json +1 -0
  456. data/ext/libcouchbase/tests/vbucket/t_config.cc +341 -0
  457. data/ext/libcouchbase/tools/CMakeLists.txt +51 -0
  458. data/ext/libcouchbase/tools/cbc-handlers.h +462 -0
  459. data/ext/libcouchbase/tools/cbc-n1qlback.cc +439 -0
  460. data/ext/libcouchbase/tools/cbc-pillowfight.cc +822 -0
  461. data/ext/libcouchbase/tools/cbc.cc +1541 -0
  462. data/ext/libcouchbase/tools/common/histogram.cc +43 -0
  463. data/ext/libcouchbase/tools/common/histogram.h +23 -0
  464. data/ext/libcouchbase/tools/common/my_inttypes.h +22 -0
  465. data/ext/libcouchbase/tools/common/options.cc +420 -0
  466. data/ext/libcouchbase/tools/common/options.h +81 -0
  467. data/ext/libcouchbase/tools/docgen/docgen.h +469 -0
  468. data/ext/libcouchbase/tools/docgen/loc.h +210 -0
  469. data/ext/libcouchbase/tools/docgen/placeholders.h +211 -0
  470. data/ext/libcouchbase/tools/docgen/seqgen.h +94 -0
  471. data/lib/libcouchbase.rb +36 -0
  472. data/lib/libcouchbase/bucket.rb +819 -0
  473. data/lib/libcouchbase/callbacks.rb +72 -0
  474. data/lib/libcouchbase/connection.rb +790 -0
  475. data/lib/libcouchbase/design_docs.rb +86 -0
  476. data/lib/libcouchbase/error.rb +68 -0
  477. data/lib/libcouchbase/ext/libcouchbase.rb +1135 -0
  478. data/lib/libcouchbase/ext/libcouchbase/cmdbase.rb +23 -0
  479. data/lib/libcouchbase/ext/libcouchbase/cmdcounter.rb +36 -0
  480. data/lib/libcouchbase/ext/libcouchbase/cmdendure.rb +26 -0
  481. data/lib/libcouchbase/ext/libcouchbase/cmdfts.rb +24 -0
  482. data/lib/libcouchbase/ext/libcouchbase/cmdget.rb +30 -0
  483. data/lib/libcouchbase/ext/libcouchbase/cmdgetreplica.rb +49 -0
  484. data/lib/libcouchbase/ext/libcouchbase/cmdhttp.rb +58 -0
  485. data/lib/libcouchbase/ext/libcouchbase/cmdn1ql.rb +40 -0
  486. data/lib/libcouchbase/ext/libcouchbase/cmdobseqno.rb +33 -0
  487. data/lib/libcouchbase/ext/libcouchbase/cmdobserve.rb +30 -0
  488. data/lib/libcouchbase/ext/libcouchbase/cmdstore.rb +40 -0
  489. data/lib/libcouchbase/ext/libcouchbase/cmdstoredur.rb +45 -0
  490. data/lib/libcouchbase/ext/libcouchbase/cmdsubdoc.rb +49 -0
  491. data/lib/libcouchbase/ext/libcouchbase/cmdverbosity.rb +29 -0
  492. data/lib/libcouchbase/ext/libcouchbase/cmdviewquery.rb +61 -0
  493. data/lib/libcouchbase/ext/libcouchbase/contigbuf.rb +14 -0
  494. data/lib/libcouchbase/ext/libcouchbase/create_st.rb +15 -0
  495. data/lib/libcouchbase/ext/libcouchbase/create_st0.rb +23 -0
  496. data/lib/libcouchbase/ext/libcouchbase/create_st1.rb +26 -0
  497. data/lib/libcouchbase/ext/libcouchbase/create_st2.rb +32 -0
  498. data/lib/libcouchbase/ext/libcouchbase/create_st3.rb +26 -0
  499. data/lib/libcouchbase/ext/libcouchbase/crst_u.rb +20 -0
  500. data/lib/libcouchbase/ext/libcouchbase/durability_opts_st_v.rb +11 -0
  501. data/lib/libcouchbase/ext/libcouchbase/durability_opts_t.rb +14 -0
  502. data/lib/libcouchbase/ext/libcouchbase/durabilityopt_sv0.rb +63 -0
  503. data/lib/libcouchbase/ext/libcouchbase/enums.rb +991 -0
  504. data/lib/libcouchbase/ext/libcouchbase/fragbuf.rb +18 -0
  505. data/lib/libcouchbase/ext/libcouchbase/ftshandle.rb +7 -0
  506. data/lib/libcouchbase/ext/libcouchbase/histogram.rb +34 -0
  507. data/lib/libcouchbase/ext/libcouchbase/http_request_t.rb +7 -0
  508. data/lib/libcouchbase/ext/libcouchbase/keybuf.rb +20 -0
  509. data/lib/libcouchbase/ext/libcouchbase/multicmd_ctx.rb +30 -0
  510. data/lib/libcouchbase/ext/libcouchbase/mutation_token.rb +17 -0
  511. data/lib/libcouchbase/ext/libcouchbase/n1qlhandle.rb +7 -0
  512. data/lib/libcouchbase/ext/libcouchbase/n1qlparams.rb +7 -0
  513. data/lib/libcouchbase/ext/libcouchbase/respbase.rb +29 -0
  514. data/lib/libcouchbase/ext/libcouchbase/respcounter.rb +32 -0
  515. data/lib/libcouchbase/ext/libcouchbase/respendure.rb +49 -0
  516. data/lib/libcouchbase/ext/libcouchbase/respfts.rb +40 -0
  517. data/lib/libcouchbase/ext/libcouchbase/respget.rb +44 -0
  518. data/lib/libcouchbase/ext/libcouchbase/resphttp.rb +48 -0
  519. data/lib/libcouchbase/ext/libcouchbase/respmcversion.rb +38 -0
  520. data/lib/libcouchbase/ext/libcouchbase/respn1ql.rb +41 -0
  521. data/lib/libcouchbase/ext/libcouchbase/respobseqno.rb +52 -0
  522. data/lib/libcouchbase/ext/libcouchbase/respobserve.rb +41 -0
  523. data/lib/libcouchbase/ext/libcouchbase/respserverbase.rb +32 -0
  524. data/lib/libcouchbase/ext/libcouchbase/respstats.rb +38 -0
  525. data/lib/libcouchbase/ext/libcouchbase/respstore.rb +32 -0
  526. data/lib/libcouchbase/ext/libcouchbase/respstoredur.rb +38 -0
  527. data/lib/libcouchbase/ext/libcouchbase/respsubdoc.rb +35 -0
  528. data/lib/libcouchbase/ext/libcouchbase/respviewquery.rb +67 -0
  529. data/lib/libcouchbase/ext/libcouchbase/sdentry.rb +22 -0
  530. data/lib/libcouchbase/ext/libcouchbase/sdspec.rb +26 -0
  531. data/lib/libcouchbase/ext/libcouchbase/t.rb +7 -0
  532. data/lib/libcouchbase/ext/libcouchbase/valbuf.rb +22 -0
  533. data/lib/libcouchbase/ext/libcouchbase/valbuf_u_buf.rb +14 -0
  534. data/lib/libcouchbase/ext/libcouchbase/viewhandle.rb +7 -0
  535. data/lib/libcouchbase/ext/libcouchbase_iocp.rb +26 -0
  536. data/lib/libcouchbase/ext/libcouchbase_libuv.rb +18 -0
  537. data/lib/libcouchbase/ext/tasks.rb +87 -0
  538. data/lib/libcouchbase/n1ql.rb +73 -0
  539. data/lib/libcouchbase/query_full_text.rb +147 -0
  540. data/lib/libcouchbase/query_n1ql.rb +121 -0
  541. data/lib/libcouchbase/query_view.rb +129 -0
  542. data/lib/libcouchbase/results_fiber.rb +262 -0
  543. data/lib/libcouchbase/results_native.rb +211 -0
  544. data/lib/libcouchbase/version.rb +5 -0
  545. data/libcouchbase.gemspec +61 -0
  546. data/spec/bucket_spec.rb +270 -0
  547. data/spec/connection_spec.rb +277 -0
  548. data/spec/design_docs_spec.rb +23 -0
  549. data/spec/error_spec.rb +26 -0
  550. data/spec/fts_spec.rb +129 -0
  551. data/spec/n1ql_spec.rb +201 -0
  552. data/spec/results_libuv_spec.rb +229 -0
  553. data/spec/results_native_spec.rb +259 -0
  554. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/design.json +1 -0
  555. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/data-0000.cbb +0 -0
  556. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/failover.json +1 -0
  557. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/meta.json +1 -0
  558. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/seqno.json +1 -0
  559. data/spec/seed/2016-10-25T043505Z/2016-10-25T043505Z-full/bucket-default/node-127.0.0.1%3A8091/snapshot_markers.json +1 -0
  560. data/spec/view_spec.rb +195 -0
  561. metadata +775 -0
@@ -0,0 +1,98 @@
1
+ // Copyright 2011 Google Inc. All Rights Reserved.
2
+ // Author: sesse@google.com (Steinar H. Gunderson)
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
+ // Various type stubs for the open-source version of Snappy.
31
+ //
32
+ // This file cannot include config.h, as it is included from snappy.h,
33
+ // which is a public header. Instead, snappy-stubs-public.h is generated by
34
+ // from snappy-stubs-public.h.in at configure time.
35
+
36
+ #ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
37
+ #define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
38
+
39
+ #if 1
40
+ #include <stdint.h>
41
+ #endif
42
+
43
+ #if 1
44
+ #include <stddef.h>
45
+ #endif
46
+
47
+ #if 0
48
+ #include <sys/uio.h>
49
+ #endif
50
+
51
+ #define SNAPPY_MAJOR 1
52
+ #define SNAPPY_MINOR 1
53
+ #define SNAPPY_PATCHLEVEL 1
54
+ #define SNAPPY_VERSION \
55
+ ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)
56
+
57
+ #include <string>
58
+
59
+ namespace snappy {
60
+
61
+ #if 1
62
+ typedef int8_t int8;
63
+ typedef uint8_t uint8;
64
+ typedef int16_t int16;
65
+ typedef uint16_t uint16;
66
+ typedef int32_t int32;
67
+ typedef uint32_t uint32;
68
+ typedef int64_t int64;
69
+ typedef uint64_t uint64;
70
+ #else
71
+ typedef signed char int8;
72
+ typedef unsigned char uint8;
73
+ typedef short int16;
74
+ typedef unsigned short uint16;
75
+ typedef int int32;
76
+ typedef unsigned int uint32;
77
+ typedef long long int64;
78
+ typedef unsigned long long uint64;
79
+ #endif
80
+
81
+ typedef std::string string;
82
+
83
+ #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
84
+ TypeName(const TypeName&); \
85
+ void operator=(const TypeName&)
86
+
87
+ #if !0
88
+ // Windows does not have an iovec type, yet the concept is universally useful.
89
+ // It is simple to define it ourselves, so we put it inside our own namespace.
90
+ struct iovec {
91
+ void* iov_base;
92
+ size_t iov_len;
93
+ };
94
+ #endif
95
+
96
+ } // namespace snappy
97
+
98
+ #endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
@@ -0,0 +1,1307 @@
1
+ // Copyright 2005 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
+ #include "snappy.h"
30
+ #include "snappy-internal.h"
31
+ #include "snappy-sinksource.h"
32
+ #include "snappy-lcb-msvc.h" // Added by libcouchbase
33
+
34
+ #include <stdio.h>
35
+
36
+ #include <algorithm>
37
+ #include <string>
38
+ #include <vector>
39
+
40
+
41
+ namespace snappy {
42
+
43
+ // Any hash function will produce a valid compressed bitstream, but a good
44
+ // hash function reduces the number of collisions and thus yields better
45
+ // compression for compressible input, and more speed for incompressible
46
+ // input. Of course, it doesn't hurt if the hash function is reasonably fast
47
+ // either, as it gets called a lot.
48
+ static inline uint32 HashBytes(uint32 bytes, int shift) {
49
+ uint32 kMul = 0x1e35a7bd;
50
+ return (bytes * kMul) >> shift;
51
+ }
52
+ static inline uint32 Hash(const char* p, int shift) {
53
+ return HashBytes(UNALIGNED_LOAD32(p), shift);
54
+ }
55
+
56
+ size_t MaxCompressedLength(size_t source_len) {
57
+ // Compressed data can be defined as:
58
+ // compressed := item* literal*
59
+ // item := literal* copy
60
+ //
61
+ // The trailing literal sequence has a space blowup of at most 62/60
62
+ // since a literal of length 60 needs one tag byte + one extra byte
63
+ // for length information.
64
+ //
65
+ // Item blowup is trickier to measure. Suppose the "copy" op copies
66
+ // 4 bytes of data. Because of a special check in the encoding code,
67
+ // we produce a 4-byte copy only if the offset is < 65536. Therefore
68
+ // the copy op takes 3 bytes to encode, and this type of item leads
69
+ // to at most the 62/60 blowup for representing literals.
70
+ //
71
+ // Suppose the "copy" op copies 5 bytes of data. If the offset is big
72
+ // enough, it will take 5 bytes to encode the copy op. Therefore the
73
+ // worst case here is a one-byte literal followed by a five-byte copy.
74
+ // I.e., 6 bytes of input turn into 7 bytes of "compressed" data.
75
+ //
76
+ // This last factor dominates the blowup, so the final estimate is:
77
+ return 32 + source_len + source_len/6;
78
+ }
79
+
80
+ enum {
81
+ LITERAL = 0,
82
+ COPY_1_BYTE_OFFSET = 1, // 3 bit length + 3 bits of offset in opcode
83
+ COPY_2_BYTE_OFFSET = 2,
84
+ COPY_4_BYTE_OFFSET = 3
85
+ };
86
+ static const int kMaximumTagLength = 5; // COPY_4_BYTE_OFFSET plus the actual offset.
87
+
88
+ // Copy "len" bytes from "src" to "op", one byte at a time. Used for
89
+ // handling COPY operations where the input and output regions may
90
+ // overlap. For example, suppose:
91
+ // src == "ab"
92
+ // op == src + 2
93
+ // len == 20
94
+ // After IncrementalCopy(src, op, len), the result will have
95
+ // eleven copies of "ab"
96
+ // ababababababababababab
97
+ // Note that this does not match the semantics of either memcpy()
98
+ // or memmove().
99
+ static inline void IncrementalCopy(const char* src, char* op, ssize_t len) {
100
+ assert(len > 0);
101
+ do {
102
+ *op++ = *src++;
103
+ } while (--len > 0);
104
+ }
105
+
106
+ // Equivalent to IncrementalCopy except that it can write up to ten extra
107
+ // bytes after the end of the copy, and that it is faster.
108
+ //
109
+ // The main part of this loop is a simple copy of eight bytes at a time until
110
+ // we've copied (at least) the requested amount of bytes. However, if op and
111
+ // src are less than eight bytes apart (indicating a repeating pattern of
112
+ // length < 8), we first need to expand the pattern in order to get the correct
113
+ // results. For instance, if the buffer looks like this, with the eight-byte
114
+ // <src> and <op> patterns marked as intervals:
115
+ //
116
+ // abxxxxxxxxxxxx
117
+ // [------] src
118
+ // [------] op
119
+ //
120
+ // a single eight-byte copy from <src> to <op> will repeat the pattern once,
121
+ // after which we can move <op> two bytes without moving <src>:
122
+ //
123
+ // ababxxxxxxxxxx
124
+ // [------] src
125
+ // [------] op
126
+ //
127
+ // and repeat the exercise until the two no longer overlap.
128
+ //
129
+ // This allows us to do very well in the special case of one single byte
130
+ // repeated many times, without taking a big hit for more general cases.
131
+ //
132
+ // The worst case of extra writing past the end of the match occurs when
133
+ // op - src == 1 and len == 1; the last copy will read from byte positions
134
+ // [0..7] and write to [4..11], whereas it was only supposed to write to
135
+ // position 1. Thus, ten excess bytes.
136
+
137
+ namespace {
138
+
139
+ const int kMaxIncrementCopyOverflow = 10;
140
+
141
+ inline void IncrementalCopyFastPath(const char* src, char* op, ssize_t len) {
142
+ while (op - src < 8) {
143
+ UnalignedCopy64(src, op);
144
+ len -= op - src;
145
+ op += op - src;
146
+ }
147
+ while (len > 0) {
148
+ UnalignedCopy64(src, op);
149
+ src += 8;
150
+ op += 8;
151
+ len -= 8;
152
+ }
153
+ }
154
+
155
+ } // namespace
156
+
157
+ static inline char* EmitLiteral(char* op,
158
+ const char* literal,
159
+ int len,
160
+ bool allow_fast_path) {
161
+ int n = len - 1; // Zero-length literals are disallowed
162
+ if (n < 60) {
163
+ // Fits in tag byte
164
+ *op++ = LITERAL | (n << 2);
165
+
166
+ // The vast majority of copies are below 16 bytes, for which a
167
+ // call to memcpy is overkill. This fast path can sometimes
168
+ // copy up to 15 bytes too much, but that is okay in the
169
+ // main loop, since we have a bit to go on for both sides:
170
+ //
171
+ // - The input will always have kInputMarginBytes = 15 extra
172
+ // available bytes, as long as we're in the main loop, and
173
+ // if not, allow_fast_path = false.
174
+ // - The output will always have 32 spare bytes (see
175
+ // MaxCompressedLength).
176
+ if (allow_fast_path && len <= 16) {
177
+ UnalignedCopy64(literal, op);
178
+ UnalignedCopy64(literal + 8, op + 8);
179
+ return op + len;
180
+ }
181
+ } else {
182
+ // Encode in upcoming bytes
183
+ char* base = op;
184
+ int count = 0;
185
+ op++;
186
+ while (n > 0) {
187
+ *op++ = n & 0xff;
188
+ n >>= 8;
189
+ count++;
190
+ }
191
+ assert(count >= 1);
192
+ assert(count <= 4);
193
+ *base = LITERAL | ((59+count) << 2);
194
+ }
195
+ memcpy(op, literal, len);
196
+ return op + len;
197
+ }
198
+
199
+ static inline char* EmitCopyLessThan64(char* op, size_t offset, int len) {
200
+ assert(len <= 64);
201
+ assert(len >= 4);
202
+ assert(offset < 65536);
203
+
204
+ if ((len < 12) && (offset < 2048)) {
205
+ size_t len_minus_4 = len - 4;
206
+ assert(len_minus_4 < 8); // Must fit in 3 bits
207
+ *op++ = COPY_1_BYTE_OFFSET + ((len_minus_4) << 2) + ((offset >> 8) << 5);
208
+ *op++ = offset & 0xff;
209
+ } else {
210
+ *op++ = COPY_2_BYTE_OFFSET + ((len-1) << 2);
211
+ LittleEndian::Store16(op, offset);
212
+ op += 2;
213
+ }
214
+ return op;
215
+ }
216
+
217
+ static inline char* EmitCopy(char* op, size_t offset, int len) {
218
+ // Emit 64 byte copies but make sure to keep at least four bytes reserved
219
+ while (len >= 68) {
220
+ op = EmitCopyLessThan64(op, offset, 64);
221
+ len -= 64;
222
+ }
223
+
224
+ // Emit an extra 60 byte copy if have too much data to fit in one copy
225
+ if (len > 64) {
226
+ op = EmitCopyLessThan64(op, offset, 60);
227
+ len -= 60;
228
+ }
229
+
230
+ // Emit remainder
231
+ op = EmitCopyLessThan64(op, offset, len);
232
+ return op;
233
+ }
234
+
235
+
236
+ bool GetUncompressedLength(const char* start, size_t n, size_t* result) {
237
+ uint32 v = 0;
238
+ const char* limit = start + n;
239
+ if (Varint::Parse32WithLimit(start, limit, &v) != NULL) {
240
+ *result = v;
241
+ return true;
242
+ } else {
243
+ return false;
244
+ }
245
+ }
246
+
247
+ namespace internal {
248
+ uint16* WorkingMemory::GetHashTable(size_t input_size, int* table_size) {
249
+ // Use smaller hash table when input.size() is smaller, since we
250
+ // fill the table, incurring O(hash table size) overhead for
251
+ // compression, and if the input is short, we won't need that
252
+ // many hash table entries anyway.
253
+ assert(kMaxHashTableSize >= 256);
254
+ size_t htsize = 256;
255
+ while (htsize < kMaxHashTableSize && htsize < input_size) {
256
+ htsize <<= 1;
257
+ }
258
+
259
+ uint16* table;
260
+ if (htsize <= ARRAYSIZE(small_table_)) {
261
+ table = small_table_;
262
+ } else {
263
+ if (large_table_ == NULL) {
264
+ large_table_ = new uint16[kMaxHashTableSize];
265
+ }
266
+ table = large_table_;
267
+ }
268
+
269
+ *table_size = htsize;
270
+ memset(table, 0, htsize * sizeof(*table));
271
+ return table;
272
+ }
273
+ } // end namespace internal
274
+
275
+ // For 0 <= offset <= 4, GetUint32AtOffset(GetEightBytesAt(p), offset) will
276
+ // equal UNALIGNED_LOAD32(p + offset). Motivation: On x86-64 hardware we have
277
+ // empirically found that overlapping loads such as
278
+ // UNALIGNED_LOAD32(p) ... UNALIGNED_LOAD32(p+1) ... UNALIGNED_LOAD32(p+2)
279
+ // are slower than UNALIGNED_LOAD64(p) followed by shifts and casts to uint32.
280
+ //
281
+ // We have different versions for 64- and 32-bit; ideally we would avoid the
282
+ // two functions and just inline the UNALIGNED_LOAD64 call into
283
+ // GetUint32AtOffset, but GCC (at least not as of 4.6) is seemingly not clever
284
+ // enough to avoid loading the value multiple times then. For 64-bit, the load
285
+ // is done when GetEightBytesAt() is called, whereas for 32-bit, the load is
286
+ // done at GetUint32AtOffset() time.
287
+
288
+ #ifdef ARCH_K8
289
+
290
+ typedef uint64 EightBytesReference;
291
+
292
+ static inline EightBytesReference GetEightBytesAt(const char* ptr) {
293
+ return UNALIGNED_LOAD64(ptr);
294
+ }
295
+
296
+ static inline uint32 GetUint32AtOffset(uint64 v, int offset) {
297
+ assert(offset >= 0);
298
+ assert(offset <= 4);
299
+ return v >> (LittleEndian::IsLittleEndian() ? 8 * offset : 32 - 8 * offset);
300
+ }
301
+
302
+ #else
303
+
304
+ typedef const char* EightBytesReference;
305
+
306
+ static inline EightBytesReference GetEightBytesAt(const char* ptr) {
307
+ return ptr;
308
+ }
309
+
310
+ static inline uint32 GetUint32AtOffset(const char* v, int offset) {
311
+ assert(offset >= 0);
312
+ assert(offset <= 4);
313
+ return UNALIGNED_LOAD32(v + offset);
314
+ }
315
+
316
+ #endif
317
+
318
+ // Flat array compression that does not emit the "uncompressed length"
319
+ // prefix. Compresses "input" string to the "*op" buffer.
320
+ //
321
+ // REQUIRES: "input" is at most "kBlockSize" bytes long.
322
+ // REQUIRES: "op" points to an array of memory that is at least
323
+ // "MaxCompressedLength(input.size())" in size.
324
+ // REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
325
+ // REQUIRES: "table_size" is a power of two
326
+ //
327
+ // Returns an "end" pointer into "op" buffer.
328
+ // "end - op" is the compressed size of "input".
329
+ namespace internal {
330
+ char* CompressFragment(const char* input,
331
+ size_t input_size,
332
+ char* op,
333
+ uint16* table,
334
+ const int table_size) {
335
+ // "ip" is the input pointer, and "op" is the output pointer.
336
+ const char* ip = input;
337
+ assert(input_size <= kBlockSize);
338
+ assert((table_size & (table_size - 1)) == 0); // table must be power of two
339
+ const int shift = 32 - Bits::Log2Floor(table_size);
340
+ assert(static_cast<int>(kuint32max >> shift) == table_size - 1);
341
+ const char* ip_end = input + input_size;
342
+ const char* base_ip = ip;
343
+ // Bytes in [next_emit, ip) will be emitted as literal bytes. Or
344
+ // [next_emit, ip_end) after the main loop.
345
+ const char* next_emit = ip;
346
+
347
+ const size_t kInputMarginBytes = 15;
348
+ if (PREDICT_TRUE(input_size >= kInputMarginBytes)) {
349
+ const char* ip_limit = input + input_size - kInputMarginBytes;
350
+
351
+ for (uint32 next_hash = Hash(++ip, shift); ; ) {
352
+ assert(next_emit < ip);
353
+ // The body of this loop calls EmitLiteral once and then EmitCopy one or
354
+ // more times. (The exception is that when we're close to exhausting
355
+ // the input we goto emit_remainder.)
356
+ //
357
+ // In the first iteration of this loop we're just starting, so
358
+ // there's nothing to copy, so calling EmitLiteral once is
359
+ // necessary. And we only start a new iteration when the
360
+ // current iteration has determined that a call to EmitLiteral will
361
+ // precede the next call to EmitCopy (if any).
362
+ //
363
+ // Step 1: Scan forward in the input looking for a 4-byte-long match.
364
+ // If we get close to exhausting the input then goto emit_remainder.
365
+ //
366
+ // Heuristic match skipping: If 32 bytes are scanned with no matches
367
+ // found, start looking only at every other byte. If 32 more bytes are
368
+ // scanned, look at every third byte, etc.. When a match is found,
369
+ // immediately go back to looking at every byte. This is a small loss
370
+ // (~5% performance, ~0.1% density) for compressible data due to more
371
+ // bookkeeping, but for non-compressible data (such as JPEG) it's a huge
372
+ // win since the compressor quickly "realizes" the data is incompressible
373
+ // and doesn't bother looking for matches everywhere.
374
+ //
375
+ // The "skip" variable keeps track of how many bytes there are since the
376
+ // last match; dividing it by 32 (ie. right-shifting by five) gives the
377
+ // number of bytes to move ahead for each iteration.
378
+ uint32 skip = 32;
379
+
380
+ const char* next_ip = ip;
381
+ const char* candidate;
382
+ do {
383
+ ip = next_ip;
384
+ uint32 hash = next_hash;
385
+ assert(hash == Hash(ip, shift));
386
+ uint32 bytes_between_hash_lookups = skip++ >> 5;
387
+ next_ip = ip + bytes_between_hash_lookups;
388
+ if (PREDICT_FALSE(next_ip > ip_limit)) {
389
+ goto emit_remainder;
390
+ }
391
+ next_hash = Hash(next_ip, shift);
392
+ candidate = base_ip + table[hash];
393
+ assert(candidate >= base_ip);
394
+ assert(candidate < ip);
395
+
396
+ table[hash] = ip - base_ip;
397
+ } while (PREDICT_TRUE(UNALIGNED_LOAD32(ip) !=
398
+ UNALIGNED_LOAD32(candidate)));
399
+
400
+ // Step 2: A 4-byte match has been found. We'll later see if more
401
+ // than 4 bytes match. But, prior to the match, input
402
+ // bytes [next_emit, ip) are unmatched. Emit them as "literal bytes."
403
+ assert(next_emit + 16 <= ip_end);
404
+ op = EmitLiteral(op, next_emit, ip - next_emit, true);
405
+
406
+ // Step 3: Call EmitCopy, and then see if another EmitCopy could
407
+ // be our next move. Repeat until we find no match for the
408
+ // input immediately after what was consumed by the last EmitCopy call.
409
+ //
410
+ // If we exit this loop normally then we need to call EmitLiteral next,
411
+ // though we don't yet know how big the literal will be. We handle that
412
+ // by proceeding to the next iteration of the main loop. We also can exit
413
+ // this loop via goto if we get close to exhausting the input.
414
+ EightBytesReference input_bytes;
415
+ uint32 candidate_bytes = 0;
416
+
417
+ do {
418
+ // We have a 4-byte match at ip, and no need to emit any
419
+ // "literal bytes" prior to ip.
420
+ const char* base = ip;
421
+ int matched = 4 + FindMatchLength(candidate + 4, ip + 4, ip_end);
422
+ ip += matched;
423
+ size_t offset = base - candidate;
424
+ assert(0 == memcmp(base, candidate, matched));
425
+ op = EmitCopy(op, offset, matched);
426
+ // We could immediately start working at ip now, but to improve
427
+ // compression we first update table[Hash(ip - 1, ...)].
428
+ const char* insert_tail = ip - 1;
429
+ next_emit = ip;
430
+ if (PREDICT_FALSE(ip >= ip_limit)) {
431
+ goto emit_remainder;
432
+ }
433
+ input_bytes = GetEightBytesAt(insert_tail);
434
+ uint32 prev_hash = HashBytes(GetUint32AtOffset(input_bytes, 0), shift);
435
+ table[prev_hash] = ip - base_ip - 1;
436
+ uint32 cur_hash = HashBytes(GetUint32AtOffset(input_bytes, 1), shift);
437
+ candidate = base_ip + table[cur_hash];
438
+ candidate_bytes = UNALIGNED_LOAD32(candidate);
439
+ table[cur_hash] = ip - base_ip;
440
+ } while (GetUint32AtOffset(input_bytes, 1) == candidate_bytes);
441
+
442
+ next_hash = HashBytes(GetUint32AtOffset(input_bytes, 2), shift);
443
+ ++ip;
444
+ }
445
+ }
446
+
447
+ emit_remainder:
448
+ // Emit the remaining bytes as a literal
449
+ if (next_emit < ip_end) {
450
+ op = EmitLiteral(op, next_emit, ip_end - next_emit, false);
451
+ }
452
+
453
+ return op;
454
+ }
455
+ } // end namespace internal
456
+
457
+ // Signature of output types needed by decompression code.
458
+ // The decompression code is templatized on a type that obeys this
459
+ // signature so that we do not pay virtual function call overhead in
460
+ // the middle of a tight decompression loop.
461
+ //
462
+ // class DecompressionWriter {
463
+ // public:
464
+ // // Called before decompression
465
+ // void SetExpectedLength(size_t length);
466
+ //
467
+ // // Called after decompression
468
+ // bool CheckLength() const;
469
+ //
470
+ // // Called repeatedly during decompression
471
+ // bool Append(const char* ip, size_t length);
472
+ // bool AppendFromSelf(uint32 offset, size_t length);
473
+ //
474
+ // // The rules for how TryFastAppend differs from Append are somewhat
475
+ // // convoluted:
476
+ // //
477
+ // // - TryFastAppend is allowed to decline (return false) at any
478
+ // // time, for any reason -- just "return false" would be
479
+ // // a perfectly legal implementation of TryFastAppend.
480
+ // // The intention is for TryFastAppend to allow a fast path
481
+ // // in the common case of a small append.
482
+ // // - TryFastAppend is allowed to read up to <available> bytes
483
+ // // from the input buffer, whereas Append is allowed to read
484
+ // // <length>. However, if it returns true, it must leave
485
+ // // at least five (kMaximumTagLength) bytes in the input buffer
486
+ // // afterwards, so that there is always enough space to read the
487
+ // // next tag without checking for a refill.
488
+ // // - TryFastAppend must always return decline (return false)
489
+ // // if <length> is 61 or more, as in this case the literal length is not
490
+ // // decoded fully. In practice, this should not be a big problem,
491
+ // // as it is unlikely that one would implement a fast path accepting
492
+ // // this much data.
493
+ // //
494
+ // bool TryFastAppend(const char* ip, size_t available, size_t length);
495
+ // };
496
+
497
+ // -----------------------------------------------------------------------
498
+ // Lookup table for decompression code. Generated by ComputeTable() below.
499
+ // -----------------------------------------------------------------------
500
+
501
+ // Mapping from i in range [0,4] to a mask to extract the bottom 8*i bits
502
+ static const uint32 wordmask[] = {
503
+ 0u, 0xffu, 0xffffu, 0xffffffu, 0xffffffffu
504
+ };
505
+
506
+ // Data stored per entry in lookup table:
507
+ // Range Bits-used Description
508
+ // ------------------------------------
509
+ // 1..64 0..7 Literal/copy length encoded in opcode byte
510
+ // 0..7 8..10 Copy offset encoded in opcode byte / 256
511
+ // 0..4 11..13 Extra bytes after opcode
512
+ //
513
+ // We use eight bits for the length even though 7 would have sufficed
514
+ // because of efficiency reasons:
515
+ // (1) Extracting a byte is faster than a bit-field
516
+ // (2) It properly aligns copy offset so we do not need a <<8
517
+ static const uint16 char_table[256] = {
518
+ 0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002,
519
+ 0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004,
520
+ 0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006,
521
+ 0x0007, 0x080a, 0x1007, 0x2007, 0x0008, 0x080b, 0x1008, 0x2008,
522
+ 0x0009, 0x0904, 0x1009, 0x2009, 0x000a, 0x0905, 0x100a, 0x200a,
523
+ 0x000b, 0x0906, 0x100b, 0x200b, 0x000c, 0x0907, 0x100c, 0x200c,
524
+ 0x000d, 0x0908, 0x100d, 0x200d, 0x000e, 0x0909, 0x100e, 0x200e,
525
+ 0x000f, 0x090a, 0x100f, 0x200f, 0x0010, 0x090b, 0x1010, 0x2010,
526
+ 0x0011, 0x0a04, 0x1011, 0x2011, 0x0012, 0x0a05, 0x1012, 0x2012,
527
+ 0x0013, 0x0a06, 0x1013, 0x2013, 0x0014, 0x0a07, 0x1014, 0x2014,
528
+ 0x0015, 0x0a08, 0x1015, 0x2015, 0x0016, 0x0a09, 0x1016, 0x2016,
529
+ 0x0017, 0x0a0a, 0x1017, 0x2017, 0x0018, 0x0a0b, 0x1018, 0x2018,
530
+ 0x0019, 0x0b04, 0x1019, 0x2019, 0x001a, 0x0b05, 0x101a, 0x201a,
531
+ 0x001b, 0x0b06, 0x101b, 0x201b, 0x001c, 0x0b07, 0x101c, 0x201c,
532
+ 0x001d, 0x0b08, 0x101d, 0x201d, 0x001e, 0x0b09, 0x101e, 0x201e,
533
+ 0x001f, 0x0b0a, 0x101f, 0x201f, 0x0020, 0x0b0b, 0x1020, 0x2020,
534
+ 0x0021, 0x0c04, 0x1021, 0x2021, 0x0022, 0x0c05, 0x1022, 0x2022,
535
+ 0x0023, 0x0c06, 0x1023, 0x2023, 0x0024, 0x0c07, 0x1024, 0x2024,
536
+ 0x0025, 0x0c08, 0x1025, 0x2025, 0x0026, 0x0c09, 0x1026, 0x2026,
537
+ 0x0027, 0x0c0a, 0x1027, 0x2027, 0x0028, 0x0c0b, 0x1028, 0x2028,
538
+ 0x0029, 0x0d04, 0x1029, 0x2029, 0x002a, 0x0d05, 0x102a, 0x202a,
539
+ 0x002b, 0x0d06, 0x102b, 0x202b, 0x002c, 0x0d07, 0x102c, 0x202c,
540
+ 0x002d, 0x0d08, 0x102d, 0x202d, 0x002e, 0x0d09, 0x102e, 0x202e,
541
+ 0x002f, 0x0d0a, 0x102f, 0x202f, 0x0030, 0x0d0b, 0x1030, 0x2030,
542
+ 0x0031, 0x0e04, 0x1031, 0x2031, 0x0032, 0x0e05, 0x1032, 0x2032,
543
+ 0x0033, 0x0e06, 0x1033, 0x2033, 0x0034, 0x0e07, 0x1034, 0x2034,
544
+ 0x0035, 0x0e08, 0x1035, 0x2035, 0x0036, 0x0e09, 0x1036, 0x2036,
545
+ 0x0037, 0x0e0a, 0x1037, 0x2037, 0x0038, 0x0e0b, 0x1038, 0x2038,
546
+ 0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a,
547
+ 0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c,
548
+ 0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e,
549
+ 0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040
550
+ };
551
+
552
+ // In debug mode, allow optional computation of the table at startup.
553
+ // Also, check that the decompression table is correct.
554
+ #ifndef NDEBUG
555
+ DEFINE_bool(snappy_dump_decompression_table, false,
556
+ "If true, we print the decompression table at startup.");
557
+
558
+ static uint16 MakeEntry(unsigned int extra,
559
+ unsigned int len,
560
+ unsigned int copy_offset) {
561
+ // Check that all of the fields fit within the allocated space
562
+ assert(extra == (extra & 0x7)); // At most 3 bits
563
+ assert(copy_offset == (copy_offset & 0x7)); // At most 3 bits
564
+ assert(len == (len & 0x7f)); // At most 7 bits
565
+ return len | (copy_offset << 8) | (extra << 11);
566
+ }
567
+
568
+ static void ComputeTable() {
569
+ uint16 dst[256];
570
+
571
+ // Place invalid entries in all places to detect missing initialization
572
+ int assigned = 0;
573
+ for (int i = 0; i < 256; i++) {
574
+ dst[i] = 0xffff;
575
+ }
576
+
577
+ // Small LITERAL entries. We store (len-1) in the top 6 bits.
578
+ for (unsigned int len = 1; len <= 60; len++) {
579
+ dst[LITERAL | ((len-1) << 2)] = MakeEntry(0, len, 0);
580
+ assigned++;
581
+ }
582
+
583
+ // Large LITERAL entries. We use 60..63 in the high 6 bits to
584
+ // encode the number of bytes of length info that follow the opcode.
585
+ for (unsigned int extra_bytes = 1; extra_bytes <= 4; extra_bytes++) {
586
+ // We set the length field in the lookup table to 1 because extra
587
+ // bytes encode len-1.
588
+ dst[LITERAL | ((extra_bytes+59) << 2)] = MakeEntry(extra_bytes, 1, 0);
589
+ assigned++;
590
+ }
591
+
592
+ // COPY_1_BYTE_OFFSET.
593
+ //
594
+ // The tag byte in the compressed data stores len-4 in 3 bits, and
595
+ // offset/256 in 5 bits. offset%256 is stored in the next byte.
596
+ //
597
+ // This format is used for length in range [4..11] and offset in
598
+ // range [0..2047]
599
+ for (unsigned int len = 4; len < 12; len++) {
600
+ for (unsigned int offset = 0; offset < 2048; offset += 256) {
601
+ dst[COPY_1_BYTE_OFFSET | ((len-4)<<2) | ((offset>>8)<<5)] =
602
+ MakeEntry(1, len, offset>>8);
603
+ assigned++;
604
+ }
605
+ }
606
+
607
+ // COPY_2_BYTE_OFFSET.
608
+ // Tag contains len-1 in top 6 bits, and offset in next two bytes.
609
+ for (unsigned int len = 1; len <= 64; len++) {
610
+ dst[COPY_2_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(2, len, 0);
611
+ assigned++;
612
+ }
613
+
614
+ // COPY_4_BYTE_OFFSET.
615
+ // Tag contents len-1 in top 6 bits, and offset in next four bytes.
616
+ for (unsigned int len = 1; len <= 64; len++) {
617
+ dst[COPY_4_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(4, len, 0);
618
+ assigned++;
619
+ }
620
+
621
+ // Check that each entry was initialized exactly once.
622
+ if (assigned != 256) {
623
+ fprintf(stderr, "ComputeTable: assigned only %d of 256\n", assigned);
624
+ abort();
625
+ }
626
+ for (int i = 0; i < 256; i++) {
627
+ if (dst[i] == 0xffff) {
628
+ fprintf(stderr, "ComputeTable: did not assign byte %d\n", i);
629
+ abort();
630
+ }
631
+ }
632
+
633
+ if (FLAGS_snappy_dump_decompression_table) {
634
+ printf("static const uint16 char_table[256] = {\n ");
635
+ for (int i = 0; i < 256; i++) {
636
+ printf("0x%04x%s",
637
+ dst[i],
638
+ ((i == 255) ? "\n" : (((i%8) == 7) ? ",\n " : ", ")));
639
+ }
640
+ printf("};\n");
641
+ }
642
+
643
+ // Check that computed table matched recorded table
644
+ for (int i = 0; i < 256; i++) {
645
+ if (dst[i] != char_table[i]) {
646
+ fprintf(stderr, "ComputeTable: byte %d: computed (%x), expect (%x)\n",
647
+ i, static_cast<int>(dst[i]), static_cast<int>(char_table[i]));
648
+ abort();
649
+ }
650
+ }
651
+ }
652
+ #endif /* !NDEBUG */
653
+
654
+ // Helper class for decompression
655
+ class SnappyDecompressor {
656
+ private:
657
+ Source* reader_; // Underlying source of bytes to decompress
658
+ const char* ip_; // Points to next buffered byte
659
+ const char* ip_limit_; // Points just past buffered bytes
660
+ uint32 peeked_; // Bytes peeked from reader (need to skip)
661
+ bool eof_; // Hit end of input without an error?
662
+ char scratch_[kMaximumTagLength]; // See RefillTag().
663
+
664
+ // Ensure that all of the tag metadata for the next tag is available
665
+ // in [ip_..ip_limit_-1]. Also ensures that [ip,ip+4] is readable even
666
+ // if (ip_limit_ - ip_ < 5).
667
+ //
668
+ // Returns true on success, false on error or end of input.
669
+ bool RefillTag();
670
+
671
+ public:
672
+ explicit SnappyDecompressor(Source* reader)
673
+ : reader_(reader),
674
+ ip_(NULL),
675
+ ip_limit_(NULL),
676
+ peeked_(0),
677
+ eof_(false) {
678
+ }
679
+
680
+ ~SnappyDecompressor() {
681
+ // Advance past any bytes we peeked at from the reader
682
+ reader_->Skip(peeked_);
683
+ }
684
+
685
+ // Returns true iff we have hit the end of the input without an error.
686
+ bool eof() const {
687
+ return eof_;
688
+ }
689
+
690
+ // Read the uncompressed length stored at the start of the compressed data.
691
+ // On succcess, stores the length in *result and returns true.
692
+ // On failure, returns false.
693
+ bool ReadUncompressedLength(uint32* result) {
694
+ assert(ip_ == NULL); // Must not have read anything yet
695
+ // Length is encoded in 1..5 bytes
696
+ *result = 0;
697
+ uint32 shift = 0;
698
+ while (true) {
699
+ if (shift >= 32) return false;
700
+ size_t n;
701
+ const char* ip = reader_->Peek(&n);
702
+ if (n == 0) return false;
703
+ const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
704
+ reader_->Skip(1);
705
+ *result |= static_cast<uint32>(c & 0x7f) << shift;
706
+ if (c < 128) {
707
+ break;
708
+ }
709
+ shift += 7;
710
+ }
711
+ return true;
712
+ }
713
+
714
+ // Process the next item found in the input.
715
+ // Returns true if successful, false on error or end of input.
716
+ template <class Writer>
717
+ void DecompressAllTags(Writer* writer) {
718
+ const char* ip = ip_;
719
+
720
+ // We could have put this refill fragment only at the beginning of the loop.
721
+ // However, duplicating it at the end of each branch gives the compiler more
722
+ // scope to optimize the <ip_limit_ - ip> expression based on the local
723
+ // context, which overall increases speed.
724
+ #define MAYBE_REFILL() \
725
+ if (ip_limit_ - ip < kMaximumTagLength) { \
726
+ ip_ = ip; \
727
+ if (!RefillTag()) return; \
728
+ ip = ip_; \
729
+ }
730
+
731
+ MAYBE_REFILL();
732
+ for ( ;; ) {
733
+ const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip++));
734
+
735
+ if ((c & 0x3) == LITERAL) {
736
+ size_t literal_length = (c >> 2) + 1u;
737
+ if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length)) {
738
+ assert(literal_length < 61);
739
+ ip += literal_length;
740
+ // NOTE(user): There is no MAYBE_REFILL() here, as TryFastAppend()
741
+ // will not return true unless there's already at least five spare
742
+ // bytes in addition to the literal.
743
+ continue;
744
+ }
745
+ if (PREDICT_FALSE(literal_length >= 61)) {
746
+ // Long literal.
747
+ const size_t literal_length_length = literal_length - 60;
748
+ literal_length =
749
+ (LittleEndian::Load32(ip) & wordmask[literal_length_length]) + 1;
750
+ ip += literal_length_length;
751
+ }
752
+
753
+ size_t avail = ip_limit_ - ip;
754
+ while (avail < literal_length) {
755
+ if (!writer->Append(ip, avail)) return;
756
+ literal_length -= avail;
757
+ reader_->Skip(peeked_);
758
+ size_t n;
759
+ ip = reader_->Peek(&n);
760
+ avail = n;
761
+ peeked_ = avail;
762
+ if (avail == 0) return; // Premature end of input
763
+ ip_limit_ = ip + avail;
764
+ }
765
+ if (!writer->Append(ip, literal_length)) {
766
+ return;
767
+ }
768
+ ip += literal_length;
769
+ MAYBE_REFILL();
770
+ } else {
771
+ const uint32 entry = char_table[c];
772
+ const uint32 trailer = LittleEndian::Load32(ip) & wordmask[entry >> 11];
773
+ const uint32 length = entry & 0xff;
774
+ ip += entry >> 11;
775
+
776
+ // copy_offset/256 is encoded in bits 8..10. By just fetching
777
+ // those bits, we get copy_offset (since the bit-field starts at
778
+ // bit 8).
779
+ const uint32 copy_offset = entry & 0x700;
780
+ if (!writer->AppendFromSelf(copy_offset + trailer, length)) {
781
+ return;
782
+ }
783
+ MAYBE_REFILL();
784
+ }
785
+ }
786
+
787
+ #undef MAYBE_REFILL
788
+ }
789
+ };
790
+
791
+ bool SnappyDecompressor::RefillTag() {
792
+ const char* ip = ip_;
793
+ if (ip == ip_limit_) {
794
+ // Fetch a new fragment from the reader
795
+ reader_->Skip(peeked_); // All peeked bytes are used up
796
+ size_t n;
797
+ ip = reader_->Peek(&n);
798
+ peeked_ = n;
799
+ if (n == 0) {
800
+ eof_ = true;
801
+ return false;
802
+ }
803
+ ip_limit_ = ip + n;
804
+ }
805
+
806
+ // Read the tag character
807
+ assert(ip < ip_limit_);
808
+ const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
809
+ const uint32 entry = char_table[c];
810
+ const uint32 needed = (entry >> 11) + 1; // +1 byte for 'c'
811
+ assert(needed <= sizeof(scratch_));
812
+
813
+ // Read more bytes from reader if needed
814
+ uint32 nbuf = ip_limit_ - ip;
815
+ if (nbuf < needed) {
816
+ // Stitch together bytes from ip and reader to form the word
817
+ // contents. We store the needed bytes in "scratch_". They
818
+ // will be consumed immediately by the caller since we do not
819
+ // read more than we need.
820
+ memmove(scratch_, ip, nbuf);
821
+ reader_->Skip(peeked_); // All peeked bytes are used up
822
+ peeked_ = 0;
823
+ while (nbuf < needed) {
824
+ size_t length;
825
+ const char* src = reader_->Peek(&length);
826
+ if (length == 0) return false;
827
+ uint32 to_add = min<uint32>(needed - nbuf, length);
828
+ memcpy(scratch_ + nbuf, src, to_add);
829
+ nbuf += to_add;
830
+ reader_->Skip(to_add);
831
+ }
832
+ assert(nbuf == needed);
833
+ ip_ = scratch_;
834
+ ip_limit_ = scratch_ + needed;
835
+ } else if (nbuf < kMaximumTagLength) {
836
+ // Have enough bytes, but move into scratch_ so that we do not
837
+ // read past end of input
838
+ memmove(scratch_, ip, nbuf);
839
+ reader_->Skip(peeked_); // All peeked bytes are used up
840
+ peeked_ = 0;
841
+ ip_ = scratch_;
842
+ ip_limit_ = scratch_ + nbuf;
843
+ } else {
844
+ // Pass pointer to buffer returned by reader_.
845
+ ip_ = ip;
846
+ }
847
+ return true;
848
+ }
849
+
850
+ template <typename Writer>
851
+ static bool InternalUncompress(Source* r, Writer* writer) {
852
+ // Read the uncompressed length from the front of the compressed input
853
+ SnappyDecompressor decompressor(r);
854
+ uint32 uncompressed_len = 0;
855
+ if (!decompressor.ReadUncompressedLength(&uncompressed_len)) return false;
856
+ return InternalUncompressAllTags(&decompressor, writer, uncompressed_len);
857
+ }
858
+
859
+ template <typename Writer>
860
+ static bool InternalUncompressAllTags(SnappyDecompressor* decompressor,
861
+ Writer* writer,
862
+ uint32 uncompressed_len) {
863
+ writer->SetExpectedLength(uncompressed_len);
864
+
865
+ // Process the entire input
866
+ decompressor->DecompressAllTags(writer);
867
+ return (decompressor->eof() && writer->CheckLength());
868
+ }
869
+
870
+ bool GetUncompressedLength(Source* source, uint32* result) {
871
+ SnappyDecompressor decompressor(source);
872
+ return decompressor.ReadUncompressedLength(result);
873
+ }
874
+
875
+ size_t Compress(Source* reader, Sink* writer) {
876
+ size_t written = 0;
877
+ size_t N = reader->Available();
878
+ char ulength[Varint::kMax32];
879
+ char* p = Varint::Encode32(ulength, N);
880
+ writer->Append(ulength, p-ulength);
881
+ written += (p - ulength);
882
+
883
+ internal::WorkingMemory wmem;
884
+ char* scratch = NULL;
885
+ char* scratch_output = NULL;
886
+
887
+ while (N > 0) {
888
+ // Get next block to compress (without copying if possible)
889
+ size_t fragment_size;
890
+ const char* fragment = reader->Peek(&fragment_size);
891
+ assert(fragment_size != 0); // premature end of input
892
+ const size_t num_to_read = min(N, kBlockSize);
893
+ size_t bytes_read = fragment_size;
894
+
895
+ size_t pending_advance = 0;
896
+ if (bytes_read >= num_to_read) {
897
+ // Buffer returned by reader is large enough
898
+ pending_advance = num_to_read;
899
+ fragment_size = num_to_read;
900
+ } else {
901
+ // Read into scratch buffer
902
+ if (scratch == NULL) {
903
+ // If this is the last iteration, we want to allocate N bytes
904
+ // of space, otherwise the max possible kBlockSize space.
905
+ // num_to_read contains exactly the correct value
906
+ scratch = new char[num_to_read];
907
+ }
908
+ memcpy(scratch, fragment, bytes_read);
909
+ reader->Skip(bytes_read);
910
+
911
+ while (bytes_read < num_to_read) {
912
+ fragment = reader->Peek(&fragment_size);
913
+ size_t n = min<size_t>(fragment_size, num_to_read - bytes_read);
914
+ memcpy(scratch + bytes_read, fragment, n);
915
+ bytes_read += n;
916
+ reader->Skip(n);
917
+ }
918
+ assert(bytes_read == num_to_read);
919
+ fragment = scratch;
920
+ fragment_size = num_to_read;
921
+ }
922
+ assert(fragment_size == num_to_read);
923
+
924
+ // Get encoding table for compression
925
+ int table_size;
926
+ uint16* table = wmem.GetHashTable(num_to_read, &table_size);
927
+
928
+ // Compress input_fragment and append to dest
929
+ const int max_output = MaxCompressedLength(num_to_read);
930
+
931
+ // Need a scratch buffer for the output, in case the byte sink doesn't
932
+ // have room for us directly.
933
+ if (scratch_output == NULL) {
934
+ scratch_output = new char[max_output];
935
+ } else {
936
+ // Since we encode kBlockSize regions followed by a region
937
+ // which is <= kBlockSize in length, a previously allocated
938
+ // scratch_output[] region is big enough for this iteration.
939
+ }
940
+ char* dest = writer->GetAppendBuffer(max_output, scratch_output);
941
+ char* end = internal::CompressFragment(fragment, fragment_size,
942
+ dest, table, table_size);
943
+ writer->Append(dest, end - dest);
944
+ written += (end - dest);
945
+
946
+ N -= num_to_read;
947
+ reader->Skip(pending_advance);
948
+ }
949
+
950
+ delete[] scratch;
951
+ delete[] scratch_output;
952
+
953
+ return written;
954
+ }
955
+
956
+ // -----------------------------------------------------------------------
957
+ // IOVec interfaces
958
+ // -----------------------------------------------------------------------
959
+
960
+ // A type that writes to an iovec.
961
+ // Note that this is not a "ByteSink", but a type that matches the
962
+ // Writer template argument to SnappyDecompressor::DecompressAllTags().
963
+ class SnappyIOVecWriter {
964
+ private:
965
+ const struct iovec* output_iov_;
966
+ const size_t output_iov_count_;
967
+
968
+ // We are currently writing into output_iov_[curr_iov_index_].
969
+ int curr_iov_index_;
970
+
971
+ // Bytes written to output_iov_[curr_iov_index_] so far.
972
+ size_t curr_iov_written_;
973
+
974
+ // Total bytes decompressed into output_iov_ so far.
975
+ size_t total_written_;
976
+
977
+ // Maximum number of bytes that will be decompressed into output_iov_.
978
+ size_t output_limit_;
979
+
980
+ inline char* GetIOVecPointer(int index, size_t offset) {
981
+ return reinterpret_cast<char*>(output_iov_[index].iov_base) +
982
+ offset;
983
+ }
984
+
985
+ public:
986
+ // Does not take ownership of iov. iov must be valid during the
987
+ // entire lifetime of the SnappyIOVecWriter.
988
+ inline SnappyIOVecWriter(const struct iovec* iov, size_t iov_count)
989
+ : output_iov_(iov),
990
+ output_iov_count_(iov_count),
991
+ curr_iov_index_(0),
992
+ curr_iov_written_(0),
993
+ total_written_(0),
994
+ output_limit_(-1) {
995
+ }
996
+
997
+ inline void SetExpectedLength(size_t len) {
998
+ output_limit_ = len;
999
+ }
1000
+
1001
+ inline bool CheckLength() const {
1002
+ return total_written_ == output_limit_;
1003
+ }
1004
+
1005
+ inline bool Append(const char* ip, size_t len) {
1006
+ if (total_written_ + len > output_limit_) {
1007
+ return false;
1008
+ }
1009
+
1010
+ while (len > 0) {
1011
+ assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
1012
+ if (curr_iov_written_ >= output_iov_[curr_iov_index_].iov_len) {
1013
+ // This iovec is full. Go to the next one.
1014
+ if (curr_iov_index_ + 1 >= output_iov_count_) {
1015
+ return false;
1016
+ }
1017
+ curr_iov_written_ = 0;
1018
+ ++curr_iov_index_;
1019
+ }
1020
+
1021
+ const size_t to_write = std::min(
1022
+ len, output_iov_[curr_iov_index_].iov_len - curr_iov_written_);
1023
+ memcpy(GetIOVecPointer(curr_iov_index_, curr_iov_written_),
1024
+ ip,
1025
+ to_write);
1026
+ curr_iov_written_ += to_write;
1027
+ total_written_ += to_write;
1028
+ ip += to_write;
1029
+ len -= to_write;
1030
+ }
1031
+
1032
+ return true;
1033
+ }
1034
+
1035
+ inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
1036
+ const size_t space_left = output_limit_ - total_written_;
1037
+ if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16 &&
1038
+ output_iov_[curr_iov_index_].iov_len - curr_iov_written_ >= 16) {
1039
+ // Fast path, used for the majority (about 95%) of invocations.
1040
+ char* ptr = GetIOVecPointer(curr_iov_index_, curr_iov_written_);
1041
+ UnalignedCopy64(ip, ptr);
1042
+ UnalignedCopy64(ip + 8, ptr + 8);
1043
+ curr_iov_written_ += len;
1044
+ total_written_ += len;
1045
+ return true;
1046
+ }
1047
+
1048
+ return false;
1049
+ }
1050
+
1051
+ inline bool AppendFromSelf(size_t offset, size_t len) {
1052
+ if (offset > total_written_ || offset == 0) {
1053
+ return false;
1054
+ }
1055
+ const size_t space_left = output_limit_ - total_written_;
1056
+ if (len > space_left) {
1057
+ return false;
1058
+ }
1059
+
1060
+ // Locate the iovec from which we need to start the copy.
1061
+ int from_iov_index = curr_iov_index_;
1062
+ size_t from_iov_offset = curr_iov_written_;
1063
+ while (offset > 0) {
1064
+ if (from_iov_offset >= offset) {
1065
+ from_iov_offset -= offset;
1066
+ break;
1067
+ }
1068
+
1069
+ offset -= from_iov_offset;
1070
+ --from_iov_index;
1071
+ assert(from_iov_index >= 0);
1072
+ from_iov_offset = output_iov_[from_iov_index].iov_len;
1073
+ }
1074
+
1075
+ // Copy <len> bytes starting from the iovec pointed to by from_iov_index to
1076
+ // the current iovec.
1077
+ while (len > 0) {
1078
+ assert(from_iov_index <= curr_iov_index_);
1079
+ if (from_iov_index != curr_iov_index_) {
1080
+ const size_t to_copy = std::min(
1081
+ output_iov_[from_iov_index].iov_len - from_iov_offset,
1082
+ len);
1083
+ Append(GetIOVecPointer(from_iov_index, from_iov_offset), to_copy);
1084
+ len -= to_copy;
1085
+ if (len > 0) {
1086
+ ++from_iov_index;
1087
+ from_iov_offset = 0;
1088
+ }
1089
+ } else {
1090
+ assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
1091
+ size_t to_copy = std::min(output_iov_[curr_iov_index_].iov_len -
1092
+ curr_iov_written_,
1093
+ len);
1094
+ if (to_copy == 0) {
1095
+ // This iovec is full. Go to the next one.
1096
+ if (curr_iov_index_ + 1 >= output_iov_count_) {
1097
+ return false;
1098
+ }
1099
+ ++curr_iov_index_;
1100
+ curr_iov_written_ = 0;
1101
+ continue;
1102
+ }
1103
+ if (to_copy > len) {
1104
+ to_copy = len;
1105
+ }
1106
+ IncrementalCopy(GetIOVecPointer(from_iov_index, from_iov_offset),
1107
+ GetIOVecPointer(curr_iov_index_, curr_iov_written_),
1108
+ to_copy);
1109
+ curr_iov_written_ += to_copy;
1110
+ from_iov_offset += to_copy;
1111
+ total_written_ += to_copy;
1112
+ len -= to_copy;
1113
+ }
1114
+ }
1115
+
1116
+ return true;
1117
+ }
1118
+
1119
+ };
1120
+
1121
+ bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,
1122
+ const struct iovec* iov, size_t iov_cnt) {
1123
+ ByteArraySource reader(compressed, compressed_length);
1124
+ return RawUncompressToIOVec(&reader, iov, iov_cnt);
1125
+ }
1126
+
1127
+ bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,
1128
+ size_t iov_cnt) {
1129
+ SnappyIOVecWriter output(iov, iov_cnt);
1130
+ return InternalUncompress(compressed, &output);
1131
+ }
1132
+
1133
+ // -----------------------------------------------------------------------
1134
+ // Flat array interfaces
1135
+ // -----------------------------------------------------------------------
1136
+
1137
+ // A type that writes to a flat array.
1138
+ // Note that this is not a "ByteSink", but a type that matches the
1139
+ // Writer template argument to SnappyDecompressor::DecompressAllTags().
1140
+ class SnappyArrayWriter {
1141
+ private:
1142
+ char* base_;
1143
+ char* op_;
1144
+ char* op_limit_;
1145
+
1146
+ public:
1147
+ inline explicit SnappyArrayWriter(char* dst)
1148
+ : base_(dst),
1149
+ op_(dst) {
1150
+ }
1151
+
1152
+ inline void SetExpectedLength(size_t len) {
1153
+ op_limit_ = op_ + len;
1154
+ }
1155
+
1156
+ inline bool CheckLength() const {
1157
+ return op_ == op_limit_;
1158
+ }
1159
+
1160
+ inline bool Append(const char* ip, size_t len) {
1161
+ char* op = op_;
1162
+ const size_t space_left = op_limit_ - op;
1163
+ if (space_left < len) {
1164
+ return false;
1165
+ }
1166
+ memcpy(op, ip, len);
1167
+ op_ = op + len;
1168
+ return true;
1169
+ }
1170
+
1171
+ inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
1172
+ char* op = op_;
1173
+ const size_t space_left = op_limit_ - op;
1174
+ if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16) {
1175
+ // Fast path, used for the majority (about 95%) of invocations.
1176
+ UnalignedCopy64(ip, op);
1177
+ UnalignedCopy64(ip + 8, op + 8);
1178
+ op_ = op + len;
1179
+ return true;
1180
+ } else {
1181
+ return false;
1182
+ }
1183
+ }
1184
+
1185
+ inline bool AppendFromSelf(size_t offset, size_t len) {
1186
+ char* op = op_;
1187
+ const size_t space_left = op_limit_ - op;
1188
+
1189
+ // Check if we try to append from before the start of the buffer.
1190
+ // Normally this would just be a check for "produced < offset",
1191
+ // but "produced <= offset - 1u" is equivalent for every case
1192
+ // except the one where offset==0, where the right side will wrap around
1193
+ // to a very big number. This is convenient, as offset==0 is another
1194
+ // invalid case that we also want to catch, so that we do not go
1195
+ // into an infinite loop.
1196
+ assert(op >= base_);
1197
+ size_t produced = op - base_;
1198
+ if (produced <= offset - 1u) {
1199
+ return false;
1200
+ }
1201
+ if (len <= 16 && offset >= 8 && space_left >= 16) {
1202
+ // Fast path, used for the majority (70-80%) of dynamic invocations.
1203
+ UnalignedCopy64(op - offset, op);
1204
+ UnalignedCopy64(op - offset + 8, op + 8);
1205
+ } else {
1206
+ if (space_left >= len + kMaxIncrementCopyOverflow) {
1207
+ IncrementalCopyFastPath(op - offset, op, len);
1208
+ } else {
1209
+ if (space_left < len) {
1210
+ return false;
1211
+ }
1212
+ IncrementalCopy(op - offset, op, len);
1213
+ }
1214
+ }
1215
+
1216
+ op_ = op + len;
1217
+ return true;
1218
+ }
1219
+ };
1220
+
1221
+ bool RawUncompress(const char* compressed, size_t n, char* uncompressed) {
1222
+ ByteArraySource reader(compressed, n);
1223
+ return RawUncompress(&reader, uncompressed);
1224
+ }
1225
+
1226
+ bool RawUncompress(Source* compressed, char* uncompressed) {
1227
+ SnappyArrayWriter output(uncompressed);
1228
+ return InternalUncompress(compressed, &output);
1229
+ }
1230
+
1231
+ bool Uncompress(const char* compressed, size_t n, string* uncompressed) {
1232
+ size_t ulength;
1233
+ if (!GetUncompressedLength(compressed, n, &ulength)) {
1234
+ return false;
1235
+ }
1236
+ // On 32-bit builds: max_size() < kuint32max. Check for that instead
1237
+ // of crashing (e.g., consider externally specified compressed data).
1238
+ if (ulength > uncompressed->max_size()) {
1239
+ return false;
1240
+ }
1241
+ STLStringResizeUninitialized(uncompressed, ulength);
1242
+ return RawUncompress(compressed, n, string_as_array(uncompressed));
1243
+ }
1244
+
1245
+
1246
+ // A Writer that drops everything on the floor and just does validation
1247
+ class SnappyDecompressionValidator {
1248
+ private:
1249
+ size_t expected_;
1250
+ size_t produced_;
1251
+
1252
+ public:
1253
+ inline SnappyDecompressionValidator() : produced_(0) { }
1254
+ inline void SetExpectedLength(size_t len) {
1255
+ expected_ = len;
1256
+ }
1257
+ inline bool CheckLength() const {
1258
+ return expected_ == produced_;
1259
+ }
1260
+ inline bool Append(const char* ip, size_t len) {
1261
+ produced_ += len;
1262
+ return produced_ <= expected_;
1263
+ }
1264
+ inline bool TryFastAppend(const char* ip, size_t available, size_t length) {
1265
+ return false;
1266
+ }
1267
+ inline bool AppendFromSelf(size_t offset, size_t len) {
1268
+ // See SnappyArrayWriter::AppendFromSelf for an explanation of
1269
+ // the "offset - 1u" trick.
1270
+ if (produced_ <= offset - 1u) return false;
1271
+ produced_ += len;
1272
+ return produced_ <= expected_;
1273
+ }
1274
+ };
1275
+
1276
+ bool IsValidCompressedBuffer(const char* compressed, size_t n) {
1277
+ ByteArraySource reader(compressed, n);
1278
+ SnappyDecompressionValidator writer;
1279
+ return InternalUncompress(&reader, &writer);
1280
+ }
1281
+
1282
+ void RawCompress(const char* input,
1283
+ size_t input_length,
1284
+ char* compressed,
1285
+ size_t* compressed_length) {
1286
+ ByteArraySource reader(input, input_length);
1287
+ UncheckedByteArraySink writer(compressed);
1288
+ Compress(&reader, &writer);
1289
+
1290
+ // Compute how many bytes were added
1291
+ *compressed_length = (writer.CurrentDestination() - compressed);
1292
+ }
1293
+
1294
+ size_t Compress(const char* input, size_t input_length, string* compressed) {
1295
+ // Pre-grow the buffer to the max length of the compressed output
1296
+ compressed->resize(MaxCompressedLength(input_length));
1297
+
1298
+ size_t compressed_length;
1299
+ RawCompress(input, input_length, string_as_array(compressed),
1300
+ &compressed_length);
1301
+ compressed->resize(compressed_length);
1302
+ return compressed_length;
1303
+ }
1304
+
1305
+
1306
+ } // end namespace snappy
1307
+