Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
hiredis
Commits
1375e400
Commit
1375e400
authored
Sep 30, 2011
by
Pieter Noordhuis
Browse files
Extract object code to separate file (+refactor)
parent
70fe4177
Changes
3
Hide whitespace changes
Inline
Side-by-side
object.c
0 → 100644
View file @
1375e400
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "object.h"
void
redis_object_free
(
redis_object
**
ptr
)
{
redis_object
*
obj
=
*
ptr
;
switch
(
obj
->
type
)
{
case
REDIS_STRING
:
case
REDIS_STATUS
:
case
REDIS_ERROR
:
if
(
obj
->
str
!=
NULL
)
{
free
(
obj
->
str
);
obj
->
str
=
NULL
;
obj
->
len
=
0
;
}
break
;
case
REDIS_ARRAY
:
if
(
obj
->
element
!=
NULL
)
{
unsigned
int
j
;
for
(
j
=
0
;
j
<
obj
->
elements
;
j
++
)
{
if
(
obj
->
element
[
j
]
!=
NULL
)
{
redis_object_free
(
&
obj
->
element
[
j
]);
}
}
free
(
obj
->
element
);
obj
->
element
=
NULL
;
obj
->
elements
=
0
;
}
break
;
}
free
(
*
ptr
);
*
ptr
=
NULL
;
}
static
redis_object
*
_object_create_from_protocol
(
redis_protocol
*
p
)
{
redis_object
*
obj
,
*
parent
;
/* Create object when the callback was not fired before. */
if
(
p
->
data
==
NULL
)
{
obj
=
p
->
data
=
malloc
(
sizeof
(
redis_object
));
if
(
obj
==
NULL
)
{
return
NULL
;
}
obj
->
type
=
p
->
type
;
obj
->
str
=
NULL
;
obj
->
len
=
0
;
obj
->
element
=
NULL
;
obj
->
elements
=
0
;
if
(
p
->
parent
)
{
parent
=
(
redis_object
*
)
p
->
parent
->
data
;
assert
(
parent
->
type
==
REDIS_ARRAY
);
parent
->
element
[
p
->
parent
->
cursor
]
=
obj
;
}
}
obj
=
(
redis_object
*
)
p
->
data
;
assert
(
obj
&&
obj
->
type
==
p
->
type
);
return
obj
;
}
static
int
_object_string_cb
(
redis_parser
*
parser
,
redis_protocol
*
p
,
const
char
*
buf
,
size_t
len
)
{
redis_object
*
self
;
char
*
dst
;
((
void
)
parser
);
self
=
_object_create_from_protocol
(
p
);
if
(
self
==
NULL
)
{
return
-
1
;
}
if
(
self
->
type
==
REDIS_STRING
)
{
assert
(
p
->
size
>=
0
);
dst
=
self
->
str
;
/* The size is known upfront: allocate memory */
if
(
dst
==
NULL
)
{
dst
=
malloc
(
p
->
size
+
1
);
if
(
dst
==
NULL
)
{
return
-
1
;
}
}
}
else
{
assert
(
p
->
size
<
0
);
/* The size is not known upfront: dynamically allocate memory */
dst
=
realloc
(
self
->
str
,
self
->
len
+
len
+
1
);
if
(
dst
==
NULL
)
{
return
-
1
;
}
}
/* Copy provided buffer */
memcpy
(
dst
+
self
->
len
,
buf
,
len
);
self
->
str
=
dst
;
self
->
len
+=
len
;
self
->
str
[
self
->
len
]
=
'\0'
;
return
0
;
}
static
int
_object_array_cb
(
redis_parser
*
parser
,
redis_protocol
*
p
,
size_t
len
)
{
redis_object
*
self
;
((
void
)
parser
);
self
=
_object_create_from_protocol
(
p
);
if
(
self
==
NULL
)
{
return
-
1
;
}
if
(
len
>
0
)
{
self
->
element
=
calloc
(
len
,
sizeof
(
redis_object
*
));
if
(
self
->
element
==
NULL
)
{
return
-
1
;
}
}
self
->
elements
=
len
;
return
0
;
}
static
int
_object_integer_cb
(
redis_parser
*
parser
,
redis_protocol
*
p
,
int64_t
value
)
{
redis_object
*
self
;
((
void
)
parser
);
self
=
_object_create_from_protocol
(
p
);
if
(
self
==
NULL
)
{
return
-
1
;
}
self
->
integer
=
value
;
return
0
;
}
static
int
_object_nil_cb
(
redis_parser
*
parser
,
redis_protocol
*
p
)
{
redis_object
*
self
;
((
void
)
parser
);
self
=
_object_create_from_protocol
(
p
);
if
(
self
==
NULL
)
{
return
-
1
;
}
return
0
;
}
static
void
_object_destroy_cb
(
redis_parser
*
parser
,
redis_protocol
*
p
)
{
assert
(
NULL
);
}
/* Set of callbacks that can be passed to the parser. */
redis_parser_callbacks
redis_object_parser_callbacks
=
{
.
on_string
=
_object_string_cb
,
.
on_array
=
_object_array_cb
,
.
on_integer
=
_object_integer_cb
,
.
on_nil
=
_object_nil_cb
,
.
destroy
=
_object_destroy_cb
};
object.h
0 → 100644
View file @
1375e400
#ifndef _HIREDIS_OBJECT_H
#define _HIREDIS_OBJECT_H 1
#include "parser.h"
typedef
struct
redis_object_s
redis_object
;
struct
redis_object_s
{
int
type
;
/* Object type */
int64_t
integer
;
/* Value for REDIS_INTEGER */
char
*
str
;
/* REDIS_STRING, REDIS_STATUS, REDIS_ERROR */
unsigned
int
len
;
/* String length */
struct
redis_object_s
**
element
;
/* Actual elements in REDIS_ARRAY */
unsigned
int
elements
;
/* Number of elements REDIS_ARRAY */
};
void
redis_object_free
(
redis_object
**
obj
);
extern
redis_parser_callbacks
redis_object_parser_callbacks
;
#endif
test/test-object.c
0 → 100644
View file @
1375e400
#include "../fmacros.h"
/* misc */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* local */
#include "test-helper.h"
#include "../parser.h"
#include "../object.h"
void
test_string
(
redis_parser
*
parser
)
{
const
char
*
buf
=
"$5
\r\n
hello
\r\n
"
;
redis_protocol
*
res
;
redis_object
*
obj
;
redis_parser_init
(
parser
,
&
redis_object_parser_callbacks
);
assert
(
redis_parser_execute
(
parser
,
&
res
,
buf
,
11
)
==
11
);
obj
=
(
redis_object
*
)
res
->
data
;
assert
(
obj
!=
NULL
);
assert_equal_int
(
obj
->
type
,
REDIS_STRING
);
assert_equal_string
(
obj
->
str
,
"hello"
);
assert_equal_int
(
obj
->
len
,
5
);
redis_object_free
(
&
obj
);
}
void
test_chunked_string
(
redis_parser
*
parser
)
{
const
char
*
buf
=
"$5
\r\n
hello
\r\n
"
;
redis_protocol
*
res
;
redis_object
*
obj
;
redis_parser_init
(
parser
,
&
redis_object_parser_callbacks
);
assert
(
redis_parser_execute
(
parser
,
&
res
,
buf
+
0
,
6
)
==
6
);
assert
(
redis_parser_execute
(
parser
,
&
res
,
buf
+
6
,
5
)
==
5
);
obj
=
(
redis_object
*
)
res
->
data
;
assert
(
obj
!=
NULL
);
assert_equal_int
(
obj
->
type
,
REDIS_STRING
);
assert_equal_string
(
obj
->
str
,
"hello"
);
assert_equal_int
(
obj
->
len
,
5
);
redis_object_free
(
&
obj
);
}
void
test_empty_string
(
redis_parser
*
parser
)
{
const
char
*
buf
=
"$0
\r\n\r\n
"
;
redis_protocol
*
res
;
redis_object
*
obj
;
redis_parser_init
(
parser
,
&
redis_object_parser_callbacks
);
assert
(
redis_parser_execute
(
parser
,
&
res
,
buf
,
6
)
==
6
);
obj
=
(
redis_object
*
)
res
->
data
;
assert
(
obj
!=
NULL
);
assert_equal_int
(
obj
->
type
,
REDIS_STRING
);
assert_equal_string
(
obj
->
str
,
""
);
assert_equal_int
(
obj
->
len
,
0
);
redis_object_free
(
&
obj
);
}
void
test_nil
(
redis_parser
*
parser
)
{
const
char
*
buf
=
"$-1
\r\n
"
;
redis_protocol
*
res
;
redis_object
*
obj
;
redis_parser_init
(
parser
,
&
redis_object_parser_callbacks
);
assert
(
redis_parser_execute
(
parser
,
&
res
,
buf
,
5
)
==
5
);
obj
=
(
redis_object
*
)
res
->
data
;
assert
(
obj
!=
NULL
);
assert_equal_int
(
obj
->
type
,
REDIS_NIL
);
redis_object_free
(
&
obj
);
}
void
test_array
(
redis_parser
*
parser
)
{
const
char
*
buf
=
"*2
\r\n
"
"$5
\r\n
hello
\r\n
"
"$5
\r\n
world
\r\n
"
;
redis_protocol
*
res
;
redis_object
*
obj
;
redis_parser_init
(
parser
,
&
redis_object_parser_callbacks
);
assert
(
redis_parser_execute
(
parser
,
&
res
,
buf
,
26
)
==
26
);
obj
=
(
redis_object
*
)
res
->
data
;
assert
(
obj
!=
NULL
);
assert_equal_int
(
obj
->
type
,
REDIS_ARRAY
);
assert_equal_int
(
obj
->
elements
,
2
);
assert_equal_int
(
obj
->
element
[
0
]
->
type
,
REDIS_STRING
);
assert_equal_string
(
obj
->
element
[
0
]
->
str
,
"hello"
);
assert_equal_int
(
obj
->
element
[
0
]
->
len
,
5
);
assert_equal_int
(
obj
->
element
[
1
]
->
type
,
REDIS_STRING
);
assert_equal_string
(
obj
->
element
[
1
]
->
str
,
"world"
);
assert_equal_int
(
obj
->
element
[
1
]
->
len
,
5
);
redis_object_free
(
&
obj
);
}
void
test_empty_array
(
redis_parser
*
parser
)
{
const
char
*
buf
=
"*0
\r\n
"
;
redis_protocol
*
res
;
redis_object
*
obj
;
redis_parser_init
(
parser
,
&
redis_object_parser_callbacks
);
assert
(
redis_parser_execute
(
parser
,
&
res
,
buf
,
4
)
==
4
);
obj
=
(
redis_object
*
)
res
->
data
;
assert
(
obj
!=
NULL
);
assert_equal_int
(
obj
->
type
,
REDIS_ARRAY
);
assert_equal_int
(
obj
->
elements
,
0
);
redis_object_free
(
&
obj
);
}
int
main
(
int
argc
,
char
**
argv
)
{
redis_parser
*
parser
=
malloc
(
sizeof
(
redis_parser
));
printf
(
"redis_object: %lu bytes
\n
"
,
sizeof
(
redis_object
));
test_string
(
parser
);
test_chunked_string
(
parser
);
test_empty_string
(
parser
);
test_nil
(
parser
);
test_array
(
parser
);
test_empty_array
(
parser
);
//test_integer(parser);
//test_status(parser);
//test_error(parser);
//test_abort_after_error(parser);
free
(
parser
);
return
0
;
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment