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.
- data/LICENSE +38 -0
- data/README.md +33 -0
- data/bin/redis +114 -0
- data/redis/Makefile +5 -0
- data/redis/extconf.rb +3 -0
- data/redis/redis-2.2.11/00-RELEASENOTES +199 -0
- data/redis/redis-2.2.11/BUGS +1 -0
- data/redis/redis-2.2.11/CONTRIBUTING +13 -0
- data/redis/redis-2.2.11/COPYING +10 -0
- data/redis/redis-2.2.11/Changelog +1032 -0
- data/redis/redis-2.2.11/INSTALL +30 -0
- data/redis/redis-2.2.11/Makefile +22 -0
- data/redis/redis-2.2.11/README +83 -0
- data/redis/redis-2.2.11/TODO +4 -0
- data/redis/redis-2.2.11/client-libraries/README +11 -0
- data/redis/redis-2.2.11/deps/hiredis/COPYING +10 -0
- data/redis/redis-2.2.11/deps/hiredis/Makefile +115 -0
- data/redis/redis-2.2.11/deps/hiredis/README.md +311 -0
- data/redis/redis-2.2.11/deps/hiredis/TODO +2 -0
- data/redis/redis-2.2.11/deps/hiredis/adapters/ae.h +95 -0
- data/redis/redis-2.2.11/deps/hiredis/adapters/libev.h +113 -0
- data/redis/redis-2.2.11/deps/hiredis/adapters/libevent.h +76 -0
- data/redis/redis-2.2.11/deps/hiredis/async.c +321 -0
- data/redis/redis-2.2.11/deps/hiredis/async.h +112 -0
- data/redis/redis-2.2.11/deps/hiredis/example-ae.c +53 -0
- data/redis/redis-2.2.11/deps/hiredis/example-libev.c +47 -0
- data/redis/redis-2.2.11/deps/hiredis/example-libevent.c +48 -0
- data/redis/redis-2.2.11/deps/hiredis/example.c +67 -0
- data/redis/redis-2.2.11/deps/hiredis/fmacros.h +15 -0
- data/redis/redis-2.2.11/deps/hiredis/hiredis.c +1058 -0
- data/redis/redis-2.2.11/deps/hiredis/hiredis.h +170 -0
- data/redis/redis-2.2.11/deps/hiredis/net.c +170 -0
- data/redis/redis-2.2.11/deps/hiredis/net.h +43 -0
- data/redis/redis-2.2.11/deps/hiredis/sds.c +479 -0
- data/redis/redis-2.2.11/deps/hiredis/sds.h +77 -0
- data/redis/redis-2.2.11/deps/hiredis/test.c +479 -0
- data/redis/redis-2.2.11/deps/hiredis/util.h +40 -0
- data/redis/redis-2.2.11/deps/linenoise/Makefile +10 -0
- data/redis/redis-2.2.11/deps/linenoise/README.markdown +45 -0
- data/redis/redis-2.2.11/deps/linenoise/example.c +27 -0
- data/redis/redis-2.2.11/deps/linenoise/linenoise.c +609 -0
- data/redis/redis-2.2.11/deps/linenoise/linenoise.h +55 -0
- data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER +214 -0
- data/redis/redis-2.2.11/design-documents/REDIS-CLUSTER-2 +343 -0
- data/redis/redis-2.2.11/doc/AppendCommand.html +48 -0
- data/redis/redis-2.2.11/doc/AppendOnlyFileHowto.html +41 -0
- data/redis/redis-2.2.11/doc/AuthCommand.html +39 -0
- data/redis/redis-2.2.11/doc/Benchmarks.html +129 -0
- data/redis/redis-2.2.11/doc/BgrewriteaofCommand.html +41 -0
- data/redis/redis-2.2.11/doc/BgsaveCommand.html +39 -0
- data/redis/redis-2.2.11/doc/BlpopCommand.html +51 -0
- data/redis/redis-2.2.11/doc/BrpoplpushCommand.html +39 -0
- data/redis/redis-2.2.11/doc/CommandReference.html +47 -0
- data/redis/redis-2.2.11/doc/Comparisons.html +42 -0
- data/redis/redis-2.2.11/doc/ConfigCommand.html +76 -0
- data/redis/redis-2.2.11/doc/Configuration.html +38 -0
- data/redis/redis-2.2.11/doc/ConnectionHandlingSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/ControlCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Credits.html +38 -0
- data/redis/redis-2.2.11/doc/DbsizeCommand.html +38 -0
- data/redis/redis-2.2.11/doc/DelCommand.html +41 -0
- data/redis/redis-2.2.11/doc/DesignPatterns.html +37 -0
- data/redis/redis-2.2.11/doc/EventLibray.html +44 -0
- data/redis/redis-2.2.11/doc/ExistsCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ExpireCommand.html +96 -0
- data/redis/redis-2.2.11/doc/FAQ.html +70 -0
- data/redis/redis-2.2.11/doc/Features.html +38 -0
- data/redis/redis-2.2.11/doc/FlushallCommand.html +39 -0
- data/redis/redis-2.2.11/doc/FlushdbCommand.html +39 -0
- data/redis/redis-2.2.11/doc/FromSqlToDataStructures.html +37 -0
- data/redis/redis-2.2.11/doc/GenericCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/GetCommand.html +39 -0
- data/redis/redis-2.2.11/doc/GetbitCommand.html +39 -0
- data/redis/redis-2.2.11/doc/GetsetCommand.html +38 -0
- data/redis/redis-2.2.11/doc/HackingStrings.html +83 -0
- data/redis/redis-2.2.11/doc/HashCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Hashes.html +37 -0
- data/redis/redis-2.2.11/doc/HdelCommand.html +39 -0
- data/redis/redis-2.2.11/doc/HexistsCommand.html +39 -0
- data/redis/redis-2.2.11/doc/HgetCommand.html +39 -0
- data/redis/redis-2.2.11/doc/HgetallCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HincrbyCommand.html +45 -0
- data/redis/redis-2.2.11/doc/HlenCommand.html +38 -0
- data/redis/redis-2.2.11/doc/HmgetCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HmsetCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HsetCommand.html +40 -0
- data/redis/redis-2.2.11/doc/HsetnxCommand.html +41 -0
- data/redis/redis-2.2.11/doc/IncrCommand.html +43 -0
- data/redis/redis-2.2.11/doc/InfoCommand.html +48 -0
- data/redis/redis-2.2.11/doc/IntroductionToRedisDataTypes.html +152 -0
- data/redis/redis-2.2.11/doc/KeysCommand.html +43 -0
- data/redis/redis-2.2.11/doc/LastsaveCommand.html +39 -0
- data/redis/redis-2.2.11/doc/LindexCommand.html +40 -0
- data/redis/redis-2.2.11/doc/ListCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Lists.html +42 -0
- data/redis/redis-2.2.11/doc/LlenCommand.html +41 -0
- data/redis/redis-2.2.11/doc/LpopCommand.html +41 -0
- data/redis/redis-2.2.11/doc/LrangeCommand.html +47 -0
- data/redis/redis-2.2.11/doc/LremCommand.html +41 -0
- data/redis/redis-2.2.11/doc/LsetCommand.html +38 -0
- data/redis/redis-2.2.11/doc/LtrimCommand.html +47 -0
- data/redis/redis-2.2.11/doc/MgetCommand.html +52 -0
- data/redis/redis-2.2.11/doc/MonitorCommand.html +63 -0
- data/redis/redis-2.2.11/doc/MoveCommand.html +42 -0
- data/redis/redis-2.2.11/doc/MsetCommand.html +44 -0
- data/redis/redis-2.2.11/doc/MultiExecCommand.html +166 -0
- data/redis/redis-2.2.11/doc/NonexistentCommands.html +51 -0
- data/redis/redis-2.2.11/doc/ObjectHashMappers.html +39 -0
- data/redis/redis-2.2.11/doc/Pipelining.html +36 -0
- data/redis/redis-2.2.11/doc/ProgrammingExamples.html +38 -0
- data/redis/redis-2.2.11/doc/ProtocolSpecification.html +137 -0
- data/redis/redis-2.2.11/doc/PublishSubscribe.html +115 -0
- data/redis/redis-2.2.11/doc/QuickStart.html +68 -0
- data/redis/redis-2.2.11/doc/QuitCommand.html +38 -0
- data/redis/redis-2.2.11/doc/README.html +119 -0
- data/redis/redis-2.2.11/doc/RandomkeyCommand.html +39 -0
- data/redis/redis-2.2.11/doc/Redis0100ChangeLog.html +67 -0
- data/redis/redis-2.2.11/doc/Redis0900ChangeLog.html +56 -0
- data/redis/redis-2.2.11/doc/RedisBigData.html +61 -0
- data/redis/redis-2.2.11/doc/RedisCLI.html +37 -0
- data/redis/redis-2.2.11/doc/RedisEventLibrary.html +70 -0
- data/redis/redis-2.2.11/doc/RedisGuides.html +37 -0
- data/redis/redis-2.2.11/doc/RedisInternals.html +38 -0
- data/redis/redis-2.2.11/doc/RedisPipelining.html +93 -0
- data/redis/redis-2.2.11/doc/RedisStatus.html +56 -0
- data/redis/redis-2.2.11/doc/Redis_1_2_0_Changelog.html +40 -0
- data/redis/redis-2.2.11/doc/Redis_2_0_0_Changelog.html +62 -0
- data/redis/redis-2.2.11/doc/Redis_2_0_Whats_new.html +59 -0
- data/redis/redis-2.2.11/doc/RenameCommand.html +39 -0
- data/redis/redis-2.2.11/doc/RenamenxCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ReplicationHowto.html +43 -0
- data/redis/redis-2.2.11/doc/ReplyTypes.html +42 -0
- data/redis/redis-2.2.11/doc/RoadMap.html +38 -0
- data/redis/redis-2.2.11/doc/RpoplpushCommand.html +44 -0
- data/redis/redis-2.2.11/doc/RpushCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SaddCommand.html +41 -0
- data/redis/redis-2.2.11/doc/SaveCommand.html +39 -0
- data/redis/redis-2.2.11/doc/ScardCommand.html +41 -0
- data/redis/redis-2.2.11/doc/SdiffCommand.html +45 -0
- data/redis/redis-2.2.11/doc/SdiffstoreCommand.html +38 -0
- data/redis/redis-2.2.11/doc/SelectCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SetCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SetCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/SetbitCommand.html +45 -0
- data/redis/redis-2.2.11/doc/SetexCommand.html +42 -0
- data/redis/redis-2.2.11/doc/SetnxCommand.html +51 -0
- data/redis/redis-2.2.11/doc/SetrangeCommand.html +58 -0
- data/redis/redis-2.2.11/doc/Sets.html +36 -0
- data/redis/redis-2.2.11/doc/ShutdownCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SideBar.html +36 -0
- data/redis/redis-2.2.11/doc/SinterCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SinterstoreCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SismemberCommand.html +42 -0
- data/redis/redis-2.2.11/doc/SlaveofCommand.html +41 -0
- data/redis/redis-2.2.11/doc/SmembersCommand.html +38 -0
- data/redis/redis-2.2.11/doc/SmoveCommand.html +44 -0
- data/redis/redis-2.2.11/doc/SortCommand.html +75 -0
- data/redis/redis-2.2.11/doc/SortedSetCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/SortedSets.html +36 -0
- data/redis/redis-2.2.11/doc/Speed.html +38 -0
- data/redis/redis-2.2.11/doc/SponsorshipHistory.html +38 -0
- data/redis/redis-2.2.11/doc/SpopCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SrandmemberCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SremCommand.html +42 -0
- data/redis/redis-2.2.11/doc/StringCommandsSidebar.html +36 -0
- data/redis/redis-2.2.11/doc/Strings.html +37 -0
- data/redis/redis-2.2.11/doc/StrlenCommand.html +39 -0
- data/redis/redis-2.2.11/doc/SubstrCommand.html +52 -0
- data/redis/redis-2.2.11/doc/SunionCommand.html +40 -0
- data/redis/redis-2.2.11/doc/SunionstoreCommand.html +38 -0
- data/redis/redis-2.2.11/doc/SupportedLanguages.html +60 -0
- data/redis/redis-2.2.11/doc/SupportedPlatforms.html +37 -0
- data/redis/redis-2.2.11/doc/TemplateCommand.html +38 -0
- data/redis/redis-2.2.11/doc/TtlCommand.html +38 -0
- data/redis/redis-2.2.11/doc/TwitterAlikeExample.html +250 -0
- data/redis/redis-2.2.11/doc/TypeCommand.html +46 -0
- data/redis/redis-2.2.11/doc/UnstableSource.html +39 -0
- data/redis/redis-2.2.11/doc/VirtualMemorySpecification.html +156 -0
- data/redis/redis-2.2.11/doc/VirtualMemoryUserGuide.html +66 -0
- data/redis/redis-2.2.11/doc/ZaddCommand.html +43 -0
- data/redis/redis-2.2.11/doc/ZcardCommand.html +41 -0
- data/redis/redis-2.2.11/doc/ZincrbyCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZrangeCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZrangebyscoreCommand.html +77 -0
- data/redis/redis-2.2.11/doc/ZrankCommand.html +43 -0
- data/redis/redis-2.2.11/doc/ZremCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZremrangebyrankCommand.html +39 -0
- data/redis/redis-2.2.11/doc/ZremrangebyscoreCommand.html +39 -0
- data/redis/redis-2.2.11/doc/ZscoreCommand.html +41 -0
- data/redis/redis-2.2.11/doc/ZunionCommand.html +42 -0
- data/redis/redis-2.2.11/doc/ZunionstoreCommand.html +43 -0
- data/redis/redis-2.2.11/doc/index.html +43 -0
- data/redis/redis-2.2.11/doc/redis.png +0 -0
- data/redis/redis-2.2.11/doc/style.css +25 -0
- data/redis/redis-2.2.11/redis.conf +417 -0
- data/redis/redis-2.2.11/src/Makefile +177 -0
- data/redis/redis-2.2.11/src/adlist.c +325 -0
- data/redis/redis-2.2.11/src/adlist.h +92 -0
- data/redis/redis-2.2.11/src/ae.c +390 -0
- data/redis/redis-2.2.11/src/ae.h +117 -0
- data/redis/redis-2.2.11/src/ae_epoll.c +91 -0
- data/redis/redis-2.2.11/src/ae_kqueue.c +93 -0
- data/redis/redis-2.2.11/src/ae_select.c +72 -0
- data/redis/redis-2.2.11/src/anet.c +347 -0
- data/redis/redis-2.2.11/src/anet.h +57 -0
- data/redis/redis-2.2.11/src/aof.c +675 -0
- data/redis/redis-2.2.11/src/config.c +627 -0
- data/redis/redis-2.2.11/src/config.h +64 -0
- data/redis/redis-2.2.11/src/db.c +543 -0
- data/redis/redis-2.2.11/src/debug.c +314 -0
- data/redis/redis-2.2.11/src/dict.c +721 -0
- data/redis/redis-2.2.11/src/dict.h +156 -0
- data/redis/redis-2.2.11/src/fmacros.h +15 -0
- data/redis/redis-2.2.11/src/help.h +638 -0
- data/redis/redis-2.2.11/src/intset.c +422 -0
- data/redis/redis-2.2.11/src/intset.h +19 -0
- data/redis/redis-2.2.11/src/lzf.h +100 -0
- data/redis/redis-2.2.11/src/lzfP.h +159 -0
- data/redis/redis-2.2.11/src/lzf_c.c +295 -0
- data/redis/redis-2.2.11/src/lzf_d.c +150 -0
- data/redis/redis-2.2.11/src/mkreleasehdr.sh +9 -0
- data/redis/redis-2.2.11/src/multi.c +268 -0
- data/redis/redis-2.2.11/src/networking.c +899 -0
- data/redis/redis-2.2.11/src/object.c +484 -0
- data/redis/redis-2.2.11/src/pqsort.c +197 -0
- data/redis/redis-2.2.11/src/pqsort.h +15 -0
- data/redis/redis-2.2.11/src/pubsub.c +267 -0
- data/redis/redis-2.2.11/src/rdb.c +1020 -0
- data/redis/redis-2.2.11/src/redis-benchmark.c +530 -0
- data/redis/redis-2.2.11/src/redis-check-aof.c +185 -0
- data/redis/redis-2.2.11/src/redis-check-dump.c +681 -0
- data/redis/redis-2.2.11/src/redis-cli.c +773 -0
- data/redis/redis-2.2.11/src/redis.c +1677 -0
- data/redis/redis-2.2.11/src/redis.h +1022 -0
- data/redis/redis-2.2.11/src/release.c +13 -0
- data/redis/redis-2.2.11/src/replication.c +557 -0
- data/redis/redis-2.2.11/src/sds.c +639 -0
- data/redis/redis-2.2.11/src/sds.h +78 -0
- data/redis/redis-2.2.11/src/sha1.c +276 -0
- data/redis/redis-2.2.11/src/sha1.h +17 -0
- data/redis/redis-2.2.11/src/solarisfixes.h +22 -0
- data/redis/redis-2.2.11/src/sort.c +389 -0
- data/redis/redis-2.2.11/src/syncio.c +154 -0
- data/redis/redis-2.2.11/src/t_hash.c +476 -0
- data/redis/redis-2.2.11/src/t_list.c +986 -0
- data/redis/redis-2.2.11/src/t_set.c +610 -0
- data/redis/redis-2.2.11/src/t_string.c +438 -0
- data/redis/redis-2.2.11/src/t_zset.c +1084 -0
- data/redis/redis-2.2.11/src/testhelp.h +54 -0
- data/redis/redis-2.2.11/src/util.c +243 -0
- data/redis/redis-2.2.11/src/valgrind.sup +5 -0
- data/redis/redis-2.2.11/src/version.h +1 -0
- data/redis/redis-2.2.11/src/vm.c +1149 -0
- data/redis/redis-2.2.11/src/ziplist.c +1323 -0
- data/redis/redis-2.2.11/src/ziplist.h +15 -0
- data/redis/redis-2.2.11/src/zipmap.c +455 -0
- data/redis/redis-2.2.11/src/zipmap.h +48 -0
- data/redis/redis-2.2.11/src/zmalloc.c +278 -0
- data/redis/redis-2.2.11/src/zmalloc.h +47 -0
- data/redis/redis-2.2.11/tests/assets/default.conf +308 -0
- data/redis/redis-2.2.11/tests/integration/aof.tcl +104 -0
- data/redis/redis-2.2.11/tests/integration/redis-cli.tcl +208 -0
- data/redis/redis-2.2.11/tests/integration/replication.tcl +98 -0
- data/redis/redis-2.2.11/tests/support/redis.tcl +241 -0
- data/redis/redis-2.2.11/tests/support/server.tcl +294 -0
- data/redis/redis-2.2.11/tests/support/test.tcl +190 -0
- data/redis/redis-2.2.11/tests/support/tmpfile.tcl +15 -0
- data/redis/redis-2.2.11/tests/support/util.tcl +296 -0
- data/redis/redis-2.2.11/tests/test_helper.tcl +221 -0
- data/redis/redis-2.2.11/tests/unit/auth.tcl +15 -0
- data/redis/redis-2.2.11/tests/unit/basic.tcl +616 -0
- data/redis/redis-2.2.11/tests/unit/cas.tcl +135 -0
- data/redis/redis-2.2.11/tests/unit/expire.tcl +74 -0
- data/redis/redis-2.2.11/tests/unit/other.tcl +240 -0
- data/redis/redis-2.2.11/tests/unit/printver.tcl +6 -0
- data/redis/redis-2.2.11/tests/unit/protocol.tcl +62 -0
- data/redis/redis-2.2.11/tests/unit/pubsub.tcl +195 -0
- data/redis/redis-2.2.11/tests/unit/quit.tcl +40 -0
- data/redis/redis-2.2.11/tests/unit/sort.tcl +189 -0
- data/redis/redis-2.2.11/tests/unit/type/hash.tcl +300 -0
- data/redis/redis-2.2.11/tests/unit/type/list.tcl +819 -0
- data/redis/redis-2.2.11/tests/unit/type/set.tcl +334 -0
- data/redis/redis-2.2.11/tests/unit/type/zset.tcl +587 -0
- data/redis/redis-2.2.11/utils/build-static-symbols.tcl +22 -0
- data/redis/redis-2.2.11/utils/generate-command-help.rb +112 -0
- data/redis/redis-2.2.11/utils/mktarball.sh +13 -0
- data/redis/redis-2.2.11/utils/redis-copy.rb +78 -0
- data/redis/redis-2.2.11/utils/redis-sha1.rb +52 -0
- data/redis/redis-2.2.11/utils/redis_init_script +42 -0
- 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
|
+
}
|