redis-server 0.0.1

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 (290) hide show
  1. data/LICENSE +38 -0
  2. data/README.md +33 -0
  3. data/bin/redis +114 -0
  4. data/redis/Makefile +5 -0
  5. data/redis/extconf.rb +3 -0
  6. data/redis/redis-2.2.11/00-RELEASENOTES +199 -0
  7. data/redis/redis-2.2.11/BUGS +1 -0
  8. data/redis/redis-2.2.11/CONTRIBUTING +13 -0
  9. data/redis/redis-2.2.11/COPYING +10 -0
  10. data/redis/redis-2.2.11/Changelog +1032 -0
  11. data/redis/redis-2.2.11/INSTALL +30 -0
  12. data/redis/redis-2.2.11/Makefile +22 -0
  13. data/redis/redis-2.2.11/README +83 -0
  14. data/redis/redis-2.2.11/TODO +4 -0
  15. data/redis/redis-2.2.11/client-libraries/README +11 -0
  16. data/redis/redis-2.2.11/deps/hiredis/COPYING +10 -0
  17. data/redis/redis-2.2.11/deps/hiredis/Makefile +115 -0
  18. data/redis/redis-2.2.11/deps/hiredis/README.md +311 -0
  19. data/redis/redis-2.2.11/deps/hiredis/TODO +2 -0
  20. data/redis/redis-2.2.11/deps/hiredis/adapters/ae.h +95 -0
  21. data/redis/redis-2.2.11/deps/hiredis/adapters/libev.h +113 -0
  22. data/redis/redis-2.2.11/deps/hiredis/adapters/libevent.h +76 -0
  23. data/redis/redis-2.2.11/deps/hiredis/async.c +321 -0
  24. data/redis/redis-2.2.11/deps/hiredis/async.h +112 -0
  25. data/redis/redis-2.2.11/deps/hiredis/example-ae.c +53 -0
  26. data/redis/redis-2.2.11/deps/hiredis/example-libev.c +47 -0
  27. data/redis/redis-2.2.11/deps/hiredis/example-libevent.c +48 -0
  28. data/redis/redis-2.2.11/deps/hiredis/example.c +67 -0
  29. data/redis/redis-2.2.11/deps/hiredis/fmacros.h +15 -0
  30. data/redis/redis-2.2.11/deps/hiredis/hiredis.c +1058 -0
  31. data/redis/redis-2.2.11/deps/hiredis/hiredis.h +170 -0
  32. data/redis/redis-2.2.11/deps/hiredis/net.c +170 -0
  33. data/redis/redis-2.2.11/deps/hiredis/net.h +43 -0
  34. data/redis/redis-2.2.11/deps/hiredis/sds.c +479 -0
  35. data/redis/redis-2.2.11/deps/hiredis/sds.h +77 -0
  36. data/redis/redis-2.2.11/deps/hiredis/test.c +479 -0
  37. data/redis/redis-2.2.11/deps/hiredis/util.h +40 -0
  38. data/redis/redis-2.2.11/deps/linenoise/Makefile +10 -0
  39. data/redis/redis-2.2.11/deps/linenoise/README.markdown +45 -0
  40. data/redis/redis-2.2.11/deps/linenoise/example.c +27 -0
  41. data/redis/redis-2.2.11/deps/linenoise/linenoise.c +609 -0
  42. data/redis/redis-2.2.11/deps/linenoise/linenoise.h +55 -0
  43. data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER +214 -0
  44. data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER-2 +343 -0
  45. data/redis/redis-2.2.11/doc/AppendCommand.html +48 -0
  46. data/redis/redis-2.2.11/doc/AppendOnlyFileHowto.html +41 -0
  47. data/redis/redis-2.2.11/doc/AuthCommand.html +39 -0
  48. data/redis/redis-2.2.11/doc/Benchmarks.html +129 -0
  49. data/redis/redis-2.2.11/doc/BgrewriteaofCommand.html +41 -0
  50. data/redis/redis-2.2.11/doc/BgsaveCommand.html +39 -0
  51. data/redis/redis-2.2.11/doc/BlpopCommand.html +51 -0
  52. data/redis/redis-2.2.11/doc/BrpoplpushCommand.html +39 -0
  53. data/redis/redis-2.2.11/doc/CommandReference.html +47 -0
  54. data/redis/redis-2.2.11/doc/Comparisons.html +42 -0
  55. data/redis/redis-2.2.11/doc/ConfigCommand.html +76 -0
  56. data/redis/redis-2.2.11/doc/Configuration.html +38 -0
  57. data/redis/redis-2.2.11/doc/ConnectionHandlingSidebar.html +36 -0
  58. data/redis/redis-2.2.11/doc/ControlCommandsSidebar.html +36 -0
  59. data/redis/redis-2.2.11/doc/Credits.html +38 -0
  60. data/redis/redis-2.2.11/doc/DbsizeCommand.html +38 -0
  61. data/redis/redis-2.2.11/doc/DelCommand.html +41 -0
  62. data/redis/redis-2.2.11/doc/DesignPatterns.html +37 -0
  63. data/redis/redis-2.2.11/doc/EventLibray.html +44 -0
  64. data/redis/redis-2.2.11/doc/ExistsCommand.html +42 -0
  65. data/redis/redis-2.2.11/doc/ExpireCommand.html +96 -0
  66. data/redis/redis-2.2.11/doc/FAQ.html +70 -0
  67. data/redis/redis-2.2.11/doc/Features.html +38 -0
  68. data/redis/redis-2.2.11/doc/FlushallCommand.html +39 -0
  69. data/redis/redis-2.2.11/doc/FlushdbCommand.html +39 -0
  70. data/redis/redis-2.2.11/doc/FromSqlToDataStructures.html +37 -0
  71. data/redis/redis-2.2.11/doc/GenericCommandsSidebar.html +36 -0
  72. data/redis/redis-2.2.11/doc/GetCommand.html +39 -0
  73. data/redis/redis-2.2.11/doc/GetbitCommand.html +39 -0
  74. data/redis/redis-2.2.11/doc/GetsetCommand.html +38 -0
  75. data/redis/redis-2.2.11/doc/HackingStrings.html +83 -0
  76. data/redis/redis-2.2.11/doc/HashCommandsSidebar.html +36 -0
  77. data/redis/redis-2.2.11/doc/Hashes.html +37 -0
  78. data/redis/redis-2.2.11/doc/HdelCommand.html +39 -0
  79. data/redis/redis-2.2.11/doc/HexistsCommand.html +39 -0
  80. data/redis/redis-2.2.11/doc/HgetCommand.html +39 -0
  81. data/redis/redis-2.2.11/doc/HgetallCommand.html +40 -0
  82. data/redis/redis-2.2.11/doc/HincrbyCommand.html +45 -0
  83. data/redis/redis-2.2.11/doc/HlenCommand.html +38 -0
  84. data/redis/redis-2.2.11/doc/HmgetCommand.html +40 -0
  85. data/redis/redis-2.2.11/doc/HmsetCommand.html +40 -0
  86. data/redis/redis-2.2.11/doc/HsetCommand.html +40 -0
  87. data/redis/redis-2.2.11/doc/HsetnxCommand.html +41 -0
  88. data/redis/redis-2.2.11/doc/IncrCommand.html +43 -0
  89. data/redis/redis-2.2.11/doc/InfoCommand.html +48 -0
  90. data/redis/redis-2.2.11/doc/IntroductionToRedisDataTypes.html +152 -0
  91. data/redis/redis-2.2.11/doc/KeysCommand.html +43 -0
  92. data/redis/redis-2.2.11/doc/LastsaveCommand.html +39 -0
  93. data/redis/redis-2.2.11/doc/LindexCommand.html +40 -0
  94. data/redis/redis-2.2.11/doc/ListCommandsSidebar.html +36 -0
  95. data/redis/redis-2.2.11/doc/Lists.html +42 -0
  96. data/redis/redis-2.2.11/doc/LlenCommand.html +41 -0
  97. data/redis/redis-2.2.11/doc/LpopCommand.html +41 -0
  98. data/redis/redis-2.2.11/doc/LrangeCommand.html +47 -0
  99. data/redis/redis-2.2.11/doc/LremCommand.html +41 -0
  100. data/redis/redis-2.2.11/doc/LsetCommand.html +38 -0
  101. data/redis/redis-2.2.11/doc/LtrimCommand.html +47 -0
  102. data/redis/redis-2.2.11/doc/MgetCommand.html +52 -0
  103. data/redis/redis-2.2.11/doc/MonitorCommand.html +63 -0
  104. data/redis/redis-2.2.11/doc/MoveCommand.html +42 -0
  105. data/redis/redis-2.2.11/doc/MsetCommand.html +44 -0
  106. data/redis/redis-2.2.11/doc/MultiExecCommand.html +166 -0
  107. data/redis/redis-2.2.11/doc/NonexistentCommands.html +51 -0
  108. data/redis/redis-2.2.11/doc/ObjectHashMappers.html +39 -0
  109. data/redis/redis-2.2.11/doc/Pipelining.html +36 -0
  110. data/redis/redis-2.2.11/doc/ProgrammingExamples.html +38 -0
  111. data/redis/redis-2.2.11/doc/ProtocolSpecification.html +137 -0
  112. data/redis/redis-2.2.11/doc/PublishSubscribe.html +115 -0
  113. data/redis/redis-2.2.11/doc/QuickStart.html +68 -0
  114. data/redis/redis-2.2.11/doc/QuitCommand.html +38 -0
  115. data/redis/redis-2.2.11/doc/README.html +119 -0
  116. data/redis/redis-2.2.11/doc/RandomkeyCommand.html +39 -0
  117. data/redis/redis-2.2.11/doc/Redis0100ChangeLog.html +67 -0
  118. data/redis/redis-2.2.11/doc/Redis0900ChangeLog.html +56 -0
  119. data/redis/redis-2.2.11/doc/RedisBigData.html +61 -0
  120. data/redis/redis-2.2.11/doc/RedisCLI.html +37 -0
  121. data/redis/redis-2.2.11/doc/RedisEventLibrary.html +70 -0
  122. data/redis/redis-2.2.11/doc/RedisGuides.html +37 -0
  123. data/redis/redis-2.2.11/doc/RedisInternals.html +38 -0
  124. data/redis/redis-2.2.11/doc/RedisPipelining.html +93 -0
  125. data/redis/redis-2.2.11/doc/RedisStatus.html +56 -0
  126. data/redis/redis-2.2.11/doc/Redis_1_2_0_Changelog.html +40 -0
  127. data/redis/redis-2.2.11/doc/Redis_2_0_0_Changelog.html +62 -0
  128. data/redis/redis-2.2.11/doc/Redis_2_0_Whats_new.html +59 -0
  129. data/redis/redis-2.2.11/doc/RenameCommand.html +39 -0
  130. data/redis/redis-2.2.11/doc/RenamenxCommand.html +42 -0
  131. data/redis/redis-2.2.11/doc/ReplicationHowto.html +43 -0
  132. data/redis/redis-2.2.11/doc/ReplyTypes.html +42 -0
  133. data/redis/redis-2.2.11/doc/RoadMap.html +38 -0
  134. data/redis/redis-2.2.11/doc/RpoplpushCommand.html +44 -0
  135. data/redis/redis-2.2.11/doc/RpushCommand.html +40 -0
  136. data/redis/redis-2.2.11/doc/SaddCommand.html +41 -0
  137. data/redis/redis-2.2.11/doc/SaveCommand.html +39 -0
  138. data/redis/redis-2.2.11/doc/ScardCommand.html +41 -0
  139. data/redis/redis-2.2.11/doc/SdiffCommand.html +45 -0
  140. data/redis/redis-2.2.11/doc/SdiffstoreCommand.html +38 -0
  141. data/redis/redis-2.2.11/doc/SelectCommand.html +39 -0
  142. data/redis/redis-2.2.11/doc/SetCommand.html +39 -0
  143. data/redis/redis-2.2.11/doc/SetCommandsSidebar.html +36 -0
  144. data/redis/redis-2.2.11/doc/SetbitCommand.html +45 -0
  145. data/redis/redis-2.2.11/doc/SetexCommand.html +42 -0
  146. data/redis/redis-2.2.11/doc/SetnxCommand.html +51 -0
  147. data/redis/redis-2.2.11/doc/SetrangeCommand.html +58 -0
  148. data/redis/redis-2.2.11/doc/Sets.html +36 -0
  149. data/redis/redis-2.2.11/doc/ShutdownCommand.html +39 -0
  150. data/redis/redis-2.2.11/doc/SideBar.html +36 -0
  151. data/redis/redis-2.2.11/doc/SinterCommand.html +40 -0
  152. data/redis/redis-2.2.11/doc/SinterstoreCommand.html +39 -0
  153. data/redis/redis-2.2.11/doc/SismemberCommand.html +42 -0
  154. data/redis/redis-2.2.11/doc/SlaveofCommand.html +41 -0
  155. data/redis/redis-2.2.11/doc/SmembersCommand.html +38 -0
  156. data/redis/redis-2.2.11/doc/SmoveCommand.html +44 -0
  157. data/redis/redis-2.2.11/doc/SortCommand.html +75 -0
  158. data/redis/redis-2.2.11/doc/SortedSetCommandsSidebar.html +36 -0
  159. data/redis/redis-2.2.11/doc/SortedSets.html +36 -0
  160. data/redis/redis-2.2.11/doc/Speed.html +38 -0
  161. data/redis/redis-2.2.11/doc/SponsorshipHistory.html +38 -0
  162. data/redis/redis-2.2.11/doc/SpopCommand.html +40 -0
  163. data/redis/redis-2.2.11/doc/SrandmemberCommand.html +40 -0
  164. data/redis/redis-2.2.11/doc/SremCommand.html +42 -0
  165. data/redis/redis-2.2.11/doc/StringCommandsSidebar.html +36 -0
  166. data/redis/redis-2.2.11/doc/Strings.html +37 -0
  167. data/redis/redis-2.2.11/doc/StrlenCommand.html +39 -0
  168. data/redis/redis-2.2.11/doc/SubstrCommand.html +52 -0
  169. data/redis/redis-2.2.11/doc/SunionCommand.html +40 -0
  170. data/redis/redis-2.2.11/doc/SunionstoreCommand.html +38 -0
  171. data/redis/redis-2.2.11/doc/SupportedLanguages.html +60 -0
  172. data/redis/redis-2.2.11/doc/SupportedPlatforms.html +37 -0
  173. data/redis/redis-2.2.11/doc/TemplateCommand.html +38 -0
  174. data/redis/redis-2.2.11/doc/TtlCommand.html +38 -0
  175. data/redis/redis-2.2.11/doc/TwitterAlikeExample.html +250 -0
  176. data/redis/redis-2.2.11/doc/TypeCommand.html +46 -0
  177. data/redis/redis-2.2.11/doc/UnstableSource.html +39 -0
  178. data/redis/redis-2.2.11/doc/VirtualMemorySpecification.html +156 -0
  179. data/redis/redis-2.2.11/doc/VirtualMemoryUserGuide.html +66 -0
  180. data/redis/redis-2.2.11/doc/ZaddCommand.html +43 -0
  181. data/redis/redis-2.2.11/doc/ZcardCommand.html +41 -0
  182. data/redis/redis-2.2.11/doc/ZincrbyCommand.html +42 -0
  183. data/redis/redis-2.2.11/doc/ZrangeCommand.html +42 -0
  184. data/redis/redis-2.2.11/doc/ZrangebyscoreCommand.html +77 -0
  185. data/redis/redis-2.2.11/doc/ZrankCommand.html +43 -0
  186. data/redis/redis-2.2.11/doc/ZremCommand.html +42 -0
  187. data/redis/redis-2.2.11/doc/ZremrangebyrankCommand.html +39 -0
  188. data/redis/redis-2.2.11/doc/ZremrangebyscoreCommand.html +39 -0
  189. data/redis/redis-2.2.11/doc/ZscoreCommand.html +41 -0
  190. data/redis/redis-2.2.11/doc/ZunionCommand.html +42 -0
  191. data/redis/redis-2.2.11/doc/ZunionstoreCommand.html +43 -0
  192. data/redis/redis-2.2.11/doc/index.html +43 -0
  193. data/redis/redis-2.2.11/doc/redis.png +0 -0
  194. data/redis/redis-2.2.11/doc/style.css +25 -0
  195. data/redis/redis-2.2.11/redis.conf +417 -0
  196. data/redis/redis-2.2.11/src/Makefile +177 -0
  197. data/redis/redis-2.2.11/src/adlist.c +325 -0
  198. data/redis/redis-2.2.11/src/adlist.h +92 -0
  199. data/redis/redis-2.2.11/src/ae.c +390 -0
  200. data/redis/redis-2.2.11/src/ae.h +117 -0
  201. data/redis/redis-2.2.11/src/ae_epoll.c +91 -0
  202. data/redis/redis-2.2.11/src/ae_kqueue.c +93 -0
  203. data/redis/redis-2.2.11/src/ae_select.c +72 -0
  204. data/redis/redis-2.2.11/src/anet.c +347 -0
  205. data/redis/redis-2.2.11/src/anet.h +57 -0
  206. data/redis/redis-2.2.11/src/aof.c +675 -0
  207. data/redis/redis-2.2.11/src/config.c +627 -0
  208. data/redis/redis-2.2.11/src/config.h +64 -0
  209. data/redis/redis-2.2.11/src/db.c +543 -0
  210. data/redis/redis-2.2.11/src/debug.c +314 -0
  211. data/redis/redis-2.2.11/src/dict.c +721 -0
  212. data/redis/redis-2.2.11/src/dict.h +156 -0
  213. data/redis/redis-2.2.11/src/fmacros.h +15 -0
  214. data/redis/redis-2.2.11/src/help.h +638 -0
  215. data/redis/redis-2.2.11/src/intset.c +422 -0
  216. data/redis/redis-2.2.11/src/intset.h +19 -0
  217. data/redis/redis-2.2.11/src/lzf.h +100 -0
  218. data/redis/redis-2.2.11/src/lzfP.h +159 -0
  219. data/redis/redis-2.2.11/src/lzf_c.c +295 -0
  220. data/redis/redis-2.2.11/src/lzf_d.c +150 -0
  221. data/redis/redis-2.2.11/src/mkreleasehdr.sh +9 -0
  222. data/redis/redis-2.2.11/src/multi.c +268 -0
  223. data/redis/redis-2.2.11/src/networking.c +899 -0
  224. data/redis/redis-2.2.11/src/object.c +484 -0
  225. data/redis/redis-2.2.11/src/pqsort.c +197 -0
  226. data/redis/redis-2.2.11/src/pqsort.h +15 -0
  227. data/redis/redis-2.2.11/src/pubsub.c +267 -0
  228. data/redis/redis-2.2.11/src/rdb.c +1020 -0
  229. data/redis/redis-2.2.11/src/redis-benchmark.c +530 -0
  230. data/redis/redis-2.2.11/src/redis-check-aof.c +185 -0
  231. data/redis/redis-2.2.11/src/redis-check-dump.c +681 -0
  232. data/redis/redis-2.2.11/src/redis-cli.c +773 -0
  233. data/redis/redis-2.2.11/src/redis.c +1677 -0
  234. data/redis/redis-2.2.11/src/redis.h +1022 -0
  235. data/redis/redis-2.2.11/src/release.c +13 -0
  236. data/redis/redis-2.2.11/src/replication.c +557 -0
  237. data/redis/redis-2.2.11/src/sds.c +639 -0
  238. data/redis/redis-2.2.11/src/sds.h +78 -0
  239. data/redis/redis-2.2.11/src/sha1.c +276 -0
  240. data/redis/redis-2.2.11/src/sha1.h +17 -0
  241. data/redis/redis-2.2.11/src/solarisfixes.h +22 -0
  242. data/redis/redis-2.2.11/src/sort.c +389 -0
  243. data/redis/redis-2.2.11/src/syncio.c +154 -0
  244. data/redis/redis-2.2.11/src/t_hash.c +476 -0
  245. data/redis/redis-2.2.11/src/t_list.c +986 -0
  246. data/redis/redis-2.2.11/src/t_set.c +610 -0
  247. data/redis/redis-2.2.11/src/t_string.c +438 -0
  248. data/redis/redis-2.2.11/src/t_zset.c +1084 -0
  249. data/redis/redis-2.2.11/src/testhelp.h +54 -0
  250. data/redis/redis-2.2.11/src/util.c +243 -0
  251. data/redis/redis-2.2.11/src/valgrind.sup +5 -0
  252. data/redis/redis-2.2.11/src/version.h +1 -0
  253. data/redis/redis-2.2.11/src/vm.c +1149 -0
  254. data/redis/redis-2.2.11/src/ziplist.c +1323 -0
  255. data/redis/redis-2.2.11/src/ziplist.h +15 -0
  256. data/redis/redis-2.2.11/src/zipmap.c +455 -0
  257. data/redis/redis-2.2.11/src/zipmap.h +48 -0
  258. data/redis/redis-2.2.11/src/zmalloc.c +278 -0
  259. data/redis/redis-2.2.11/src/zmalloc.h +47 -0
  260. data/redis/redis-2.2.11/tests/assets/default.conf +308 -0
  261. data/redis/redis-2.2.11/tests/integration/aof.tcl +104 -0
  262. data/redis/redis-2.2.11/tests/integration/redis-cli.tcl +208 -0
  263. data/redis/redis-2.2.11/tests/integration/replication.tcl +98 -0
  264. data/redis/redis-2.2.11/tests/support/redis.tcl +241 -0
  265. data/redis/redis-2.2.11/tests/support/server.tcl +294 -0
  266. data/redis/redis-2.2.11/tests/support/test.tcl +190 -0
  267. data/redis/redis-2.2.11/tests/support/tmpfile.tcl +15 -0
  268. data/redis/redis-2.2.11/tests/support/util.tcl +296 -0
  269. data/redis/redis-2.2.11/tests/test_helper.tcl +221 -0
  270. data/redis/redis-2.2.11/tests/unit/auth.tcl +15 -0
  271. data/redis/redis-2.2.11/tests/unit/basic.tcl +616 -0
  272. data/redis/redis-2.2.11/tests/unit/cas.tcl +135 -0
  273. data/redis/redis-2.2.11/tests/unit/expire.tcl +74 -0
  274. data/redis/redis-2.2.11/tests/unit/other.tcl +240 -0
  275. data/redis/redis-2.2.11/tests/unit/printver.tcl +6 -0
  276. data/redis/redis-2.2.11/tests/unit/protocol.tcl +62 -0
  277. data/redis/redis-2.2.11/tests/unit/pubsub.tcl +195 -0
  278. data/redis/redis-2.2.11/tests/unit/quit.tcl +40 -0
  279. data/redis/redis-2.2.11/tests/unit/sort.tcl +189 -0
  280. data/redis/redis-2.2.11/tests/unit/type/hash.tcl +300 -0
  281. data/redis/redis-2.2.11/tests/unit/type/list.tcl +819 -0
  282. data/redis/redis-2.2.11/tests/unit/type/set.tcl +334 -0
  283. data/redis/redis-2.2.11/tests/unit/type/zset.tcl +587 -0
  284. data/redis/redis-2.2.11/utils/build-static-symbols.tcl +22 -0
  285. data/redis/redis-2.2.11/utils/generate-command-help.rb +112 -0
  286. data/redis/redis-2.2.11/utils/mktarball.sh +13 -0
  287. data/redis/redis-2.2.11/utils/redis-copy.rb +78 -0
  288. data/redis/redis-2.2.11/utils/redis-sha1.rb +52 -0
  289. data/redis/redis-2.2.11/utils/redis_init_script +42 -0
  290. metadata +362 -0
