##// END OF EJS Templates
pathencode: remove unused variable...
Augie Fackler -
r38125:f7a03989 default
parent child Browse files
Show More
@@ -1,765 +1,758 b''
1 1 /*
2 2 pathencode.c - efficient path name encoding
3 3
4 4 Copyright 2012 Facebook
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8 */
9 9
10 10 /*
11 11 * An implementation of the name encoding scheme used by the fncache
12 12 * store. The common case is of a path < 120 bytes long, which is
13 13 * handled either in a single pass with no allocations or two passes
14 14 * with a single allocation. For longer paths, multiple passes are
15 15 * required.
16 16 */
17 17
18 18 #define PY_SSIZE_T_CLEAN
19 19 #include <Python.h>
20 20 #include <assert.h>
21 21 #include <ctype.h>
22 22 #include <stdlib.h>
23 23 #include <string.h>
24 24
25 25 #include "util.h"
26 26
27 27 /* state machine for the fast path */
28 28 enum path_state {
29 29 START, /* first byte of a path component */
30 30 A, /* "AUX" */
31 31 AU,
32 32 THIRD, /* third of a 3-byte sequence, e.g. "AUX", "NUL" */
33 33 C, /* "CON" or "COMn" */
34 34 CO,
35 35 COMLPT, /* "COM" or "LPT" */
36 36 COMLPTn,
37 37 L,
38 38 LP,
39 39 N,
40 40 NU,
41 41 P, /* "PRN" */
42 42 PR,
43 43 LDOT, /* leading '.' */
44 44 DOT, /* '.' in a non-leading position */
45 45 H, /* ".h" */
46 46 HGDI, /* ".hg", ".d", or ".i" */
47 47 SPACE,
48 48 DEFAULT, /* byte of a path component after the first */
49 49 };
50 50
51 51 /* state machine for dir-encoding */
52 52 enum dir_state {
53 53 DDOT,
54 54 DH,
55 55 DHGDI,
56 56 DDEFAULT,
57 57 };
58 58
59 59 static inline int inset(const uint32_t bitset[], char c)
60 60 {
61 61 return bitset[((uint8_t)c) >> 5] & (1 << (((uint8_t)c) & 31));
62 62 }
63 63
64 64 static inline void charcopy(char *dest, Py_ssize_t *destlen, size_t destsize,
65 65 char c)
66 66 {
67 67 if (dest) {
68 68 assert(*destlen < destsize);
69 69 dest[*destlen] = c;
70 70 }
71 71 (*destlen)++;
72 72 }
73 73
74 74 static inline void memcopy(char *dest, Py_ssize_t *destlen, size_t destsize,
75 75 const void *src, Py_ssize_t len)
76 76 {
77 77 if (dest) {
78 78 assert(*destlen + len < destsize);
79 79 memcpy((void *)&dest[*destlen], src, len);
80 80 }
81 81 *destlen += len;
82 82 }
83 83
84 84 static inline void hexencode(char *dest, Py_ssize_t *destlen, size_t destsize,
85 85 uint8_t c)
86 86 {
87 87 static const char hexdigit[] = "0123456789abcdef";
88 88
89 89 charcopy(dest, destlen, destsize, hexdigit[c >> 4]);
90 90 charcopy(dest, destlen, destsize, hexdigit[c & 15]);
91 91 }
92 92
93 93 /* 3-byte escape: tilde followed by two hex digits */
94 94 static inline void escape3(char *dest, Py_ssize_t *destlen, size_t destsize,
95 95 char c)
96 96 {
97 97 charcopy(dest, destlen, destsize, '~');
98 98 hexencode(dest, destlen, destsize, c);
99 99 }
100 100
101 101 static Py_ssize_t _encodedir(char *dest, size_t destsize, const char *src,
102 102 Py_ssize_t len)
103 103 {
104 104 enum dir_state state = DDEFAULT;
105 105 Py_ssize_t i = 0, destlen = 0;
106 106
107 107 while (i < len) {
108 108 switch (state) {
109 109 case DDOT:
110 110 switch (src[i]) {
111 111 case 'd':
112 112 case 'i':
113 113 state = DHGDI;
114 114 charcopy(dest, &destlen, destsize, src[i++]);
115 115 break;
116 116 case 'h':
117 117 state = DH;
118 118 charcopy(dest, &destlen, destsize, src[i++]);
119 119 break;
120 120 default:
121 121 state = DDEFAULT;
122 122 break;
123 123 }
124 124 break;
125 125 case DH:
126 126 if (src[i] == 'g') {
127 127 state = DHGDI;
128 128 charcopy(dest, &destlen, destsize, src[i++]);
129 129 } else
130 130 state = DDEFAULT;
131 131 break;
132 132 case DHGDI:
133 133 if (src[i] == '/') {
134 134 memcopy(dest, &destlen, destsize, ".hg", 3);
135 135 charcopy(dest, &destlen, destsize, src[i++]);
136 136 }
137 137 state = DDEFAULT;
138 138 break;
139 139 case DDEFAULT:
140 140 if (src[i] == '.')
141 141 state = DDOT;
142 142 charcopy(dest, &destlen, destsize, src[i++]);
143 143 break;
144 144 }
145 145 }
146 146
147 147 return destlen;
148 148 }
149 149
150 150 PyObject *encodedir(PyObject *self, PyObject *args)
151 151 {
152 152 Py_ssize_t len, newlen;
153 153 PyObject *pathobj, *newobj;
154 154 char *path;
155 155
156 156 if (!PyArg_ParseTuple(args, "O:encodedir", &pathobj))
157 157 return NULL;
158 158
159 159 if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) {
160 160 PyErr_SetString(PyExc_TypeError, "expected a string");
161 161 return NULL;
162 162 }
163 163
164 164 newlen = len ? _encodedir(NULL, 0, path, len + 1) : 1;
165 165
166 166 if (newlen == len + 1) {
167 167 Py_INCREF(pathobj);
168 168 return pathobj;
169 169 }
170 170
171 171 newobj = PyBytes_FromStringAndSize(NULL, newlen);
172 172
173 173 if (newobj) {
174 174 assert(PyBytes_Check(newobj));
175 175 Py_SIZE(newobj)--;
176 176 _encodedir(PyBytes_AS_STRING(newobj), newlen, path, len + 1);
177 177 }
178 178
179 179 return newobj;
180 180 }
181 181
182 182 static Py_ssize_t _encode(const uint32_t twobytes[8], const uint32_t onebyte[8],
183 183 char *dest, Py_ssize_t destlen, size_t destsize,
184 184 const char *src, Py_ssize_t len, int encodedir)
185 185 {
186 186 enum path_state state = START;
187 187 Py_ssize_t i = 0;
188 188
189 189 /*
190 190 * Python strings end with a zero byte, which we use as a
191 191 * terminal token as they are not valid inside path names.
192 192 */
193 193
194 194 while (i < len) {
195 195 switch (state) {
196 196 case START:
197 197 switch (src[i]) {
198 198 case '/':
199 199 charcopy(dest, &destlen, destsize, src[i++]);
200 200 break;
201 201 case '.':
202 202 state = LDOT;
203 203 escape3(dest, &destlen, destsize, src[i++]);
204 204 break;
205 205 case ' ':
206 206 state = DEFAULT;
207 207 escape3(dest, &destlen, destsize, src[i++]);
208 208 break;
209 209 case 'a':
210 210 state = A;
211 211 charcopy(dest, &destlen, destsize, src[i++]);
212 212 break;
213 213 case 'c':
214 214 state = C;
215 215 charcopy(dest, &destlen, destsize, src[i++]);
216 216 break;
217 217 case 'l':
218 218 state = L;
219 219 charcopy(dest, &destlen, destsize, src[i++]);
220 220 break;
221 221 case 'n':
222 222 state = N;
223 223 charcopy(dest, &destlen, destsize, src[i++]);
224 224 break;
225 225 case 'p':
226 226 state = P;
227 227 charcopy(dest, &destlen, destsize, src[i++]);
228 228 break;
229 229 default:
230 230 state = DEFAULT;
231 231 break;
232 232 }
233 233 break;
234 234 case A:
235 235 if (src[i] == 'u') {
236 236 state = AU;
237 237 charcopy(dest, &destlen, destsize, src[i++]);
238 238 } else
239 239 state = DEFAULT;
240 240 break;
241 241 case AU:
242 242 if (src[i] == 'x') {
243 243 state = THIRD;
244 244 i++;
245 245 } else
246 246 state = DEFAULT;
247 247 break;
248 248 case THIRD:
249 249 state = DEFAULT;
250 250 switch (src[i]) {
251 251 case '.':
252 252 case '/':
253 253 case '\0':
254 254 escape3(dest, &destlen, destsize, src[i - 1]);
255 255 break;
256 256 default:
257 257 i--;
258 258 break;
259 259 }
260 260 break;
261 261 case C:
262 262 if (src[i] == 'o') {
263 263 state = CO;
264 264 charcopy(dest, &destlen, destsize, src[i++]);
265 265 } else
266 266 state = DEFAULT;
267 267 break;
268 268 case CO:
269 269 if (src[i] == 'm') {
270 270 state = COMLPT;
271 271 i++;
272 272 } else if (src[i] == 'n') {
273 273 state = THIRD;
274 274 i++;
275 275 } else
276 276 state = DEFAULT;
277 277 break;
278 278 case COMLPT:
279 279 switch (src[i]) {
280 280 case '1':
281 281 case '2':
282 282 case '3':
283 283 case '4':
284 284 case '5':
285 285 case '6':
286 286 case '7':
287 287 case '8':
288 288 case '9':
289 289 state = COMLPTn;
290 290 i++;
291 291 break;
292 292 default:
293 293 state = DEFAULT;
294 294 charcopy(dest, &destlen, destsize, src[i - 1]);
295 295 break;
296 296 }
297 297 break;
298 298 case COMLPTn:
299 299 state = DEFAULT;
300 300 switch (src[i]) {
301 301 case '.':
302 302 case '/':
303 303 case '\0':
304 304 escape3(dest, &destlen, destsize, src[i - 2]);
305 305 charcopy(dest, &destlen, destsize, src[i - 1]);
306 306 break;
307 307 default:
308 308 memcopy(dest, &destlen, destsize, &src[i - 2],
309 309 2);
310 310 break;
311 311 }
312 312 break;
313 313 case L:
314 314 if (src[i] == 'p') {
315 315 state = LP;
316 316 charcopy(dest, &destlen, destsize, src[i++]);
317 317 } else
318 318 state = DEFAULT;
319 319 break;
320 320 case LP:
321 321 if (src[i] == 't') {
322 322 state = COMLPT;
323 323 i++;
324 324 } else
325 325 state = DEFAULT;
326 326 break;
327 327 case N:
328 328 if (src[i] == 'u') {
329 329 state = NU;
330 330 charcopy(dest, &destlen, destsize, src[i++]);
331 331 } else
332 332 state = DEFAULT;
333 333 break;
334 334 case NU:
335 335 if (src[i] == 'l') {
336 336 state = THIRD;
337 337 i++;
338 338 } else
339 339 state = DEFAULT;
340 340 break;
341 341 case P:
342 342 if (src[i] == 'r') {
343 343 state = PR;
344 344 charcopy(dest, &destlen, destsize, src[i++]);
345 345 } else
346 346 state = DEFAULT;
347 347 break;
348 348 case PR:
349 349 if (src[i] == 'n') {
350 350 state = THIRD;
351 351 i++;
352 352 } else
353 353 state = DEFAULT;
354 354 break;
355 355 case LDOT:
356 356 switch (src[i]) {
357 357 case 'd':
358 358 case 'i':
359 359 state = HGDI;
360 360 charcopy(dest, &destlen, destsize, src[i++]);
361 361 break;
362 362 case 'h':
363 363 state = H;
364 364 charcopy(dest, &destlen, destsize, src[i++]);
365 365 break;
366 366 default:
367 367 state = DEFAULT;
368 368 break;
369 369 }
370 370 break;
371 371 case DOT:
372 372 switch (src[i]) {
373 373 case '/':
374 374 case '\0':
375 375 state = START;
376 376 memcopy(dest, &destlen, destsize, "~2e", 3);
377 377 charcopy(dest, &destlen, destsize, src[i++]);
378 378 break;
379 379 case 'd':
380 380 case 'i':
381 381 state = HGDI;
382 382 charcopy(dest, &destlen, destsize, '.');
383 383 charcopy(dest, &destlen, destsize, src[i++]);
384 384 break;
385 385 case 'h':
386 386 state = H;
387 387 memcopy(dest, &destlen, destsize, ".h", 2);
388 388 i++;
389 389 break;
390 390 default:
391 391 state = DEFAULT;
392 392 charcopy(dest, &destlen, destsize, '.');
393 393 break;
394 394 }
395 395 break;
396 396 case H:
397 397 if (src[i] == 'g') {
398 398 state = HGDI;
399 399 charcopy(dest, &destlen, destsize, src[i++]);
400 400 } else
401 401 state = DEFAULT;
402 402 break;
403 403 case HGDI:
404 404 if (src[i] == '/') {
405 405 state = START;
406 406 if (encodedir)
407 407 memcopy(dest, &destlen, destsize, ".hg",
408 408 3);
409 409 charcopy(dest, &destlen, destsize, src[i++]);
410 410 } else
411 411 state = DEFAULT;
412 412 break;
413 413 case SPACE:
414 414 switch (src[i]) {
415 415 case '/':
416 416 case '\0':
417 417 state = START;
418 418 memcopy(dest, &destlen, destsize, "~20", 3);
419 419 charcopy(dest, &destlen, destsize, src[i++]);
420 420 break;
421 421 default:
422 422 state = DEFAULT;
423 423 charcopy(dest, &destlen, destsize, ' ');
424 424 break;
425 425 }
426 426 break;
427 427 case DEFAULT:
428 428 while (inset(onebyte, src[i])) {
429 429 charcopy(dest, &destlen, destsize, src[i++]);
430 430 if (i == len)
431 431 goto done;
432 432 }
433 433 switch (src[i]) {
434 434 case '.':
435 435 state = DOT;
436 436 i++;
437 437 break;
438 438 case ' ':
439 439 state = SPACE;
440 440 i++;
441 441 break;
442 442 case '/':
443 443 state = START;
444 444 charcopy(dest, &destlen, destsize, '/');
445 445 i++;
446 446 break;
447 447 default:
448 448 if (inset(onebyte, src[i])) {
449 449 do {
450 450 charcopy(dest, &destlen,
451 451 destsize, src[i++]);
452 452 } while (i < len &&
453 453 inset(onebyte, src[i]));
454 454 } else if (inset(twobytes, src[i])) {
455 455 char c = src[i++];
456 456 charcopy(dest, &destlen, destsize, '_');
457 457 charcopy(dest, &destlen, destsize,
458 458 c == '_' ? '_' : c + 32);
459 459 } else
460 460 escape3(dest, &destlen, destsize,
461 461 src[i++]);
462 462 break;
463 463 }
464 464 break;
465 465 }
466 466 }
467 467 done:
468 468 return destlen;
469 469 }
470 470
471 471 static Py_ssize_t basicencode(char *dest, size_t destsize, const char *src,
472 472 Py_ssize_t len)
473 473 {
474 474 static const uint32_t twobytes[8] = {0, 0, 0x87fffffe};
475 475
476 476 static const uint32_t onebyte[8] = {
477 477 1, 0x2bff3bfa, 0x68000001, 0x2fffffff,
478 478 };
479 479
480 480 Py_ssize_t destlen = 0;
481 481
482 482 return _encode(twobytes, onebyte, dest, destlen, destsize, src, len, 1);
483 483 }
484 484
485 485 static const Py_ssize_t maxstorepathlen = 120;
486 486
487 487 static Py_ssize_t _lowerencode(char *dest, size_t destsize, const char *src,
488 488 Py_ssize_t len)
489 489 {
490 490 static const uint32_t onebyte[8] = {1, 0x2bfffbfb, 0xe8000001,
491 491 0x2fffffff};
492 492
493 493 static const uint32_t lower[8] = {0, 0, 0x7fffffe};
494 494
495 495 Py_ssize_t i, destlen = 0;
496 496
497 497 for (i = 0; i < len; i++) {
498 498 if (inset(onebyte, src[i]))
499 499 charcopy(dest, &destlen, destsize, src[i]);
500 500 else if (inset(lower, src[i]))
501 501 charcopy(dest, &destlen, destsize, src[i] + 32);
502 502 else
503 503 escape3(dest, &destlen, destsize, src[i]);
504 504 }
505 505
506 506 return destlen;
507 507 }
508 508
509 509 PyObject *lowerencode(PyObject *self, PyObject *args)
510 510 {
511 511 char *path;
512 512 Py_ssize_t len, newlen;
513 513 PyObject *ret;
514 514
515 515 if (!PyArg_ParseTuple(args, PY23("s#:lowerencode", "y#:lowerencode"),
516 516 &path, &len))
517 517 return NULL;
518 518
519 519 newlen = _lowerencode(NULL, 0, path, len);
520 520 ret = PyBytes_FromStringAndSize(NULL, newlen);
521 521 if (ret)
522 522 _lowerencode(PyBytes_AS_STRING(ret), newlen, path, len);
523 523
524 524 return ret;
525 525 }
526 526
527 527 /* See store.py:_auxencode for a description. */
528 528 static Py_ssize_t auxencode(char *dest, size_t destsize, const char *src,
529 529 Py_ssize_t len)
530 530 {
531 531 static const uint32_t twobytes[8];
532 532
533 533 static const uint32_t onebyte[8] = {
534 534 ~0U, 0xffff3ffe, ~0U, ~0U, ~0U, ~0U, ~0U, ~0U,
535 535 };
536 536
537 537 return _encode(twobytes, onebyte, dest, 0, destsize, src, len, 0);
538 538 }
539 539
540 540 static PyObject *hashmangle(const char *src, Py_ssize_t len, const char sha[20])
541 541 {
542 542 static const Py_ssize_t dirprefixlen = 8;
543 543 static const Py_ssize_t maxshortdirslen = 68;
544 544 char *dest;
545 545 PyObject *ret;
546 546
547 547 Py_ssize_t i, d, p, lastslash = len - 1, lastdot = -1;
548 548 Py_ssize_t destsize, destlen = 0, slop, used;
549 549
550 550 while (lastslash >= 0 && src[lastslash] != '/') {
551 551 if (src[lastslash] == '.' && lastdot == -1)
552 552 lastdot = lastslash;
553 553 lastslash--;
554 554 }
555 555
556 556 #if 0
557 557 /* All paths should end in a suffix of ".i" or ".d".
558 558 Unfortunately, the file names in test-hybridencode.py
559 559 violate this rule. */
560 560 if (lastdot != len - 3) {
561 561 PyErr_SetString(PyExc_ValueError,
562 562 "suffix missing or wrong length");
563 563 return NULL;
564 564 }
565 565 #endif
566 566
567 567 /* If src contains a suffix, we will append it to the end of
568 568 the new string, so make room. */
569 569 destsize = 120;
570 570 if (lastdot >= 0)
571 571 destsize += len - lastdot - 1;
572 572
573 573 ret = PyBytes_FromStringAndSize(NULL, destsize);
574 574 if (ret == NULL)
575 575 return NULL;
576 576
577 577 dest = PyBytes_AS_STRING(ret);
578 578 memcopy(dest, &destlen, destsize, "dh/", 3);
579 579
580 580 /* Copy up to dirprefixlen bytes of each path component, up to
581 581 a limit of maxshortdirslen bytes. */
582 582 for (i = d = p = 0; i < lastslash; i++, p++) {
583 583 if (src[i] == '/') {
584 584 char d = dest[destlen - 1];
585 585 /* After truncation, a directory name may end
586 586 in a space or dot, which are unportable. */
587 587 if (d == '.' || d == ' ')
588 588 dest[destlen - 1] = '_';
589 589 /* The + 3 is to account for "dh/" in the beginning */
590 590 if (destlen > maxshortdirslen + 3)
591 591 break;
592 592 charcopy(dest, &destlen, destsize, src[i]);
593 593 p = -1;
594 594 } else if (p < dirprefixlen)
595 595 charcopy(dest, &destlen, destsize, src[i]);
596 596 }
597 597
598 598 /* Rewind to just before the last slash copied. */
599 599 if (destlen > maxshortdirslen + 3)
600 600 do {
601 601 destlen--;
602 602 } while (destlen > 0 && dest[destlen] != '/');
603 603
604 604 if (destlen > 3) {
605 605 if (lastslash > 0) {
606 606 char d = dest[destlen - 1];
607 607 /* The last directory component may be
608 608 truncated, so make it safe. */
609 609 if (d == '.' || d == ' ')
610 610 dest[destlen - 1] = '_';
611 611 }
612 612
613 613 charcopy(dest, &destlen, destsize, '/');
614 614 }
615 615
616 616 /* Add a prefix of the original file's name. Its length
617 617 depends on the number of bytes left after accounting for
618 618 hash and suffix. */
619 619 used = destlen + 40;
620 620 if (lastdot >= 0)
621 621 used += len - lastdot - 1;
622 622 slop = maxstorepathlen - used;
623 623 if (slop > 0) {
624 624 Py_ssize_t basenamelen =
625 625 lastslash >= 0 ? len - lastslash - 2 : len - 1;
626 626
627 627 if (basenamelen > slop)
628 628 basenamelen = slop;
629 629 if (basenamelen > 0)
630 630 memcopy(dest, &destlen, destsize, &src[lastslash + 1],
631 631 basenamelen);
632 632 }
633 633
634 634 /* Add hash and suffix. */
635 635 for (i = 0; i < 20; i++)
636 636 hexencode(dest, &destlen, destsize, sha[i]);
637 637
638 638 if (lastdot >= 0)
639 639 memcopy(dest, &destlen, destsize, &src[lastdot],
640 640 len - lastdot - 1);
641 641
642 642 assert(PyBytes_Check(ret));
643 643 Py_SIZE(ret) = destlen;
644 644
645 645 return ret;
646 646 }
647 647
648 648 /*
649 649 * Avoiding a trip through Python would improve performance by 50%,
650 650 * but we don't encounter enough long names to be worth the code.
651 651 */
652 652 static int sha1hash(char hash[20], const char *str, Py_ssize_t len)
653 653 {
654 654 static PyObject *shafunc;
655 655 PyObject *shaobj, *hashobj;
656 656
657 657 if (shafunc == NULL) {
658 PyObject *hashlib, *name = PyBytes_FromString("hashlib");
659
660 if (name == NULL)
661 return -1;
662
663 hashlib = PyImport_ImportModule("hashlib");
664 Py_DECREF(name);
665
658 PyObject *hashlib = PyImport_ImportModule("hashlib");
666 659 if (hashlib == NULL) {
667 660 PyErr_SetString(PyExc_ImportError,
668 661 "pathencode failed to find hashlib");
669 662 return -1;
670 663 }
671 664 shafunc = PyObject_GetAttrString(hashlib, "sha1");
672 665 Py_DECREF(hashlib);
673 666
674 667 if (shafunc == NULL) {
675 668 PyErr_SetString(PyExc_AttributeError,
676 669 "module 'hashlib' has no "
677 670 "attribute 'sha1' in pathencode");
678 671 return -1;
679 672 }
680 673 }
681 674
682 675 shaobj = PyObject_CallFunction(shafunc, PY23("s#", "y#"), str, len);
683 676
684 677 if (shaobj == NULL)
685 678 return -1;
686 679
687 680 hashobj = PyObject_CallMethod(shaobj, "digest", "");
688 681 Py_DECREF(shaobj);
689 682 if (hashobj == NULL)
690 683 return -1;
691 684
692 685 if (!PyBytes_Check(hashobj) || PyBytes_GET_SIZE(hashobj) != 20) {
693 686 PyErr_SetString(PyExc_TypeError,
694 687 "result of digest is not a 20-byte hash");
695 688 Py_DECREF(hashobj);
696 689 return -1;
697 690 }
698 691
699 692 memcpy(hash, PyBytes_AS_STRING(hashobj), 20);
700 693 Py_DECREF(hashobj);
701 694 return 0;
702 695 }
703 696
704 697 #define MAXENCODE 4096 * 4
705 698
706 699 static PyObject *hashencode(const char *src, Py_ssize_t len)
707 700 {
708 701 char dired[MAXENCODE];
709 702 char lowered[MAXENCODE];
710 703 char auxed[MAXENCODE];
711 704 Py_ssize_t dirlen, lowerlen, auxlen, baselen;
712 705 char sha[20];
713 706
714 707 baselen = (len - 5) * 3;
715 708 if (baselen >= MAXENCODE) {
716 709 PyErr_SetString(PyExc_ValueError, "string too long");
717 710 return NULL;
718 711 }
719 712
720 713 dirlen = _encodedir(dired, baselen, src, len);
721 714 if (sha1hash(sha, dired, dirlen - 1) == -1)
722 715 return NULL;
723 716 lowerlen = _lowerencode(lowered, baselen, dired + 5, dirlen - 5);
724 717 auxlen = auxencode(auxed, baselen, lowered, lowerlen);
725 718 return hashmangle(auxed, auxlen, sha);
726 719 }
727 720
728 721 PyObject *pathencode(PyObject *self, PyObject *args)
729 722 {
730 723 Py_ssize_t len, newlen;
731 724 PyObject *pathobj, *newobj;
732 725 char *path;
733 726
734 727 if (!PyArg_ParseTuple(args, "O:pathencode", &pathobj))
735 728 return NULL;
736 729
737 730 if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) {
738 731 PyErr_SetString(PyExc_TypeError, "expected a string");
739 732 return NULL;
740 733 }
741 734
742 735 if (len > maxstorepathlen)
743 736 newlen = maxstorepathlen + 2;
744 737 else
745 738 newlen = len ? basicencode(NULL, 0, path, len + 1) : 1;
746 739
747 740 if (newlen <= maxstorepathlen + 1) {
748 741 if (newlen == len + 1) {
749 742 Py_INCREF(pathobj);
750 743 return pathobj;
751 744 }
752 745
753 746 newobj = PyBytes_FromStringAndSize(NULL, newlen);
754 747
755 748 if (newobj) {
756 749 assert(PyBytes_Check(newobj));
757 750 Py_SIZE(newobj)--;
758 751 basicencode(PyBytes_AS_STRING(newobj), newlen, path,
759 752 len + 1);
760 753 }
761 754 } else
762 755 newobj = hashencode(path, len + 1);
763 756
764 757 return newobj;
765 758 }
General Comments 0
You need to be logged in to leave comments. Login now