5454#include < libmemcached/common.h>
5555#include < libmemcached/string.hpp>
5656
57+ static memcached_return_t tokenize (char *str_ptr, char *end_ptr,
58+ char **tokens, size_t *ntokens)
59+ {
60+ size_t i;
61+ char *cur_ptr;
62+ for (i= 0 ; i < *ntokens; i++)
63+ {
64+ cur_ptr= str_ptr;
65+ while (!iscntrl (*cur_ptr) && !isspace (*cur_ptr))
66+ {
67+ if (cur_ptr >= end_ptr) return MEMCACHED_PARTIAL_READ;
68+ cur_ptr++;
69+ }
70+ if (cur_ptr == str_ptr) break ;
71+ *cur_ptr= ' \0 ' ;
72+ tokens[i]= str_ptr;
73+ str_ptr= cur_ptr + 1 ;
74+ }
75+ *ntokens= i;
76+ return MEMCACHED_SUCCESS;
77+ }
78+
5779static memcached_return_t textual_value_fetch (memcached_server_write_instance_st ptr,
5880 char *buffer, size_t buffer_length,
5981 memcached_result_st *result)
6082{
6183 char *string_ptr;
6284 char *end_ptr;
63- char *next_ptr;
64- size_t value_length;
65- size_t to_read;
66- ssize_t read_length= 0 ;
85+ ssize_t value_length;
86+ ssize_t read_length;
6787
6888 if (ptr->root ->flags .use_udp )
6989 return memcached_set_error (*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
7090
7191 WATCHPOINT_ASSERT (ptr->root );
92+
93+ string_ptr= buffer + 6 ; /* "VALUE " */
7294 end_ptr= buffer + buffer_length;
7395
7496 memcached_result_reset (result);
7597
76- string_ptr= buffer;
77- string_ptr+= 6 ; /* "VALUE " */
98+ char *tokens[4 ]= {NULL , };
99+ size_t ntoken= 4 ;
100+
101+ memcached_return_t rc= tokenize (string_ptr, end_ptr, tokens, &ntoken);
102+ if (rc != MEMCACHED_SUCCESS)
103+ return rc;
78104
79105 /* We load the key */
80106 {
81- char *key= result->item_key ;
82- size_t key_length= 0 ;
83-
84- string_ptr += memcached_array_size (ptr->root ->_namespace ); /* prefix length */
85-
86- while (!iscntrl (*string_ptr) && !isspace (*string_ptr)) {
87- if (key_length < MEMCACHED_MAX_KEY) {
88- key[key_length]= *string_ptr;
89- }
90- key_length++;
91- string_ptr++;
107+ char *key= tokens[0 ] + memcached_array_size (ptr->root ->_namespace );
108+ int key_length= snprintf (result->item_key , MEMCACHED_MAX_KEY, " %s" , key);
109+ if (key_length < 0 )
110+ {
111+ return memcached_set_error (*ptr, MEMCACHED_MEMORY_ALLOCATION_FAILURE, MEMCACHED_AT);
92112 }
93-
94- if (key_length < MEMCACHED_MAX_KEY) {
95- key[key_length]= 0 ;
96- result->key_length = key_length;
97- } else {
98- snprintf (key + MEMCACHED_MAX_KEY - 4 , 4 , " ..." );
99- result->key_length = MEMCACHED_MAX_KEY - 1 ;
113+ else if (key_length >= MEMCACHED_MAX_KEY)
114+ {
115+ snprintf (result->item_key + MEMCACHED_MAX_KEY - 4 , 4 , " ..." );
116+ key_length= MEMCACHED_MAX_KEY - 1 ;
100117 memcached_set_error (*ptr, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
101118 }
102- }
103-
104- if (end_ptr == string_ptr)
105- goto read_error;
106-
107- /* Flags fetch move past space */
108- string_ptr++;
109- if (end_ptr == string_ptr)
110- goto read_error;
111-
112- for (next_ptr= string_ptr; isdigit (*string_ptr); string_ptr++) {};
113- result->item_flags = (uint32_t ) strtoul (next_ptr, &string_ptr, 10 );
114119
115- if (end_ptr == string_ptr)
116- goto read_error;
117-
118- /* Length fetch move past space*/
119- string_ptr++;
120- if (end_ptr == string_ptr)
121- goto read_error;
122-
123- for (next_ptr= string_ptr; isdigit (*string_ptr); string_ptr++) {};
124- value_length= (size_t )strtoull (next_ptr, &string_ptr, 10 );
125-
126- if (end_ptr == string_ptr)
127- goto read_error;
128-
129- /* Skip spaces */
130- if (*string_ptr == ' \r ' )
131- {
132- /* Skip past the \r\n */
133- string_ptr+= 2 ;
120+ result->key_length = (size_t )key_length;
134121 }
135- else
122+
123+ result->item_flags = (uint32_t )strtoul (tokens[1 ], NULL , 10 );
124+ value_length= (ssize_t )strtoull (tokens[2 ], NULL , 10 );
125+ if (ntoken == 4 )
136126 {
137- string_ptr++;
138- for (next_ptr= string_ptr; isdigit (*string_ptr); string_ptr++) {};
139- result->item_cas = strtoull (next_ptr, &string_ptr, 10 );
127+ result->item_cas = strtoull (tokens[3 ], NULL , 10 );
140128 }
141129
142- if (end_ptr < string_ptr)
143- goto read_error;
144-
145130 /* We add two bytes so that we can walk the \r\n */
146131 if (memcached_failed (memcached_string_check (&result->value , value_length +2 )))
147132 {
@@ -150,43 +135,27 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
150135
151136 {
152137 char *value_ptr= memcached_string_value_mutable (&result->value );
153- /*
154- We read the \r\n into the string since not doing so is more
155- cycles then the waster of memory to do so.
156-
157- We are null terminating through, which will most likely make
158- some people lazy about using the return length.
159- */
160- to_read= (value_length) + 2 ;
161- memcached_return_t rrc= memcached_io_read (ptr, value_ptr, to_read, &read_length);
162- if (memcached_failed (rrc))
138+ rc= memcached_io_read (ptr, value_ptr, value_length + 2 , &read_length);
139+ if (rc == MEMCACHED_IN_PROGRESS)
163140 {
164- if (rrc == MEMCACHED_IN_PROGRESS) {
165- memcached_quit_server (ptr, true );
166- return memcached_set_error (*ptr, rrc, MEMCACHED_AT);
167- }
168- return rrc;
141+ memcached_quit_server (ptr, true );
142+ return memcached_set_error (*ptr, rc, MEMCACHED_AT);
143+ }
144+ else if (memcached_failed (rc))
145+ {
146+ return rc;
169147 }
170- }
171148
172- if (read_length != ( ssize_t )( value_length + 2 ) )
173- {
174- goto read_error ;
175- }
149+ if (read_length != value_length + 2 )
150+ {
151+ return MEMCACHED_PARTIAL_READ ;
152+ }
176153
177- /* This next bit blows the API, but this is internal....*/
178- {
179- char *char_ptr;
180- char_ptr= memcached_string_value_mutable (&result->value );;
181- char_ptr[value_length]= 0 ;
182- char_ptr[value_length +1 ]= 0 ;
154+ memset (value_ptr + value_length, 0 , 2 );
183155 memcached_string_set_length (&result->value , value_length);
184156 }
185157
186158 return MEMCACHED_SUCCESS;
187-
188- read_error:
189- return MEMCACHED_PARTIAL_READ;
190159}
191160
192161static memcached_return_t textual_version_fetch (memcached_server_write_instance_st instance, char *buffer)
0 commit comments