bytevectors
[software/python-on-guile.git] / modules / language / python / str.scm
1 (define-module (language python str)
2 #:use-module (oop goops)
3 #:use-module (oop pf-objects)
4 #:use-module (ice-9 match)
5 #:use-module (rnrs bytevectors)
6 #:use-module (system foreign)
7 #:use-module (language python string)
8 #:use-module (language python for)
9 #:use-module (language python try)
10 #:use-module (language python exceptions)
11 #:use-module (language python list)
12 #:use-module (language python hash)
13 #:export (<py-str> pystr-listing str str->bytevector))
14
15 (define (str->bytevector x) (slot-ref x 'str))
16 (define-syntax-rule (aif it p x y) (let ((it p)) (if it x y)))
17
18 (define b-ref bytevector-u8-ref)
19 (define b-set! bytevector-u8-set!)
20 (define b-make make-bytevector)
21 (define b-len bytevector-length)
22
23 (define-class <py-str> () str)
24
25 (define (b-char x)
26 (cond
27 ((char? x)
28 (ch-find x))
29 ((string? x)
30 (ch-find (string-ref x 0)))
31 (else
32 x)))
33
34 (define-python-class str (<py-str>)
35 (define __init__
36 (case-lambda
37 ((self s)
38 (cond
39 ((is-a? s <string>)
40 (let* ((n (string-length s))
41 (str (b-make n)))
42 (let lp ((i 0))
43 (if (< i n)
44 (begin
45 (b-set! str i (ch-find (string-ref s i)))
46 (lp (+ i 1)))))
47 (slot-set! self 'str str)))
48 ((is-a? s <py-string>)
49 (__init__ self (slot-ref s 'str)))
50 ((is-a? s <py-str>)
51 (slot-set! self 'str (slot-ref s 'str)))
52 ((is-a? s <bytevector>)
53 (slot-set! self 'str s))
54 (else
55 (for ((x : s)) ((r '()))
56 (cons (b-char x) r)
57
58 #:final
59 (let* ((n (length r))
60 (str (b-make n)))
61 (let lp ((i (- n 1)) (r r))
62 (if (>= i 0)
63 (begin
64 (b-set! str i (car r))
65 (lp (- i 1) (cdr r)))
66 (slot-set! self 'str str)))))))))))
67
68 (define-syntax-rule (define-py (f o . u) code ...)
69 (begin
70 (define-method (f (o <bytevector>) . u) code ...)
71 (define-method (f (o <py-str>) . l) (apply f (slot-ref o 'str) l))))
72
73 (define-method (write (b <py-str>) . l)
74 (apply write (b->string (slot-ref b 'str)) l))
75
76 (define dynlink (dynamic-link))
77
78 (define stringn
79 (pointer->procedure
80 '*
81 (dynamic-func "scm_from_locale_stringn" dynlink)
82 (list '* size_t)))
83
84 (define ch->i (make-hash-table))
85
86 (define (re-eval ch)
87 (let lp ((i 0))
88 (if (< i 256)
89 (if (eq? ch (chf i))
90 (begin
91 (hash-set! ch->i ch i)
92 (lp (+ i 1)))
93 (lp (+ i 1)))
94 (hash-ref ch->i ch))))
95
96 (define (ch-find ch)
97 (aif it (hash-ref ch->i ch #f)
98 (if (eq? ch (chf it))
99 it
100 (re-eval ch))
101 (re-eval ch)))
102
103 (define (chf ch)
104 (let ((str (pointer->scm
105 (stringn
106 (bytevector->pointer
107 (b-make 1 ch))
108 1))))
109 (if (= (string-length str) 1)
110 (string-ref str 0)
111 (chf 0))))
112
113 (define (b->string b)
114 (pointer->scm
115 (stringn (bytevector->pointer b) (b-len b))))
116
117 (define-py (py-capitalize s)
118 (let* ((n (b-len s))
119 (w (b-make n)))
120 (let lp ((i 0) (first? #t))
121 (if (< i n)
122 (let* ((x (b-ref s i))
123 (ch (chf x)))
124 (define (f first?)
125 (b-set! w i x)
126 (lp (+ i 1) first?))
127
128 (if (and first? (char-alphabetic? ch))
129 (aif it (ch-find (char-upcase ch))
130 (begin
131 (b-set! w i it)
132 (lp (+ i 1) #f))
133 (f #t))
134 (f #f)))
135 (str w)))))
136
137 (define-py (py-center o w . l)
138 (let* ((ws (if (pair? l)
139 (ch-find (b-ref (car l) 0))
140 (ch-find #\space)))
141 (n (b-len o))
142 (w (if (< w n) n w))
143 (d (- w n))
144 (e (floor-quotient (- w n) 2))
145 (s (b-make w (ch-find #\space))))
146 (let lp ((i 0) (j e))
147 (if (< i n)
148 (begin
149 (b-set! s j (b-ref o i))
150 (lp (+ i 1) (+ j 1)))))
151 (str s)))
152
153 ;;;py-decode
154 ;;;py-encode
155
156 (define-py (py-endswith o suff . l)
157 (let* ((suff (slot-ref (str suff) 'str))
158 (n (b-len o))
159 (ns (b-len suff))
160 (f (lambda (x) (< x 0) (+ n x) x)))
161 (call-with-values (lambda ()
162 (match l
163 (() (values 0 n ))
164 ((x) (values (f x) n ))
165 ((x y) (values (f x) (f y)))))
166 (lambda (start end)
167 (let lp ((i (- n ns)) (j 0))
168 (if (< i start)
169 (lp (+ i 1) (+ j 1))
170 (if (>= i end)
171 #t
172 (and
173 (eq? (b-ref o i) (b-ref suff j))
174 (lp (+ i 1) (+ j 1))))))))))
175
176 (define-py (py-startswith o pre . l)
177 (let* ((pre (slot-ref (str pre) 'str))
178 (n (b-len o))
179 (ns (b-len pre))
180 (f (lambda (x) (< x 0) (+ n x) x)))
181 (call-with-values (lambda ()
182 (match l
183 (() (values 0 n ))
184 ((x) (values (f x) n ))
185 ((x y) (values (f x) (f y)))))
186 (lambda (start end)
187 (let lp ((i 0))
188 (cond
189 ((or (>= i end)
190 (>= i ns))
191 #t)
192 ((< i start)
193 (lp (+ i 1)))
194 (else
195 (and
196 (eq? (b-ref o i) (b-ref pre i))
197 (lp (+ i 1))))))))))
198
199
200 (define-py (py-expandtabs s . l)
201 (let* ((tabsize (match l (() 8) ((x) x)))
202 (ct (ch-find #\tab))
203 (cs (ch-find #\space))
204 (n (b-len s)))
205 (let lp ((i 0) (r '()))
206 (if (< i n)
207 (let ((x (b-ref s i)))
208 (if (eq? x ct)
209 (let lp2 ((j 0) (r r))
210 (if (< j tabsize)
211 (lp2 (+ j 1) (cons cs r))
212 (lp (+ i 1) r)))
213 (lp (+ i 1) (cons x r))))
214 (str (reverse r))))))
215
216 (define (b-contains s sub start end)
217 (define nsub (b-len sub))
218 (define (match i)
219 (let lp ((i i) (j 0))
220 (if (and (< j nsub) (< i end))
221 (if (eq? (b-ref s i) (b-ref sub j))
222 (lp (+ i 1) (+ j 1))
223 #f)
224 #t)))
225
226 (let lp ((i (max start 0)))
227 (if (< i end)
228 (if (match i)
229 i
230 (lp (+ i 1)))
231 #f)))
232
233 (define-py (py-find s sub . l)
234 (let* ((n (b-len s))
235 (f (lambda (x) (< x 0) (+ n x) x)))
236 (call-with-values (lambda ()
237 (match l
238 (() (values 0 n ))
239 ((x) (values (f x) n ))
240 ((x y) (values (f x) (f y)))))
241 (lambda (start end)
242 (let ((sub (slot-ref (str sub) 'str)))
243 (aif it (b-contains s sub start end)
244 it
245 -1))))))
246
247 (define (b-reverse s)
248 (if (is-a? s (<py-str>))
249 (b-reverse (slot-ref s 'str))
250 (let* ((n (b-len s))
251 (r (b-make n)))
252 (let lp ((i 0) (j (- n 1)))
253 (if (< i n)
254 (begin
255 (b-set! r j (b-ref s i))
256 (lp (+ i 1) (- j 1)))
257 r)))))
258
259
260 (define-py (py-rfind s sub . l)
261 (let* ((sub (slot-ref (str sub) 'str))
262 (n (b-len s))
263 (s (b-reverse s))
264 (sub (b-reverse sub))
265 (f (lambda (x) (< x 0) (+ n x) x)))
266 (call-with-values (lambda ()
267 (match l
268 (() (values 0 n ))
269 ((x) (values (f x) n ))
270 ((x y) (values (f x) (f y)))))
271 (lambda (start end)
272 (aif it (b-contains s sub start end)
273 (- n it (b-len sub))
274 -1)))))
275
276 #|
277 (define i (f-list #:i (mk-token (f+ (f-reg! "[0-9]")))))
278 (define s (f-list #:s (mk-token (f+ (f-not! (f-tag "}"))))))
279 (define e (f-list #:e (f-and (f-tag "}") f-true)))
280 (define tagbody (f-or! e i s))
281
282 (define tag (f-seq "{" tagbody "}"))
283 (define nontag (f-list #:str (mk-token (f+ (f-or! (f-tag "{{")
284 (f-not! tag))))))
285 (define e (ff* (f-or! tag nontag)))
286
287 (define (compile x args kwargs)
288 (let lp ((l x) (r '()) (u '()) (i 0))
289 (match l
290 (((#:str x) . l)
291 (lp l (cons x r) u i))
292 (((#:i x) . l)
293 (lp l (cons "~a" r) (cons (list-ref args (string->number x)) u) i))
294 (((#:s x) . l)
295 (lp l (cons "~a" r) (cons (hash-ref kwargs x None) u) i))
296 (((#:e) . l)
297 (lp l (cons "~a" r) (cons (list-ref args i) u) (+ i 1)))
298 (()
299 (apply format #f (string-join (reverse r) "") (reverse u))))))
300
301 (define-py (py-format format s . l)
302 (call-with-values
303 (lambda ()
304 (let lp ((l l) (args '()) (kwargs (make-hash-table)))
305 (match l
306 (((? keyword? key) x . l)
307 (hash-set! kwargs (symbol->string (keyword->symbol key)) x)
308 (lp l args kwargs))
309 ((x . l)
310 (lp l (cons x args) kwargs))
311 (()
312 (values (reverse args) kwargs)))))
313 (lambda (args kwargs)
314 (compile (parse s e) args kwargs))))
315 |#
316
317 (define-syntax-rule (mk-is py-isalnum x ...)
318 (define-py (py-isalnum s)
319 (let ((n (b-len s)))
320 (let lp ((i 0))
321 (if (< i n)
322 (let ((ch (chf (b-ref s i))))
323 (if (or (x ch) ...)
324 (lp (+ i 1))
325 #f))
326 #t)))))
327
328 (mk-is py-isalnum char-alphabetic? char-numeric?)
329 (mk-is py-isalpha char-alphabetic?)
330 (mk-is py-isdigit char-numeric?)
331 (mk-is py-islower char-lower-case?)
332 (mk-is py-isspace char-whitespace?)
333 (mk-is py-isupper char-upper-case?)
334
335
336 (define-py (py-istitle s)
337 (let ((n (b-len s)))
338 (if ((> n 0))
339 (let lp ((i 0) (space? #t))
340 (if (< i n)
341 (let ((ch (chf (b-ref s i))))
342 (if space?
343 (cond
344 ((char-whitespace? ch)
345 (lp (+ i 1) #t))
346 ((char-upper-case? ch)
347 (lp (+ i 1) #f))
348 (else
349 #f))
350 (cond
351 ((char-whitespace? ch)
352 (lp (+ i 1) #t))
353 ((char-upper-case? ch)
354 #f)
355 ((char-lower-case? ch)
356 (lp (+ i 1) #f))
357 (else
358 #f))))
359 #t))
360 #f)))
361
362 (define (b-join l s)
363 (let* ((ns (b-len s))
364 (l (pk (map (lambda (x) (slot-ref (str x) 'str)) l)))
365 (n (let lp ((l l) (n 0))
366 (if (pair? l)
367 (let ((x (car l))
368 (l (cdr l)))
369 (lp l (+ n (b-len x) (if (pair? l) ns 0))))
370 n)))
371 (r (b-make n)))
372 (let lp ((l l) (i 0))
373 (if (pair? l)
374 (let* ((x (car l))
375 (n (b-len x))
376 (l (cdr l)))
377 (let lp2 ((j 0) (i i))
378 (if (< j n)
379 (begin
380 (b-set! r i (b-ref x j))
381 (lp2 (+ j 1) (+ i 1)))
382 (if (pair? l)
383 (let lp3 ((j 0) (i i))
384 (if (< j ns)
385 (begin
386 (b-set! r i (b-ref s j))
387 (lp3 (+ j 1) (+ i 1)))
388 (lp l i)))
389 (lp l i)))))
390 (str r)))))
391
392 (define-py (py-join s iterator)
393 (b-join (to-list iterator) s))
394
395 (define-py (pylist-slice s n1 n2 n3)
396 (define N (b-len s))
397 (define (f n) (if (< n 0) (+ N n) n))
398
399 (let* ((n1 (f (if (eq? n1 None) 0 n1)))
400 (n2 (f (if (eq? n2 None) N n2)))
401 (n3 (f (if (eq? n3 None) 1 n3)))
402 (r (b-make (floor-quotient (+ 1 (abs (- n2 n1))) n3))))
403 (let lp ((i n1) (j 0))
404 (if (< i n3)
405 (begin
406 (b-set! r j (b-ref s i))
407 (lp (+ i n3) (+ j 1)))
408 (str r)))))
409
410
411 (define-py (py-ljust s width . l)
412 (let* ((n (b-len s))
413 (ch (match l
414 ((x)
415 (b-char x))
416 (()
417 (b-char #\space)))))
418 (if (< width n)
419 (pylist-slice s 0 width 1)
420 (let ((ret (b-make width ch)))
421 (let lp ((i 0))
422 (if (< i n)
423 (begin
424 (b-set! ret i (b-ref s i))
425 (lp (+ i 1)))
426 (str ret)))))))
427
428 (define-py (py-rjust s width . l)
429 (let* ((n (b-len s))
430 (ch (match l
431 ((x)
432 (b-char x))
433 (()
434 (b-char #\space)))))
435 (if (< width n)
436 (pylist-slice s (- width) (len s) 1)
437 (let ((ret (b-make width ch)))
438 (let lp ((i 0) (j (- width n)))
439 (if (< i n)
440 (begin
441 (b-set! ret j (b-ref s i))
442 (lp (+ i 1) (+ j 1)))
443 (str ret)))))))
444
445
446 (define-py (py-lower s)
447 (let* ((n (b-len s))
448 (r (b-make n)))
449 (let lp ((i 0))
450 (if (< i n)
451 (let* ((x (b-ref s i))
452 (ch (chf x)))
453 (b-set! r i (if (char-upper-case? ch)
454 (ch-find (char-downcase ch))
455 x))
456 (lp (+ i 1)))
457 (str r)))))
458
459 (define-py (py-upper s)
460 (let* ((n (b-len s))
461 (r (b-make n)))
462 (let lp ((i 0))
463 (if (< i n)
464 (let* ((x (b-ref s i))
465 (ch (chf x)))
466 (b-set! r i (if (char-lower-case? ch)
467 (ch-find (char-upcase ch))
468 x))
469 (lp (+ i 1)))
470 (str r)))))
471
472 (define-py (py-swapcase s)
473 (let* ((n (b-len s))
474 (r (b-make n)))
475 (let lp ((i 0))
476 (if (< i n)
477 (let* ((x (b-ref s i))
478 (ch (chf x)))
479 (b-set! r i (cond
480 ((char-lower-case? ch)
481 (ch-find (char-upcase ch)))
482 ((char-upper-case? ch)
483 (ch-find (char-downcase ch)))
484 (else
485 x)))
486 (lp (+ i 1)))
487 (str r)))))
488
489 (define b-trim
490 (case-lambda
491 ((s)
492 (b-trim s (lambda (ch x) (char-whitespace? ch))))
493 ((s p)
494 (let ((n (b-len s)))
495 (let lp ((i 0) (r '()) (first? #t))
496 (if (< i n)
497 (let ((x (b-ref s i)))
498 (if first?
499 (if (p (chf x) x)
500 (lp (+ i 1) r #t)
501 (lp (+ i 1) (cons x r) #f))
502 (lp (+ i 1) (cons x r) #f)))
503 (str (reverse r))))))))
504
505 (define b-rtrim
506 (case-lambda
507 ((s)
508 (b-rtrim s (lambda (ch x) (char-whitespace? ch))))
509 ((s p)
510 (let ((n (b-len s)))
511 (let lp ((i (- n 1)) (r '()) (first? #t))
512 (if (>= i 0)
513 (let ((x (b-ref s i)))
514 (if first?
515 (if (p (chf x) x)
516 (lp (- i 1) r #t)
517 (lp (- i 1) (cons x r) #f))
518 (lp (- i 1) (cons x r) #f)))
519 (str r)))))))
520
521 (define-py (py-lstrip s . l)
522 (match l
523 (()
524 (b-trim s))
525 ((x)
526 (let ((l (map b-char (to-list x))))
527 (b-trim s (lambda (ch x) (member x l)))))))
528
529 (define-py (py-rstrip s . l)
530 (match l
531 (()
532 (b-rtrim s))
533 ((x)
534 (let ((l (map b-char (to-list x))))
535 (b-rtrim s (lambda (ch x) (member x l)))))))
536
537
538 (define-py (py-partition s sep)
539 (let* ((sep (slot-ref (str sep) 'str))
540 (n (b-len s))
541 (m (b-len sep)))
542 (define (test i)
543 (let lp ((i i) (j 0))
544 (if (< i n)
545 (if (< j m)
546 (if (eq? (b-ref s i) (b-ref sep j))
547 (lp (+ i 1) (+ j 1))
548 #f)
549 #t)
550 #f)))
551 (let lp ((i 0))
552 (if (< i n)
553 (if (test i)
554 (list (pylist-slice s 0 i) sep (pylist-slice s (+ i m) n))
555 (lp (+ i 1)))
556 (list s "" "")))))
557
558 (define-py (py-rpartition ss ssep)
559 (let* ((ssep (slot-ref (str ssep) 'str))
560 (s (b-reverse ss))
561 (sep (b-reverse ssep))
562 (n (b-len s))
563 (m (b-len sep)))
564 (define (test i)
565 (let lp ((i i) (j 0))
566 (if (< i n)
567 (if (< j m)
568 (if (eq? (b-ref s i) (b-ref sep j))
569 (lp (+ i 1) (+ j 1))
570 #f)
571 #t)
572 #f)))
573 (let lp ((i 0))
574 (if (< i n)
575 (if (test i)
576 (list (str
577 (b-reverse
578 (pylist-slice s (+ i m) n)))
579 ssep
580 (str
581 (b-reverse
582 (pylist-slice s 0 i))))
583 (lp (+ i 1)))
584 (list "" "" s)))))
585
586 (define-py (py-replace s old new . l)
587 (let ((n (match l (() #f) ((n . _) n))))
588 (b-join
589 (reverse
590 (let lp ((s s) (r '()))
591 (let ((l (py-partition s old)))
592 (if (equal? (cadr l) "")
593 (cons s r)
594 (lp (list-ref l 2) (cons (car l) r))))))
595 new)))
596
597 (define-py (py-strip s . l)
598 (apply py-rstrip (apply py-lstrip s l) l))
599
600 (define-py (pylist-index o val . l)
601 (let* ((n (b-len o))
602 (vec o)
603 (f (lambda (m) (if (< m 0) (+ m n) m))))
604 (call-with-values
605 (lambda ()
606 (match l
607 (()
608 (values 0 n))
609 ((x)
610 (values (f x) n))
611 ((x y)
612 (values (f x) (f y)))))
613 (lambda (n1 n2)
614 (if (and (>= n1 0) (>= n2 0) (< n1 n) (<= n2 n))
615 (let lp ((i n1))
616 (if (< i n2)
617 (let ((r (b-ref vec i)))
618 (if (equal? r val)
619 i
620 (lp (+ i 1))))
621 (raise ValueError "could not find value in index fkn")))
622 (raise IndexError "index out of scop in index fkn"))))))
623
624 (define-py (py-rindex s . l)
625 (let ((n (b-len s)))
626 (- n (apply pylist-index (b-reverse s) l) 1)))
627
628 #;
629 (define-py (py-title title s)
630 (string-titlecase s))
631
632 #;
633 (define-py (py-split s . l)
634 (define ws (f+ (f-reg "[ \t\n]")))
635 (define r
636 (f-or! (f-seq f-eof (f-out '()))
637 (f-cons (f-seq (mk-token (f* (f-reg! "."))) f-eof) (f-out '()))))
638 (define (u ws) (mk-token (f+ (f-not! ws))))
639 (define (tok ws i)
640 (if (= i 0)
641 (f-list (mk-token (f* (f-reg! "."))))
642 (let ((e (mk-token (f* (f-not! ws)))))
643 (f-seq (f? ws)
644 (f-cons e
645 (let lp ((i i))
646 (if (> (- i 1) 0)
647 (f-or! (f-seq (f? ws) f-eof (f-out '()))
648 (f-cons (f-seq ws e) (Ds (lp (- i 1)))))
649 r)))))))
650
651 (define N 1000000000000)
652 (let ((e (call-with-values
653 (lambda ()
654 (match l
655 (() (values ws N))
656 ((sep) (values (f-tag sep) N))
657 ((sep n) (values (f-tag sep) n))))
658 tok)))
659 (parse s e)))
660
661 #;
662 (define-py (py-rsplit s . l)
663 (reverse
664 (map string-reverse
665 (apply py-split
666 (string-reverse s)
667 (match l
668 (() '())
669 ((sep . l) (cons (string-reverse sep) l)))))))
670
671
672 (define-py (py-splitlines s . l)
673 (let ((n (len s))
674 (keep? (match l
675 ((#:keepends v)
676 v)
677 ((v)
678 v)
679 (_ #f))))
680 (let lp ((i 0) (r '()) (old 0))
681 (if (< i n)
682 (let* ((x (b-ref s i))
683 (ch (chf x)))
684 (if (eq? ch #\newline)
685 (if keep?
686 (lp (+ i 1)
687 (cons
688 (pylist-slice s old (+ i 1) 1)
689 r)
690 (+ i 1))
691 (lp (+ i 1)
692 (cons
693 (pylist-slice s old i 1)
694 r)
695 (+ i 1)))
696 (lp (+ i 1) r old)))
697 (reverse r)))))
698
699 (define-py (py-translate s table . l)
700 (let* ((table (slot-ref (str table) 'str))
701 (n (b-len s))
702 (w (b-make n))
703 (t (if (eq? table None) #f table))
704 (d (match l (() #f) ((x) (map b-char (to-list x))))))
705 (define (tr ch)
706 (define (e)
707 (if t
708 (if (< ch (b-len t))
709 (b-ref t ch)
710 ch)
711 ch))
712
713 (if d
714 (if (member ch d)
715 #f
716 (e))
717 (e)))
718
719 (let lp ((i 0) (k 0))
720 (if (< i n)
721 (let ((ch (tr (b-ref s i))))
722 (if ch
723 (begin
724 (b-set! w k ch)
725 (lp (+ i 1) (+ k 1)))
726 (lp (+ i 1) k)))
727 (if (= k n)
728 w
729 (pylist-slice w 0 k 1))))))
730
731 (define-syntax-rule (a b x y) (b (symbol->string x) (symbol->string y)))
732
733 (define-syntax-rule (mkop op)
734 (begin
735 (define-method (op (s1 <bytevector>) (s2 <py-str>))
736 (op s1 (slot-ref s2 'str)))
737 (define-method (op (s2 <py-str>) (s1 <bytevector>))
738 (op s1 (slot-ref s2 'str)))))
739
740 (mkop <)
741 (mkop <=)
742 (mkop >)
743 (mkop >=)
744 (mkop py-equal?)
745 (mkop +)
746 (mkop *)
747
748 (define-syntax-rule (mkop2 op)
749 (define-method (< (s1 <bytevector>) (s2 <bytevector>))
750 (let* ((n1 (b-len s1))
751 (n2 (b-len s2))
752 (n (min n1 n2)))
753 (let lp ((i 0))
754 (if (< i n)
755 (let ((x1 (b-ref s1 i))
756 (x2 (b-ref s2 i)))
757 (if (= x1 x2)
758 (lp (+ i 1))
759 (op x1 x2)))
760 (op n1 n2))))))
761
762 (mkop2 <)
763 (mkop2 <=)
764 (mkop2 >=)
765 (mkop2 >)
766 (mkop2 py-equal?)
767
768 (define-py (py-zfill s width)
769 (let* ((n (b-len s))
770 (w (pylist-slice s 0 n 1)))
771 (let lp ((i 0))
772 (if (< i n)
773 (let* ((x (b-ref s i))
774 (ch (chf x)))
775 (if (char-numeric? ch)
776 (let lp ((j (max 0 (- i width))))
777 (if (< j i)
778 (begin
779 (b-set! w j (ch-find #\0))
780 (lp (+ j 1)))
781 w))
782 (lp (+ i 1))))
783 s))))
784
785 (define-method (pyhash (o <py-str>)) (hash (slot-ref o 'str) pyhash-N))
786
787 (define-class <str-iter> (<py-str>) str i d)
788
789 (define-method (wrap-in (o <str-iter> ))
790 (let ((out (make <str-iter>)))
791 (slot-set! out 'str (slot-ref o 'str))
792 (slot-set! out 'i (slot-ref o 'i))
793 (slot-set! out 'd (slot-ref o 'd))
794 out))
795
796 (define-method (wrap-in (s <bytevector>))
797 (let ((out (make <str-iter>)))
798 (slot-set! out 'str s)
799 (slot-set! out 'i 0)
800 (slot-set! out 'd 1)
801 out))
802
803 (define-method (py-reversed (s <bytevector>))
804 (let ((out (make <str-iter>)))
805 (slot-set! out 'str s)
806 (slot-set! out 'i (- (b-len s) 1))
807 (slot-set! out 'd -1)
808 out))
809
810 (define-method (next (o <str-iter>))
811 (let ((i (slot-ref o 'i ))
812 (d (slot-ref o 'd))
813 (str (slot-ref o 'str)))
814 (if (> d 0)
815 (if (< i (b-len str))
816 (let ((ret (b-ref str i)))
817 (slot-set! o 'i (+ i d))
818 ret)
819 (throw StopIteration))
820 (if (>= i 0)
821 (let ((ret (b-ref str i)))
822 (slot-set! o 'i (+ i d))
823 ret)
824 (throw StopIteration)))))
825
826 (define (pystr-listing)
827 (let ((l (to-pylist
828 (map symbol->string
829 '(__add__ __class__ __contains__ __delattr__ __doc__
830 __eq__ __format__ __ge__ __getattribute__
831 __getitem__ __getnewargs__ __getslice__ __gt__
832 __hash__ __init__ __le__ __len__ __lt__ __mod__
833 __mul__ __ne__ __new__ __reduce__ __reduce_ex__
834 __repr__ __rmod__ __rmul__ __setattr__ __sizeof__
835 __str__ __subclasshook__
836 _formatter_field_name_split _formatter_parser
837 capitalize center count decode encode endswith
838 expandtabs find format index isalnum isalpha
839 isdigit islower isspace istitle isupper join
840 ljust lower lstrip partition replace rfind rindex
841 rjust rpartition rsplit rstrip split splitlines
842 startswith strip swapcase
843 title translate upper zfill)))))
844 (pylist-sort! l)
845 l))