Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
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
Show 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