@@ -0,0 +1,170 @@
1
+ /*
2
+ * Copyright (c) 2009-2010, Salvatore Sanfilippo <antirez at gmail dot com>
3
+ * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
4
+ *
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ * * Neither the name of Redis nor the names of its contributors may be used
16
+ * to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ * POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+ #ifndef __HIREDIS_H
33
+ #define __HIREDIS_H
34
+ #include <stdio.h> /* for size_t */
35
+ #include <stdarg.h> /* for va_list */
36
+
37
+ #define HIREDIS_MAJOR 0
38
+ #define HIREDIS_MINOR 9
39
+ #define HIREDIS_PATCH 2
40
+
41
+ #define REDIS_ERR -1
42
+ #define REDIS_OK 0
43
+
44
+ /* When an error occurs, the err flag in a context is set to hold the type of
45
+ * error that occured. REDIS_ERR_IO means there was an I/O error and you
46
+ * should use the "errno" variable to find out what is wrong.
47
+ * For other values, the "errstr" field will hold a description. */
48
+ #define REDIS_ERR_IO 1 /* error in read or write */
49
+ #define REDIS_ERR_EOF 3 /* eof */
50
+ #define REDIS_ERR_PROTOCOL 4 /* protocol error */
51
+ #define REDIS_ERR_OTHER 2 /* something else */
52
+
53
+ /* Connection type can be blocking or non-blocking and is set in the
54
+ * least significant bit of the flags field in redisContext. */
55
+ #define REDIS_BLOCK 0x1
56
+
57
+ /* Connection may be disconnected before being free'd. The second bit
58
+ * in the flags field is set when the context is connected. */
59
+ #define REDIS_CONNECTED 0x2
60
+
61
+ /* The async API might try to disconnect cleanly and flush the output
62
+ * buffer and read all subsequent replies before disconnecting.
63
+ * This flag means no new commands can come in and the connection
64
+ * should be terminated once all replies have been read. */
65
+ #define REDIS_DISCONNECTING 0x4
66
+
67
+ #define REDIS_REPLY_STRING 1
68
+ #define REDIS_REPLY_ARRAY 2
69
+ #define REDIS_REPLY_INTEGER 3
70
+ #define REDIS_REPLY_NIL 4
71
+ #define REDIS_REPLY_STATUS 5
72
+ #define REDIS_REPLY_ERROR 6
73
+
74
+ #ifdef __cplusplus
75
+ extern "C" {
76
+ #endif
77
+
78
+ /* This is the reply object returned by redisCommand() */
79
+ typedef struct redisReply {
80
+ int type; /* REDIS_REPLY_* */
81
+ long long integer; /* The integer when type is REDIS_REPLY_INTEGER */
82
+ int len; /* Length of string */
83
+ char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */
84
+ size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */
85
+ struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */
86
+ } redisReply;
87
+
88
+ typedef struct redisReadTask {
89
+ int type;
90
+ int elements; /* number of elements in multibulk container */
91
+ int idx; /* index in parent (array) object */
92
+ void *obj; /* holds user-generated value for a read task */
93
+ struct redisReadTask *parent; /* parent task */
94
+ void *privdata; /* user-settable arbitrary field */
95
+ } redisReadTask;
96
+
97
+ typedef struct redisReplyObjectFunctions {
98
+ void *(*createString)(const redisReadTask*, char*, size_t);
99
+ void *(*createArray)(const redisReadTask*, int);
100
+ void *(*createInteger)(const redisReadTask*, long long);
101
+ void *(*createNil)(const redisReadTask*);
102
+ void (*freeObject)(void*);
103
+ } redisReplyObjectFunctions;
104
+
105
+ struct redisContext; /* need forward declaration of redisContext */
106
+
107
+ /* Context for a connection to Redis */
108
+ typedef struct redisContext {
109
+ int fd;
110
+ int flags;
111
+ char *obuf; /* Write buffer */
112
+ int err; /* Error flags, 0 when there is no error */
113
+ char *errstr; /* String representation of error when applicable */
114
+
115
+ /* Function set for reply buildup and reply reader */
116
+ redisReplyObjectFunctions *fn;
117
+ void *reader;
118
+ } redisContext;
119
+
120
+ void freeReplyObject(void *reply);
121
+ void *redisReplyReaderCreate();
122
+ int redisReplyReaderSetReplyObjectFunctions(void *reader, redisReplyObjectFunctions *fn);
123
+ int redisReplyReaderSetPrivdata(void *reader, void *privdata);
124
+ void *redisReplyReaderGetObject(void *reader);
125
+ char *redisReplyReaderGetError(void *reader);
126
+ void redisReplyReaderFree(void *ptr);
127
+ void redisReplyReaderFeed(void *reader, char *buf, size_t len);
128
+ int redisReplyReaderGetReply(void *reader, void **reply);
129
+
130
+ /* Functions to format a command according to the protocol. */
131
+ int redisvFormatCommand(char **target, const char *format, va_list ap);
132
+ int redisFormatCommand(char **target, const char *format, ...);
133
+ int redisFormatCommandArgv(char **target, int argc, const char **argv, const size_t *argvlen);
134
+
135
+ redisContext *redisConnect(const char *ip, int port);
136
+ redisContext *redisConnectNonBlock(const char *ip, int port);
137
+ redisContext *redisConnectUnix(const char *path);
138
+ redisContext *redisConnectUnixNonBlock(const char *path);
139
+ int redisSetReplyObjectFunctions(redisContext *c, redisReplyObjectFunctions *fn);
140
+ void redisFree(redisContext *c);
141
+ int redisBufferRead(redisContext *c);
142
+ int redisBufferWrite(redisContext *c, int *done);
143
+
144
+ /* In a blocking context, this function first checks if there are unconsumed
145
+ * replies to return and returns one if so. Otherwise, it flushes the output
146
+ * buffer to the socket and reads until it has a reply. In a non-blocking
147
+ * context, it will return unconsumed replies until there are no more. */
148
+ int redisGetReply(redisContext *c, void **reply);
149
+ int redisGetReplyFromReader(redisContext *c, void **reply);
150
+
151
+ /* Write a command to the output buffer. Use these functions in blocking mode
152
+ * to get a pipeline of commands. */
153
+ void redisvAppendCommand(redisContext *c, const char *format, va_list ap);
154
+ void redisAppendCommand(redisContext *c, const char *format, ...);
155
+ void redisAppendCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
156
+
157
+ /* Issue a command to Redis. In a blocking context, it is identical to calling
158
+ * redisAppendCommand, followed by redisGetReply. The function will return
159
+ * NULL if there was an error in performing the request, otherwise it will
160
+ * return the reply. In a non-blocking context, it is identical to calling
161
+ * only redisAppendCommand and will always return NULL. */
162
+ void *redisvCommand(redisContext *c, const char *format, va_list ap);
163
+ void *redisCommand(redisContext *c, const char *format, ...);
164
+ void *redisCommandArgv(redisContext *c, int argc, const char **argv, const size_t *argvlen);
165
+
166
+ #ifdef __cplusplus
167
+ }
168
+ #endif
169
+
170
+ #endif
@@ -0,0 +1,170 @@
1
+ /* Extracted from anet.c to work properly with Hiredis error reporting.
2
+ *
3
+ * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
4
+ * Copyright (c) 2010, Pieter Noordhuis <pcnoordhuis at gmail dot com>
5
+ *
6
+ * All rights reserved.
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * * Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ * notice, this list of conditions and the following disclaimer in the
14
+ * documentation and/or other materials provided with the distribution.
15
+ * * Neither the name of Redis nor the names of its contributors may be used
16
+ * to endorse or promote products derived from this software without
17
+ * specific prior written permission.
18
+ *
19
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
+ * POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+ #include "fmacros.h"
33
+ #include <sys/types.h>
34
+ #include <sys/socket.h>
35
+ #include <sys/un.h>
36
+ #include <netinet/in.h>
37
+ #include <netinet/tcp.h>
38
+ #include <arpa/inet.h>
39
+ #include <unistd.h>
40
+ #include <fcntl.h>
41
+ #include <string.h>
42
+ #include <netdb.h>
43
+ #include <errno.h>
44
+ #include <stdarg.h>
45
+ #include <stdio.h>
46
+
47
+ #include "net.h"
48
+ #include "sds.h"
49
+
50
+ /* Forward declaration */
51
+ void __redisSetError(redisContext *c, int type, sds err);
52
+
53
+ static int redisCreateSocket(redisContext *c, int type) {
54
+ int s, on = 1;
55
+ if ((s = socket(type, SOCK_STREAM, 0)) == -1) {
56
+ __redisSetError(c,REDIS_ERR_IO,NULL);
57
+ return REDIS_ERR;
58
+ }
59
+ if (type == AF_INET) {
60
+ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
61
+ __redisSetError(c,REDIS_ERR_IO,NULL);
62
+ close(s);
63
+ return REDIS_ERR;
64
+ }
65
+ }
66
+ return s;
67
+ }
68
+
69
+ static int redisSetNonBlock(redisContext *c, int fd) {
70
+ int flags;
71
+
72
+ /* Set the socket nonblocking.
73
+ * Note that fcntl(2) for F_GETFL and F_SETFL can't be
74
+ * interrupted by a signal. */
75
+ if ((flags = fcntl(fd, F_GETFL)) == -1) {
76
+ __redisSetError(c,REDIS_ERR_IO,
77
+ sdscatprintf(sdsempty(), "fcntl(F_GETFL): %s", strerror(errno)));
78
+ close(fd);
79
+ return REDIS_ERR;
80
+ }
81
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) {
82
+ __redisSetError(c,REDIS_ERR_IO,
83
+ sdscatprintf(sdsempty(), "fcntl(F_SETFL,O_NONBLOCK): %s", strerror(errno)));
84
+ close(fd);
85
+ return REDIS_ERR;
86
+ }
87
+ return REDIS_OK;
88
+ }
89
+
90
+ static int redisSetTcpNoDelay(redisContext *c, int fd) {
91
+ int yes = 1;
92
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof(yes)) == -1) {
93
+ __redisSetError(c,REDIS_ERR_IO,
94
+ sdscatprintf(sdsempty(), "setsockopt(TCP_NODELAY): %s", strerror(errno)));
95
+ return REDIS_ERR;
96
+ }
97
+ return REDIS_OK;
98
+ }
99
+
100
+ int redisContextConnectTcp(redisContext *c, const char *addr, int port) {
101
+ int s;
102
+ int blocking = (c->flags & REDIS_BLOCK);
103
+ struct sockaddr_in sa;
104
+
105
+ if ((s = redisCreateSocket(c,AF_INET)) == REDIS_ERR)
106
+ return REDIS_ERR;
107
+ if (!blocking && redisSetNonBlock(c,s) == REDIS_ERR)
108
+ return REDIS_ERR;
109
+
110
+ sa.sin_family = AF_INET;
111
+ sa.sin_port = htons(port);
112
+ if (inet_aton(addr, &sa.sin_addr) == 0) {
113
+ struct hostent *he;
114
+
115
+ he = gethostbyname(addr);
116
+ if (he == NULL) {
117
+ __redisSetError(c,REDIS_ERR_OTHER,
118
+ sdscatprintf(sdsempty(),"Can't resolve: %s",addr));
119
+ close(s);
120
+ return REDIS_ERR;
121
+ }
122
+ memcpy(&sa.sin_addr, he->h_addr, sizeof(struct in_addr));
123
+ }
124
+
125
+ if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
126
+ if (errno == EINPROGRESS && !blocking) {
127
+ /* This is ok. */
128
+ } else {
129
+ __redisSetError(c,REDIS_ERR_IO,NULL);
130
+ close(s);
131
+ return REDIS_ERR;
132
+ }
133
+ }
134
+
135
+ if (redisSetTcpNoDelay(c,s) != REDIS_OK) {
136
+ close(s);
137
+ return REDIS_ERR;
138
+ }
139
+
140
+ c->fd = s;
141
+ c->flags |= REDIS_CONNECTED;
142
+ return REDIS_OK;
143
+ }
144
+
145
+ int redisContextConnectUnix(redisContext *c, const char *path) {
146
+ int s;
147
+ int blocking = (c->flags & REDIS_BLOCK);
148
+ struct sockaddr_un sa;
149
+
150
+ if ((s = redisCreateSocket(c,AF_LOCAL)) == REDIS_ERR)
151
+ return REDIS_ERR;
152
+ if (!blocking && redisSetNonBlock(c,s) != REDIS_OK)
153
+ return REDIS_ERR;
154
+
155
+ sa.sun_family = AF_LOCAL;
156
+ strncpy(sa.sun_path,path,sizeof(sa.sun_path)-1);
157
+ if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1) {
158
+ if (errno == EINPROGRESS && !blocking) {
159
+ /* This is ok. */
160
+ } else {
161
+ __redisSetError(c,REDIS_ERR_IO,NULL);
162
+ close(s);
163
+ return REDIS_ERR;
164
+ }
165
+ }
166
+
167
+ c->fd = s;
168
+ c->flags |= REDIS_CONNECTED;
169
+ return REDIS_OK;
170
+ }
@@ -0,0 +1,43 @@
1
+ /* Extracted from anet.c to work properly with Hiredis error reporting.
2
+ *
3
+ * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of Redis nor the names of its contributors may be used
15
+ * to endorse or promote products derived from this software without
16
+ * specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ * POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #ifndef __NET_H
32
+ #define __NET_H
33
+
34
+ #include "hiredis.h"
35
+
36
+ #if defined(__sun)
37
+ #define AF_LOCAL AF_UNIX
38
+ #endif
39
+
40
+ int redisContextConnectTcp(redisContext *c, const char *addr, int port);
41
+ int redisContextConnectUnix(redisContext *c, const char *path);
42
+
43
+ #endif
@@ -0,0 +1,479 @@
1
+ /* SDSLib, A C dynamic strings library
2
+ *
3
+ * Copyright (c) 2006-2010, Salvatore Sanfilippo <antirez at gmail dot com>
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice,
10
+ * this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of Redis nor the names of its contributors may be used
15
+ * to endorse or promote products derived from this software without
16
+ * specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ * POSSIBILITY OF SUCH DAMAGE.
29
+ */
30
+
31
+ #define SDS_ABORT_ON_OOM
32
+
33
+ #include "sds.h"
34
+ #include <stdio.h>
35
+ #include <stdlib.h>
36
+ #include <string.h>
37
+ #include <ctype.h>
38
+
39
+ static void sdsOomAbort(void) {
40
+ fprintf(stderr,"SDS: Out Of Memory (SDS_ABORT_ON_OOM defined)\n");
41
+ abort();
42
+ }
43
+
44
+ sds sdsnewlen(const void *init, size_t initlen) {
45
+ struct sdshdr *sh;
46
+
47
+ sh = malloc(sizeof(struct sdshdr)+initlen+1);
48
+ #ifdef SDS_ABORT_ON_OOM
49
+ if (sh == NULL) sdsOomAbort();
50
+ #else
51
+ if (sh == NULL) return NULL;
52
+ #endif
53
+ sh->len = initlen;
54
+ sh->free = 0;
55
+ if (initlen) {
56
+ if (init) memcpy(sh->buf, init, initlen);
57
+ else memset(sh->buf,0,initlen);
58
+ }
59
+ sh->buf[initlen] = '\0';
60
+ return (char*)sh->buf;
61
+ }
62
+
63
+ sds sdsempty(void) {
64
+ return sdsnewlen("",0);
65
+ }
66
+
67
+ sds sdsnew(const char *init) {
68
+ size_t initlen = (init == NULL) ? 0 : strlen(init);
69
+ return sdsnewlen(init, initlen);
70
+ }
71
+
72
+ size_t sdslen(const sds s) {
73
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
74
+ return sh->len;
75
+ }
76
+
77
+ sds sdsdup(const sds s) {
78
+ return sdsnewlen(s, sdslen(s));
79
+ }
80
+
81
+ void sdsfree(sds s) {
82
+ if (s == NULL) return;
83
+ free(s-sizeof(struct sdshdr));
84
+ }
85
+
86
+ size_t sdsavail(sds s) {
87
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
88
+ return sh->free;
89
+ }
90
+
91
+ void sdsupdatelen(sds s) {
92
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
93
+ int reallen = strlen(s);
94
+ sh->free += (sh->len-reallen);
95
+ sh->len = reallen;
96
+ }
97
+
98
+ static sds sdsMakeRoomFor(sds s, size_t addlen) {
99
+ struct sdshdr *sh, *newsh;
100
+ size_t free = sdsavail(s);
101
+ size_t len, newlen;
102
+
103
+ if (free >= addlen) return s;
104
+ len = sdslen(s);
105
+ sh = (void*) (s-(sizeof(struct sdshdr)));
106
+ newlen = (len+addlen)*2;
107
+ newsh = realloc(sh, sizeof(struct sdshdr)+newlen+1);
108
+ #ifdef SDS_ABORT_ON_OOM
109
+ if (newsh == NULL) sdsOomAbort();
110
+ #else
111
+ if (newsh == NULL) return NULL;
112
+ #endif
113
+
114
+ newsh->free = newlen - len;
115
+ return newsh->buf;
116
+ }
117
+
118
+ sds sdscatlen(sds s, const void *t, size_t len) {
119
+ struct sdshdr *sh;
120
+ size_t curlen = sdslen(s);
121
+
122
+ s = sdsMakeRoomFor(s,len);
123
+ if (s == NULL) return NULL;
124
+ sh = (void*) (s-(sizeof(struct sdshdr)));
125
+ memcpy(s+curlen, t, len);
126
+ sh->len = curlen+len;
127
+ sh->free = sh->free-len;
128
+ s[curlen+len] = '\0';
129
+ return s;
130
+ }
131
+
132
+ sds sdscat(sds s, const char *t) {
133
+ return sdscatlen(s, t, strlen(t));
134
+ }
135
+
136
+ sds sdscpylen(sds s, char *t, size_t len) {
137
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
138
+ size_t totlen = sh->free+sh->len;
139
+
140
+ if (totlen < len) {
141
+ s = sdsMakeRoomFor(s,len-sh->len);
142
+ if (s == NULL) return NULL;
143
+ sh = (void*) (s-(sizeof(struct sdshdr)));
144
+ totlen = sh->free+sh->len;
145
+ }
146
+ memcpy(s, t, len);
147
+ s[len] = '\0';
148
+ sh->len = len;
149
+ sh->free = totlen-len;
150
+ return s;
151
+ }
152
+
153
+ sds sdscpy(sds s, char *t) {
154
+ return sdscpylen(s, t, strlen(t));
155
+ }
156
+
157
+ sds sdscatvprintf(sds s, const char *fmt, va_list ap) {
158
+ va_list cpy;
159
+ char *buf, *t;
160
+ size_t buflen = 16;
161
+
162
+ while(1) {
163
+ buf = malloc(buflen);
164
+ #ifdef SDS_ABORT_ON_OOM
165
+ if (buf == NULL) sdsOomAbort();
166
+ #else
167
+ if (buf == NULL) return NULL;
168
+ #endif
169
+ buf[buflen-2] = '\0';
170
+ va_copy(cpy,ap);
171
+ vsnprintf(buf, buflen, fmt, cpy);
172
+ if (buf[buflen-2] != '\0') {
173
+ free(buf);
174
+ buflen *= 2;
175
+ continue;
176
+ }
177
+ break;
178
+ }
179
+ t = sdscat(s, buf);
180
+ free(buf);
181
+ return t;
182
+ }
183
+
184
+ sds sdscatprintf(sds s, const char *fmt, ...) {
185
+ va_list ap;
186
+ char *t;
187
+ va_start(ap, fmt);
188
+ t = sdscatvprintf(s,fmt,ap);
189
+ va_end(ap);
190
+ return t;
191
+ }
192
+
193
+ sds sdstrim(sds s, const char *cset) {
194
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
195
+ char *start, *end, *sp, *ep;
196
+ size_t len;
197
+
198
+ sp = start = s;
199
+ ep = end = s+sdslen(s)-1;
200
+ while(sp <= end && strchr(cset, *sp)) sp++;
201
+ while(ep > start && strchr(cset, *ep)) ep--;
202
+ len = (sp > ep) ? 0 : ((ep-sp)+1);
203
+ if (sh->buf != sp) memmove(sh->buf, sp, len);
204
+ sh->buf[len] = '\0';
205
+ sh->free = sh->free+(sh->len-len);
206
+ sh->len = len;
207
+ return s;
208
+ }
209
+
210
+ sds sdsrange(sds s, int start, int end) {
211
+ struct sdshdr *sh = (void*) (s-(sizeof(struct sdshdr)));
212
+ size_t newlen, len = sdslen(s);
213
+
214
+ if (len == 0) return s;
215
+ if (start < 0) {
216
+ start = len+start;
217
+ if (start < 0) start = 0;
218
+ }
219
+ if (end < 0) {
220
+ end = len+end;
221
+ if (end < 0) end = 0;
222
+ }
223
+ newlen = (start > end) ? 0 : (end-start)+1;
224
+ if (newlen != 0) {
225
+ if (start >= (signed)len) start = len-1;
226
+ if (end >= (signed)len) end = len-1;
227
+ newlen = (start > end) ? 0 : (end-start)+1;
228
+ } else {
229
+ start = 0;
230
+ }
231
+ if (start != 0) memmove(sh->buf, sh->buf+start, newlen);
232
+ sh->buf[newlen] = 0;
233
+ sh->free = sh->free+(sh->len-newlen);
234
+ sh->len = newlen;
235
+ return s;
236
+ }
237
+
238
+ void sdstolower(sds s) {
239
+ int len = sdslen(s), j;
240
+
241
+ for (j = 0; j < len; j++) s[j] = tolower(s[j]);
242
+ }
243
+
244
+ void sdstoupper(sds s) {
245
+ int len = sdslen(s), j;
246
+
247
+ for (j = 0; j < len; j++) s[j] = toupper(s[j]);
248
+ }
249
+
250
+ int sdscmp(sds s1, sds s2) {
251
+ size_t l1, l2, minlen;
252
+ int cmp;
253
+
254
+ l1 = sdslen(s1);
255
+ l2 = sdslen(s2);
256
+ minlen = (l1 < l2) ? l1 : l2;
257
+ cmp = memcmp(s1,s2,minlen);
258
+ if (cmp == 0) return l1-l2;
259
+ return cmp;
260
+ }
261
+
262
+ /* Split 's' with separator in 'sep'. An array
263
+ * of sds strings is returned. *count will be set
264
+ * by reference to the number of tokens returned.
265
+ *
266
+ * On out of memory, zero length string, zero length
267
+ * separator, NULL is returned.
268
+ *
269
+ * Note that 'sep' is able to split a string using
270
+ * a multi-character separator. For example
271
+ * sdssplit("foo_-_bar","_-_"); will return two
272
+ * elements "foo" and "bar".
273
+ *
274
+ * This version of the function is binary-safe but
275
+ * requires length arguments. sdssplit() is just the
276
+ * same function but for zero-terminated strings.
277
+ */
278
+ sds *sdssplitlen(char *s, int len, char *sep, int seplen, int *count) {
279
+ int elements = 0, slots = 5, start = 0, j;
280
+
281
+ sds *tokens = malloc(sizeof(sds)*slots);
282
+ #ifdef SDS_ABORT_ON_OOM
283
+ if (tokens == NULL) sdsOomAbort();
284
+ #endif
285
+ if (seplen < 1 || len < 0 || tokens == NULL) return NULL;
286
+ if (len == 0) {
287
+ *count = 0;
288
+ return tokens;
289
+ }
290
+ for (j = 0; j < (len-(seplen-1)); j++) {
291
+ /* make sure there is room for the next element and the final one */
292
+ if (slots < elements+2) {
293
+ sds *newtokens;
294
+
295
+ slots *= 2;
296
+ newtokens = realloc(tokens,sizeof(sds)*slots);
297
+ if (newtokens == NULL) {
298
+ #ifdef SDS_ABORT_ON_OOM
299
+ sdsOomAbort();
300
+ #else
301
+ goto cleanup;
302
+ #endif
303
+ }
304
+ tokens = newtokens;
305
+ }
306
+ /* search the separator */
307
+ if ((seplen == 1 && *(s+j) == sep[0]) || (memcmp(s+j,sep,seplen) == 0)) {
308
+ tokens[elements] = sdsnewlen(s+start,j-start);
309
+ if (tokens[elements] == NULL) {
310
+ #ifdef SDS_ABORT_ON_OOM
311
+ sdsOomAbort();
312
+ #else
313
+ goto cleanup;
314
+ #endif
315
+ }
316
+ elements++;
317
+ start = j+seplen;
318
+ j = j+seplen-1; /* skip the separator */
319
+ }
320
+ }
321
+ /* Add the final element. We are sure there is room in the tokens array. */
322
+ tokens[elements] = sdsnewlen(s+start,len-start);
323
+ if (tokens[elements] == NULL) {
324
+ #ifdef SDS_ABORT_ON_OOM
325
+ sdsOomAbort();
326
+ #else
327
+ goto cleanup;
328
+ #endif
329
+ }
330
+ elements++;
331
+ *count = elements;
332
+ return tokens;
333
+
334
+ #ifndef SDS_ABORT_ON_OOM
335
+ cleanup:
336
+ {
337
+ int i;
338
+ for (i = 0; i < elements; i++) sdsfree(tokens[i]);
339
+ free(tokens);
340
+ return NULL;
341
+ }
342
+ #endif
343
+ }
344
+
345
+ void sdsfreesplitres(sds *tokens, int count) {
346
+ if (!tokens) return;
347
+ while(count--)
348
+ sdsfree(tokens[count]);
349
+ free(tokens);
350
+ }
351
+
352
+ sds sdsfromlonglong(long long value) {
353
+ char buf[32], *p;
354
+ unsigned long long v;
355
+
356
+ v = (value < 0) ? -value : value;
357
+ p = buf+31; /* point to the last character */
358
+ do {
359
+ *p-- = '0'+(v%10);
360
+ v /= 10;
361
+ } while(v);
362
+ if (value < 0) *p-- = '-';
363
+ p++;
364
+ return sdsnewlen(p,32-(p-buf));
365
+ }
366
+
367
+ sds sdscatrepr(sds s, char *p, size_t len) {
368
+ s = sdscatlen(s,"\"",1);
369
+ while(len--) {
370
+ switch(*p) {
371
+ case '\\':
372
+ case '"':
373
+ s = sdscatprintf(s,"\\%c",*p);
374
+ break;
375
+ case '\n': s = sdscatlen(s,"\\n",1); break;
376
+ case '\r': s = sdscatlen(s,"\\r",1); break;
377
+ case '\t': s = sdscatlen(s,"\\t",1); break;
378
+ case '\a': s = sdscatlen(s,"\\a",1); break;
379
+ case '\b': s = sdscatlen(s,"\\b",1); break;
380
+ default:
381
+ if (isprint(*p))
382
+ s = sdscatprintf(s,"%c",*p);
383
+ else
384
+ s = sdscatprintf(s,"\\x%02x",(unsigned char)*p);
385
+ break;
386
+ }
387
+ p++;
388
+ }
389
+ return sdscatlen(s,"\"",1);
390
+ }
391
+
392
+ /* Split a line into arguments, where every argument can be in the
393
+ * following programming-language REPL-alike form:
394
+ *
395
+ * foo bar "newline are supported\n" and "\xff\x00otherstuff"
396
+ *
397
+ * The number of arguments is stored into *argc, and an array
398
+ * of sds is returned. The caller should sdsfree() all the returned
399
+ * strings and finally free() the array itself.
400
+ *
401
+ * Note that sdscatrepr() is able to convert back a string into
402
+ * a quoted string in the same format sdssplitargs() is able to parse.
403
+ */
404
+ sds *sdssplitargs(char *line, int *argc) {
405
+ char *p = line;
406
+ char *current = NULL;
407
+ char **vector = NULL;
408
+
409
+ *argc = 0;
410
+ while(1) {
411
+ /* skip blanks */
412
+ while(*p && isspace(*p)) p++;
413
+ if (*p) {
414
+ /* get a token */
415
+ int inq=0; /* set to 1 if we are in "quotes" */
416
+ int done=0;
417
+
418
+ if (current == NULL) current = sdsempty();
419
+ while(!done) {
420
+ if (inq) {
421
+ if (*p == '\\' && *(p+1)) {
422
+ char c;
423
+
424
+ p++;
425
+ switch(*p) {
426
+ case 'n': c = '\n'; break;
427
+ case 'r': c = '\r'; break;
428
+ case 't': c = '\t'; break;
429
+ case 'b': c = '\b'; break;
430
+ case 'a': c = '\a'; break;
431
+ default: c = *p; break;
432
+ }
433
+ current = sdscatlen(current,&c,1);
434
+ } else if (*p == '"') {
435
+ /* closing quote must be followed by a space */
436
+ if (*(p+1) && !isspace(*(p+1))) goto err;
437
+ done=1;
438
+ } else if (!*p) {
439
+ /* unterminated quotes */
440
+ goto err;
441
+ } else {
442
+ current = sdscatlen(current,p,1);
443
+ }
444
+ } else {
445
+ switch(*p) {
446
+ case ' ':
447
+ case '\n':
448
+ case '\r':
449
+ case '\t':
450
+ case '\0':
451
+ done=1;
452
+ break;
453
+ case '"':
454
+ inq=1;
455
+ break;
456
+ default:
457
+ current = sdscatlen(current,p,1);
458
+ break;
459
+ }
460
+ }
461
+ if (*p) p++;
462
+ }
463
+ /* add the token to the vector */
464
+ vector = realloc(vector,((*argc)+1)*sizeof(char*));
465
+ vector[*argc] = current;
466
+ (*argc)++;
467
+ current = NULL;
468
+ } else {
469
+ return vector;
470
+ }
471
+ }
472
+
473
+ err:
474
+ while((*argc)--)
475
+ sdsfree(vector[*argc]);
476
+ free(vector);
477
+ if (current) sdsfree(current);
478
+ return NULL;
479
+ }