Changeset 480
- Timestamp:
- 03/30/07 09:07:27 (2 years ago)
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/client-xs-20070328/Cache-Memcached-GetParserXS/GetParserXS.xs
r305 r480 25 25 } 26 26 27 void set_key (AV* self, const char *key) {28 av_store(self, KEY, newSVpv(key, strlen(key)));29 } 30 31 SV *get_key_sv (AV* self) {27 inline void set_key (AV* self, const char *key, int len) { 28 av_store(self, KEY, newSVpv(key, len)); 29 } 30 31 inline SV *get_key_sv (AV* self) { 32 32 SV** svp = av_fetch(self, KEY, 0); 33 33 if (svp) … … 36 36 } 37 37 38 SV *get_on_item (AV* self) {38 inline SV *get_on_item (AV* self) { 39 39 SV** svp = av_fetch(self, ON_ITEM, 0); 40 40 if (svp) … … 43 43 } 44 44 45 void set_flags (AV* self, int flags) {45 inline void set_flags (AV* self, int flags) { 46 46 av_store(self, FLAGS, newSViv(flags)); 47 47 } 48 48 49 void set_offset (AV* self, int offset) {49 inline void set_offset (AV* self, int offset) { 50 50 av_store(self, OFFSET, newSViv(offset)); 51 51 } 52 52 53 void set_state (AV* self, int state) {53 inline void set_state (AV* self, int state) { 54 54 av_store(self, STATE, newSViv(state)); 55 55 } 56 56 57 HV* get_dest (AV* self) {57 inline HV* get_dest (AV* self) { 58 58 SV** svp = av_fetch(self, DEST, 0); 59 59 if (svp) … … 62 62 } 63 63 64 in t get_state (AV* self) {64 inline int get_state (AV* self) { 65 65 SV** svp = av_fetch(self, STATE, 0); 66 66 if (svp) … … 69 69 } 70 70 71 SV* get_buffer (AV* self) {71 inline SV* get_buffer (AV* self) { 72 72 SV** svp = av_fetch(self, BUF, 0); 73 73 if (svp) … … 88 88 STRLEN len; 89 89 char* buf; 90 char key[257];91 90 unsigned int itemlen; 92 91 unsigned int flags; … … 94 93 int nslen = get_nslen(self); 95 94 SV* on_item = get_on_item(self); 96 95 register signed char c; 96 char *key; 97 register char *p; 98 int key_len, barelen; 99 int state, copy, new_p; 100 char *barekey; 101 97 102 if (DEBUG) 98 103 printf("get_buffer (nslen = %d)...\n", nslen); … … 101 106 int rv; 102 107 buf = SvPV(bufsv, len); 103 104 if (DEBUG) 105 printf(" buf (len=%d) = [%s]\n", len, buf); 106 107 scanned = 0; 108 rv = sscanf(buf, "VALUE %256s %u %u%n", key, &flags, &itemlen, &scanned); 109 110 if (DEBUG) 111 printf("rv=%d, scanned=%d, one=[%d], two=[%d]\n", 112 rv, scanned, buf[scanned], buf[scanned+1]); 113 114 if (rv >= 3 && scanned && buf[scanned+1] == '\n') { 115 int p = scanned + 2; /* 2 to skip \r\n */ 116 int state = itemlen + 2; /* 2 to include reading final \r\n, a different \r\n */ 117 int copy = len - p > state ? state : len - p; 118 char *barekey = key + nslen; 119 120 if (DEBUG) 108 p = buf; 109 110 if (DEBUG) { 111 char first_line[1000]; 112 int i; 113 char *end; 114 for (i = 0, end = buf; *end && *end != '\n' && i++ < 900; end++) 115 ; 116 end += 10; 117 strncpy (first_line, buf, end - buf + 1); 118 first_line[end - buf + 1] = '\0'; 119 printf("GOT buf (len=%d)\nFirst line: %s\n", len, first_line); 120 } 121 122 if ((c = *p++) == 'V') { 123 if (*p++ != 'A' || *p++ != 'L' || *p++ != 'U' || *p++ != 'E' || *p++ != ' ') { 124 if (DEBUG) 125 puts ("ERROR: Illegal command beginning with V"); 126 goto recover_from_partial_line; 127 } 128 129 // Parsing VALUE %s<key> %u<flags> %u<bytes> 130 131 for (key = p; *p++ > ' ';) 132 ; 133 key_len = p - key - 1; 134 if (*(p - 1) != ' ') { 135 if (DEBUG) 136 printf ("ERROR: key not space-terminated: key %s, char %c\n", key, *(p - 1)); 137 goto recover_from_partial_line; 138 } 139 // Note that key just points into the buffer and is not null-terminated 140 // yet. Leave it that way in case we're dealing with a partial line. 141 142 // Get flags and itemlen as integers. Note invalid characters 143 // are not caught and will result in strange numbers. 144 145 for (flags = 0; (c = *p++ - '0') >= 0; flags = flags * 10 + c) 146 ; 147 if (c != (signed char)' ' - '0') { 148 if (DEBUG) 149 puts ("ERROR: Flags not space terminated"); 150 goto recover_from_partial_line; 151 } 152 153 154 for (itemlen = 0; (c = *p++ - '0') >= 0; itemlen = itemlen * 10 + c) 155 ; 156 if (c != (signed char)'\r' - '0' || *p++ != '\n') { 157 if (DEBUG) 158 puts ("ERROR: byte count not CRLF-terminated"); 159 goto recover_from_partial_line; 160 } 161 162 163 // p is left at the start of the value data. 164 165 new_p = p - buf; 166 state = itemlen + 2; /* 2 to include reading final \r\n, a different \r\n */ 167 copy = len - new_p > state ? state : len - new_p; 168 barekey = key + nslen; 169 barelen = key_len - nslen; 170 171 if (DEBUG) { 172 char temp_key[256]; 173 strncpy (temp_key, key, key_len); 174 temp_key[key_len] = '\0'; 121 175 printf("key=[%s], state=%d, copy=%d\n", key, state, copy); 176 } 122 177 123 178 if (copy) { 124 //SV* newSVpv(const char*, STRLEN); 125 //SV** hv_store(HV*, const char* key, U32 klen, SV* val, U32 hash); 126 /* $ret->{$self->[KEY]} = substr($self->[BUF], $p, $copy) */ 127 hv_store(ret, barekey, strlen(barekey), newSVpv(buf + p, copy), 0); 128 buf[p + copy - 1] = '\0'; 179 *(key + key_len) = '\0'; // Null-terminate the key in-buffer 180 hv_store(ret, barekey, barelen, newSVpv(buf + new_p, copy), 0); 181 buf[new_p + copy - 1] = '\0'; 129 182 130 183 if (DEBUG) 131 printf("doing store: len=%d key=[%s] of data [%s]\n", 132 strlen(barekey), barekey, 133 buf + p); 184 printf("doing store: len=%d key=[%s] of data [%c]\n", 185 strlen(barekey), barekey, *(buf + new_p)); 134 186 } 135 187 136 188 /* delete the stuff we used */ 137 sv_chop(bufsv, buf + p + copy);189 sv_chop(bufsv, buf + new_p + copy); 138 190 139 191 if (copy == state) { … … 144 196 SAVETMPS ; 145 197 PUSHMARK(SP) ; 146 XPUSHs(sv_2mortal(newSVpv(barekey, strlen(barekey))));198 XPUSHs(sv_2mortal(newSVpv(barekey, barelen))); 147 199 XPUSHs(sv_2mortal(newSViv(flags))); 148 200 PUTBACK ; … … 158 210 set_offset(self, copy); 159 211 set_flags(self, flags); 160 set_key(self, barekey );212 set_key(self, barekey, barelen); 161 213 set_state(self, state); 162 214 … … 168 220 } 169 221 170 if (strncmp(buf, "END\r\n", 5) == 0) { 171 /* we're done successfully, return 1 to finish */ 172 return final_answer(self, 1); 173 } 222 else if (c == 'E') { 223 224 // Parsing END 225 226 if (*p++ == 'N' && *p++ == 'D' && *p++ == '\r' && *p == '\n') 227 return final_answer(self, 1); 228 } 229 // Just fall through if after 'E' was not "ND\r\n" 230 231 else 232 ; // Unknown command: not 'E' or 'V' at [0] 174 233 175 234 … … 183 242 */ 184 243 244 recover_from_partial_line: 185 245 set_offset(self, len); 186 246 return 0;
