summaryrefslogtreecommitdiff
path: root/hiredis.c
diff options
context:
space:
mode:
authorPieter Noordhuis <pcnoordhuis@gmail.com>2010-12-02 16:18:30 +0100
committerPieter Noordhuis <pcnoordhuis@gmail.com>2010-12-02 16:20:55 +0100
commit7684d556bd7250786eb6fd38c656368530903677 (patch)
tree480c0053c81973476277811ab8683152c4144e22 /hiredis.c
parentff50dff70d03a994077d7d1ab960f32dec372ab2 (diff)
Add (nearly) full printf support by delegating to vsprintf
Diffstat (limited to 'hiredis.c')
-rw-r--r--hiredis.c54
1 files changed, 54 insertions, 0 deletions
diff --git a/hiredis.c b/hiredis.c
index 7ae962b..c3b2815 100644
--- a/hiredis.c
+++ b/hiredis.c
@@ -32,6 +32,7 @@
#include <unistd.h>
#include <assert.h>
#include <errno.h>
+#include <ctype.h>
#include "hiredis.h"
#include "net.h"
@@ -639,6 +640,59 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
case '%':
current = sdscat(current,"%");
break;
+ default:
+ /* Try to detect printf format */
+ {
+ char _format[16];
+ const char *_p = c+1;
+ size_t _l = 0;
+ va_list _cpy;
+
+ /* Flags */
+ if (*_p != '\0' && *_p == '#') _p++;
+ if (*_p != '\0' && *_p == '0') _p++;
+ if (*_p != '\0' && *_p == '-') _p++;
+ if (*_p != '\0' && *_p == ' ') _p++;
+ if (*_p != '\0' && *_p == '+') _p++;
+
+ /* Field width */
+ while (*_p != '\0' && isdigit(*_p)) _p++;
+
+ /* Precision */
+ if (*_p == '.') {
+ _p++;
+ while (*_p != '\0' && isdigit(*_p)) _p++;
+ }
+
+ /* Modifiers */
+ if (*_p != '\0') {
+ if (*_p == 'h' || *_p == 'l') {
+ /* Allow a single repetition for these modifiers */
+ if (_p[0] == _p[1]) _p++;
+ _p++;
+ }
+ }
+
+ /* Conversion specifier */
+ if (*_p != '\0' && strchr("diouxXeEfFgGaA",*_p) != NULL) {
+ _l = (_p+1)-c;
+ if (_l < sizeof(_format)-2) {
+ memcpy(_format,c,_l);
+ _format[_l] = '\0';
+ va_copy(_cpy,ap);
+ current = sdscatvprintf(current,_format,_cpy);
+ interpolated = 1;
+ va_end(_cpy);
+
+ /* Update current position (note: outer blocks
+ * increment c twice so compensate here) */
+ c = _p-1;
+ }
+ }
+
+ /* Consume and discard vararg */
+ va_arg(ap,void);
+ }
}
c++;
}