5454#include < libmemcached/common.h>
5555#include < libmemcached/string.hpp>
5656
57+ static int tokenize (char *buffer, int length, char **tokens, int ntokens)
58+ {
59+ int i;
60+ int cur_str;
61+ int begin_str= 0 ;
62+ for (i= 0 ; i < ntokens; i++)
63+ {
64+ cur_str= begin_str;
65+ while (!iscntrl (buffer[cur_str]) && !isspace (buffer[cur_str]))
66+ {
67+ if (cur_str >= length) return -1 ;
68+ cur_str++;
69+ }
70+ if (cur_str == begin_str) break ;
71+ buffer[cur_str]= ' \0 ' ;
72+ tokens[i]= &buffer[begin_str];
73+ begin_str= cur_str + 1 ;
74+ }
75+ return i;
76+ }
77+
5778static memcached_return_t textual_value_fetch (memcached_server_write_instance_st ptr,
5879 char *buffer, size_t buffer_length,
5980 memcached_result_st *result)
6081{
6182 char *string_ptr;
62- char *end_ptr;
63- char *next_ptr;
64- size_t value_length;
65- size_t to_read;
66- ssize_t read_length= 0 ;
83+ ssize_t value_length;
84+ ssize_t read_length;
6785
6886 if (ptr->root ->flags .use_udp )
6987 return memcached_set_error (*ptr, MEMCACHED_NOT_SUPPORTED, MEMCACHED_AT);
7088
7189 WATCHPOINT_ASSERT (ptr->root );
72- end_ptr= buffer + buffer_length;
90+
91+ string_ptr= buffer + 6 ; /* "VALUE " */
7392
7493 memcached_result_reset (result);
7594
76- string_ptr= buffer;
77- string_ptr+= 6 ; /* "VALUE " */
95+ char *tokens[4 ]= {NULL , };
96+ int ntoken= tokenize (string_ptr, buffer_length - 6 , tokens, 4 );
97+ if (ntoken < 0 )
98+ return MEMCACHED_PARTIAL_READ;
7899
79100 /* We load the key */
80101 {
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++;
92- }
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 ;
102+ char *key= tokens[0 ] + memcached_array_size (ptr->root ->_namespace );
103+ int key_length= snprintf (result->item_key , MEMCACHED_MAX_KEY, " %s" , key);
104+ if (key_length >= MEMCACHED_MAX_KEY)
105+ {
106+ snprintf (result->item_key + MEMCACHED_MAX_KEY - 4 , 4 , " ..." );
107+ key_length= MEMCACHED_MAX_KEY - 1 ;
100108 memcached_set_error (*ptr, MEMCACHED_KEY_TOO_BIG, MEMCACHED_AT);
101109 }
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 );
114-
115- if (end_ptr == string_ptr)
116- goto read_error;
117110
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 ;
111+ result->key_length = (size_t )key_length;
134112 }
135- else
113+
114+ result->item_flags = (uint32_t )strtoul (tokens[1 ], NULL , 10 );
115+ value_length= (ssize_t )strtoull (tokens[2 ], NULL , 10 );
116+ if (ntoken == 4 )
136117 {
137- string_ptr++;
138- for (next_ptr= string_ptr; isdigit (*string_ptr); string_ptr++) {};
139- result->item_cas = strtoull (next_ptr, &string_ptr, 10 );
118+ result->item_cas = strtoull (tokens[3 ], NULL , 10 );
140119 }
141120
142- if (end_ptr < string_ptr)
143- goto read_error;
144-
145121 /* We add two bytes so that we can walk the \r\n */
146122 if (memcached_failed (memcached_string_check (&result->value , value_length +2 )))
147123 {
@@ -150,43 +126,27 @@ static memcached_return_t textual_value_fetch(memcached_server_write_instance_st
150126
151127 {
152128 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))
129+ memcached_return_t rc= memcached_io_read (ptr, value_ptr, value_length + 2 , &read_length);
130+ if (rc == MEMCACHED_IN_PROGRESS)
163131 {
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;
132+ memcached_quit_server (ptr, true );
133+ return memcached_set_error (*ptr, rc, MEMCACHED_AT);
134+ }
135+ else if (memcached_failed (rc))
136+ {
137+ return rc;
169138 }
170- }
171139
172- if (read_length != ( ssize_t )( value_length + 2 ) )
173- {
174- goto read_error ;
175- }
140+ if (read_length != value_length + 2 )
141+ {
142+ return MEMCACHED_PARTIAL_READ ;
143+ }
176144
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 ;
145+ memset (value_ptr + value_length, 0 , 2 );
183146 memcached_string_set_length (&result->value , value_length);
184147 }
185148
186149 return MEMCACHED_SUCCESS;
187-
188- read_error:
189- return MEMCACHED_PARTIAL_READ;
190150}
191151
192152static memcached_return_t textual_version_fetch (memcached_server_write_instance_st instance, char *buffer)
0 commit comments