126 goto quit; |
126 goto quit; |
127 } |
127 } |
128 |
128 |
129 Py_INCREF(Py_None); |
129 Py_INCREF(Py_None); |
130 return Py_None; |
130 return Py_None; |
131 |
|
132 quit: |
131 quit: |
133 return NULL; |
132 return NULL; |
134 } |
133 } |
135 |
134 |
|
135 #ifdef _WIN32 |
|
136 # ifdef _MSC_VER |
|
137 /* msvc 6.0 has problems */ |
|
138 # define inline __inline |
|
139 typedef unsigned long uint32_t; |
|
140 # else |
|
141 # include <stdint.h> |
|
142 # endif |
|
143 static uint32_t ntohl(uint32_t x) |
|
144 { |
|
145 return ((x & 0x000000ffUL) << 24) | |
|
146 ((x & 0x0000ff00UL) << 8) | |
|
147 ((x & 0x00ff0000UL) >> 8) | |
|
148 ((x & 0xff000000UL) >> 24); |
|
149 } |
|
150 #else |
|
151 /* not windows */ |
|
152 # include <sys/types.h> |
|
153 # if defined __BEOS__ && !defined __HAIKU__ |
|
154 # include <ByteOrder.h> |
|
155 # else |
|
156 # include <arpa/inet.h> |
|
157 # endif |
|
158 # include <inttypes.h> |
|
159 #endif |
|
160 |
|
161 static PyObject *parse_dirstate(PyObject *self, PyObject *args) |
|
162 { |
|
163 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL; |
|
164 PyObject *fname = NULL, *cname = NULL, *entry = NULL; |
|
165 char *str, *cur, *end, *cpos; |
|
166 int state, mode, size, mtime, flen; |
|
167 int len; |
|
168 char decode[16]; /* for alignment */ |
|
169 |
|
170 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate", |
|
171 &PyDict_Type, &dmap, |
|
172 &PyDict_Type, &cmap, |
|
173 &str, &len)) |
|
174 goto quit; |
|
175 |
|
176 /* read parents */ |
|
177 if (len < 40) |
|
178 goto quit; |
|
179 |
|
180 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20); |
|
181 if (!parents) |
|
182 goto quit; |
|
183 |
|
184 /* read filenames */ |
|
185 cur = str + 40; |
|
186 end = str + len; |
|
187 |
|
188 while (cur < end - 17) { |
|
189 /* unpack header */ |
|
190 state = *cur; |
|
191 memcpy(decode, cur + 1, 16); |
|
192 mode = ntohl(*(uint32_t *)(decode)); |
|
193 size = ntohl(*(uint32_t *)(decode + 4)); |
|
194 mtime = ntohl(*(uint32_t *)(decode + 8)); |
|
195 flen = ntohl(*(uint32_t *)(decode + 12)); |
|
196 cur += 17; |
|
197 if (cur + flen > end) |
|
198 goto quit; |
|
199 |
|
200 entry = Py_BuildValue("ciii", state, mode, size, mtime); |
|
201 PyObject_GC_UnTrack(entry); /* don't waste time with this */ |
|
202 if (!entry) |
|
203 goto quit; |
|
204 |
|
205 cpos = memchr(cur, 0, flen); |
|
206 if (cpos) { |
|
207 fname = PyString_FromStringAndSize(cur, cpos - cur); |
|
208 cname = PyString_FromStringAndSize(cpos + 1, |
|
209 flen - (cpos - cur) - 1); |
|
210 if (!fname || !cname || |
|
211 PyDict_SetItem(cmap, fname, cname) == -1 || |
|
212 PyDict_SetItem(dmap, fname, entry) == -1) |
|
213 goto quit; |
|
214 Py_DECREF(cname); |
|
215 } else { |
|
216 fname = PyString_FromStringAndSize(cur, flen); |
|
217 if (!fname || |
|
218 PyDict_SetItem(dmap, fname, entry) == -1) |
|
219 goto quit; |
|
220 } |
|
221 cur += flen; |
|
222 Py_DECREF(fname); |
|
223 Py_DECREF(entry); |
|
224 fname = cname = entry = NULL; |
|
225 } |
|
226 |
|
227 ret = parents; |
|
228 Py_INCREF(ret); |
|
229 quit: |
|
230 Py_XDECREF(fname); |
|
231 Py_XDECREF(cname); |
|
232 Py_XDECREF(entry); |
|
233 Py_XDECREF(parents); |
|
234 return ret; |
|
235 } |
|
236 |
136 static char parsers_doc[] = "Efficient content parsing."; |
237 static char parsers_doc[] = "Efficient content parsing."; |
137 |
238 |
138 static PyMethodDef methods[] = { |
239 static PyMethodDef methods[] = { |
139 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, |
240 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, |
|
241 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, |
140 {NULL, NULL} |
242 {NULL, NULL} |
141 }; |
243 }; |
142 |
244 |
143 PyMODINIT_FUNC initparsers(void) |
245 PyMODINIT_FUNC initparsers(void) |
144 { |
246 { |