Skip to content
Permalink
Newer
Older
100644 2713 lines (2491 sloc) 85.5 KB
Sep 5, 2014
1
;(function($B){
2
3
var bltns = $B.InjectBuiltins()
4
eval(bltns)
Sep 5, 2014
5
6
// build tables from data in unicode_data.js
7
var unicode_tables = $B.unicode_tables
Sep 5, 2014
8
str
Feb 10, 2018
9
var str = {
Mar 19, 2018
10
__class__: _b_.type,
11
__dir__: object.__dir__,
12
$infos: {
13
__module__: "builtins",
14
__name__: "str"
15
},
str
Feb 10, 2018
16
$is_class: true,
Mar 19, 2018
17
$native: true
Sep 5, 2014
18
}
19
Mar 19, 2018
21
if($.start === null || $.start === _b_.None){$.start = 0}
22
else if($.start < 0){
23
$.start += $.self.length
24
$.start = Math.max(0, $.start)
25
}
26
if($.end === null || $.end === _b_.None){$.end = $.self.length}
27
else if($.end < 0){
28
$.end += $.self.length
29
$.end = Math.max(0, $.end)
30
}
Mar 19, 2018
32
if(! isinstance($.start, _b_.int) || ! isinstance($.end, _b_.int)){
33
throw _b_.TypeError.$factory("slice indices must be integers " +
34
"or None or have an __index__ method")
35
}
39
function reverse(s){
40
// Reverse a string
Mar 19, 2018
41
return s.split("").reverse().join("")
42
}
43
44
function check_str(obj){
Mar 19, 2018
45
if(! _b_.isinstance(obj, str)){
Mar 21, 2018
46
throw _b_.TypeError.$factory("can't convert '" +
47
$B.class_name(obj) + "' object to str implicitly")
Mar 19, 2018
48
}
51
str.__add__ = function(self, other){
Mar 19, 2018
52
if(!(typeof other === "string")){
53
try{return getattr(other, "__radd__")(self)}
54
catch(err){
55
throw _b_.TypeError.$factory("Can't convert " +
56
$B.class_name(other) + " to str implicitly")}
Sep 5, 2014
57
}
Mar 19, 2018
58
return self + other
Sep 5, 2014
59
}
60
Mar 19, 2018
61
str.__contains__ = function(self, item){
62
if(! _b_.isinstance(item, str)){
Mar 19, 2018
63
throw _b_.TypeError.$factory("'in <string>' requires " +
64
"string as left operand, not " + item.__class__)
65
}
66
if(typeof item == "string"){
67
var nbcar = item.length
68
}else{
69
var nbcar = _b_.len(item)
70
}
Mar 19, 2018
71
if(nbcar == 0) {return true} // a string contains the empty string
72
if(self.length == 0){return nbcar == 0}
73
for(var i = 0, len = self.length; i < len; i++){
74
if(self.substr(i, nbcar) == item){return true}
Sep 5, 2014
75
}
76
return false
77
}
78
str
Feb 10, 2018
79
str.__delitem__ = function(){
80
throw _b_.TypeError.$factory("'str' object doesn't support item deletion")
Sep 5, 2014
81
}
82
Mar 19, 2018
83
// __dir__must be assigned explicitely because attribute resolution for
84
// builtin classes doesn't use __mro__
str
Feb 10, 2018
85
str.__dir__ = object.__dir__
87
str.__eq__ = function(self, other){
Mar 23, 2018
88
if(_b_.isinstance(other, _b_.str)){
89
return other.valueOf() == self.valueOf()
90
}
91
return _b_.NotImplemented
Sep 5, 2014
92
}
93
94
function preformat(self, fmt){
str
Feb 10, 2018
95
if(fmt.empty){return _b_.str.$factory(self)}
Mar 19, 2018
96
if(fmt.type && fmt.type != "s"){
97
throw _b_.ValueError.$factory("Unknown format code '" + fmt.type +
98
"' for object of type 'str'")
100
return self
101
}
102
str
Feb 10, 2018
103
str.__format__ = function(self, format_spec) {
104
var fmt = new $B.parse_format_spec(format_spec)
Mar 19, 2018
105
if(fmt.sign !== undefined){
106
throw _b_.ValueError.$factory(
107
"Sign not allowed in string format specifier")
109
if(fmt.precision){
110
self = self.substr(0, fmt.precision)
111
}
112
// For strings, alignment default to left
Mar 19, 2018
113
fmt.align = fmt.align || "<"
114
return $B.format_width(preformat(self, fmt), fmt)
Sep 5, 2014
115
}
116
str
Feb 10, 2018
117
str.__getitem__ = function(self,arg){
Mar 19, 2018
118
if(isinstance(arg, _b_.int)){
Sep 5, 2014
119
var pos = arg
Mar 19, 2018
120
if(arg < 0) {pos += self.length}
121
if(pos >= 0 && pos < self.length){return self.charAt(pos)}
122
throw _b_.IndexError.$factory("string index out of range")
123
}
124
if(isinstance(arg, slice)) {
125
var s = _b_.slice.$conv_for_seq(arg, self.length),
126
start = s.start,
127
stop = s.stop,
128
step = s.step
129
var res = "",
Mar 19, 2018
130
i = null
Mar 19, 2018
131
if(step > 0){
132
if(stop <= start){return ""}
133
for(var i = start; i < stop; i += step){res += self.charAt(i)}
Mar 23, 2018
134
}else{
Mar 19, 2018
135
if(stop >= start){return ''}
136
for(var i = start; i > stop; i += step){res += self.charAt(i)}
Sep 5, 2014
138
return res
139
}
140
if(isinstance(arg, _b_.bool)){return self.__getitem__(_b_.int.$factory(arg))}
Mar 19, 2018
141
throw _b_.TypeError.$factory("string indices must be integers")
Sep 5, 2014
142
}
143
144
var prefix = 2,
145
suffix = 3,
Jun 12, 2020
146
mask = (2 ** 32 - 1),
147
str_hash_cache = {}
148
149
str.$nb_str_hash_cache = 0
Jun 12, 2020
150
151
function fnv(p){
152
if(p.length == 0){
153
return 0
154
}
Sep 5, 2014
155
156
var x = prefix
157
x = (x ^ (p.charCodeAt(0) << 7)) & mask
158
for(var i = 0, len = p.length; i < len; i++){
159
x = ((1000003 * x) ^ p.charCodeAt(i)) & mask
160
}
161
x = (x ^ p.length) & mask
162
x = (x ^ suffix) & mask
Sep 5, 2014
163
164
if(x == -1){
165
x = -2
166
}
167
return x
168
}
170
str.__hash__ = function(self) {
Jun 12, 2020
171
if(str_hash_cache[self] !== undefined){
172
return str_hash_cache[self]
173
}
174
str.$nb_str_hash_cache++
175
if(str.$nb_str_hash_cache > 100000){
176
// Avoid memory overflow
177
str.$nb_str_hash_cache = 0
178
str_hash_cache = {}
179
}
Jun 12, 2020
180
return str_hash_cache[self] = fnv(self)
Sep 5, 2014
181
}
182
Mar 19, 2018
183
str.__init__ = function(self, arg){
Sep 5, 2014
184
self.valueOf = function(){return arg}
185
self.toString = function(){return arg}
Sep 5, 2014
187
}
188
189
var str_iterator = $B.make_iterator_class("str_iterator")
str
Feb 10, 2018
190
str.__iter__ = function(self){
192
return str_iterator.$factory(items)
Sep 5, 2014
193
}
194
195
str.__len__ = function(self){
196
return self.length
197
}
Sep 5, 2014
198
199
// Start of section for legacy formatting (with %)
200
Mar 19, 2018
201
var kwarg_key = new RegExp("([^\\)]*)\\)")
202
203
var NotANumber = function() {
Mar 19, 2018
204
this.name = "NotANumber"
205
}
206
Mar 19, 2018
207
var number_check = function(s){
208
if(! isinstance(s, [_b_.int, _b_.float])){
209
throw new NotANumber()
210
}
211
}
212
Mar 19, 2018
213
var get_char_array = function(size, char){
Mar 23, 2018
214
if(size <= 0){return ""}
215
return new Array(size + 1).join(char)
216
}
217
Mar 19, 2018
218
var format_padding = function(s, flags, minus_one){
219
var padding = flags.padding
Mar 23, 2018
220
if(! padding){ // undefined
221
return s
222
}
223
s = s.toString()
224
padding = parseInt(padding, 10)
Mar 23, 2018
225
if(minus_one){ // numeric formatting where sign goes in front of padding
226
padding -= 1
227
}
Mar 19, 2018
228
if(! flags.left){
229
return get_char_array(padding - s.length, flags.pad_char) + s
Mar 19, 2018
230
}else{
231
// left adjusted
232
return s + get_char_array(padding - s.length, flags.pad_char)
233
}
234
}
235
Mar 19, 2018
236
var format_int_precision = function(val, flags){
237
var precision = flags.precision
Mar 19, 2018
238
if(!precision){
239
return val.toString()
240
}
241
precision = parseInt(precision, 10)
Mar 19, 2018
243
if(val.__class__ === $B.long_int){
244
s = $B.long_int.to_base(val, 10)
245
}else{
246
s = val.toString()
Mar 19, 2018
248
if(s[0] === "-"){
249
return "-" + get_char_array(precision - s.length + 1, "0") + s.slice(1)
Mar 19, 2018
251
return get_char_array(precision - s.length, "0") + s
252
}
253
Mar 19, 2018
254
var format_float_precision = function(val, upper, flags, modifier){
255
var precision = flags.precision
256
// val is a float
Mar 19, 2018
257
if(isFinite(val)){
258
return modifier(val, precision, flags, upper)
Mar 19, 2018
260
if(val === Infinity){
261
val = "inf"
262
}else if(val === -Infinity){
263
val = "-inf"
264
}else{
265
val = "nan"
Mar 19, 2018
267
if(upper){
268
return val.toUpperCase()
269
}
270
return val
272
}
273
Mar 19, 2018
274
var format_sign = function(val, flags){
275
if(flags.sign){
276
if(val >= 0){
277
return "+"
Sep 5, 2014
278
}
Mar 19, 2018
279
}else if (flags.space){
280
if(val >= 0){
281
return " "
282
}
283
}
284
return ""
285
}
Sep 5, 2014
286
287
var str_format = function(val, flags) {
288
// string format supports left and right padding
289
flags.pad_char = " " // even if 0 padding is defined, don't use it
str
Feb 10, 2018
290
return format_padding(str.$factory(val), flags)
Sep 5, 2014
292
293
var num_format = function(val, flags) {
294
number_check(val)
Mar 19, 2018
295
if(val.__class__ === $B.long_int){
296
val = $B.long_int.to_base(val, 10)
297
}else{
298
val = parseInt(val)
301
var s = format_int_precision(val, flags)
Mar 19, 2018
302
if(flags.pad_char === "0"){
303
if(val < 0){
304
s = s.substring(1)
Mar 19, 2018
305
return "-" + format_padding(s, flags, true)
306
}
307
var sign = format_sign(val, flags)
Mar 19, 2018
308
if(sign !== ""){
309
return sign + format_padding(s, flags, true)
310
}
311
}
313
return format_padding(format_sign(val, flags) + s, flags)
314
}
Sep 5, 2014
315
316
var repr_format = function(val, flags) {
317
flags.pad_char = " " // even if 0 padding is defined, don't use it
318
return format_padding(repr(val), flags)
319
}
Sep 5, 2014
320
321
var ascii_format = function(val, flags) {
322
flags.pad_char = " " // even if 0 padding is defined, don't use it
323
return format_padding(ascii(val), flags)
324
}
Sep 5, 2014
325
326
// converts val to float and sets precision if missing
Mar 19, 2018
327
var _float_helper = function(val, flags){
328
number_check(val)
Mar 19, 2018
329
if(! flags.precision){
330
if(! flags.decimal_point){
331
flags.precision = 6
Mar 19, 2018
332
}else{
333
flags.precision = 0
334
}
Mar 19, 2018
335
}else{
336
flags.precision = parseInt(flags.precision, 10)
337
validate_precision(flags.precision)
338
}
339
return parseFloat(val)
340
}
Sep 5, 2014
341
342
// used to capture and remove trailing zeroes
Mar 19, 2018
343
var trailing_zeros = /(.*?)(0+)([eE].*)/,
344
leading_zeros = /\.(0*)/,
345
trailing_dot = /\.$/
Sep 5, 2014
346
347
var validate_precision = function(precision) {
348
// force precision to limits of javascript
Mar 19, 2018
349
if(precision > 20){precision = 20}
350
}
351
352
// gG
Mar 19, 2018
353
var floating_point_format = function(val, upper, flags){
354
val = _float_helper(val, flags),
355
v = val.toString(),
356
v_len = v.length,
357
dot_idx = v.indexOf('.')
358
if(dot_idx < 0){dot_idx = v_len}
359
if(val < 1 && val > -1){
360
var zeros = leading_zeros.exec(v),
361
numzeros
362
if(zeros){
363
numzeros = zeros[1].length
Mar 19, 2018
364
}else{
365
numzeros = 0
366
}
Mar 19, 2018
367
if(numzeros >= 4){
368
val = format_sign(val, flags) + format_float_precision(val, upper,
369
flags, _floating_g_exp_helper)
370
if(!flags.alternate){
371
var trl = trailing_zeros.exec(val)
Mar 19, 2018
372
if(trl){
373
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
375
}else{
376
if(flags.precision <= 1){
377
val = val[0] + "." + val.substring(1)
379
}
380
return format_padding(val, flags)
381
}
382
flags.precision = (flags.precision || 0) + numzeros
Mar 19, 2018
383
return format_padding(format_sign(val, flags) +
384
format_float_precision(val, upper, flags,
385
function(val, precision) {
386
return val.toFixed(min(precision, v_len - dot_idx) +
387
numzeros)
388
}),
389
flags
390
)
391
}
392
393
if(dot_idx > flags.precision){
394
val = format_sign(val, flags) + format_float_precision(val, upper,
395
flags, _floating_g_exp_helper)
396
if(! flags.alternate){
397
var trl = trailing_zeros.exec(val)
Mar 19, 2018
398
if(trl){
399
val = trl[1].replace(trailing_dot, "") + trl[3] // remove trailing
Mar 19, 2018
401
}else{
402
if(flags.precision <= 1){
403
val = val[0] + "." + val.substring(1)
404
}
405
}
406
return format_padding(val, flags)
407
}
Mar 19, 2018
408
return format_padding(format_sign(val, flags) +
409
format_float_precision(val, upper, flags,
410
function(val, precision) {
411
if(!flags.decimal_point){
412
precision = min(v_len - 1, 6)
413
}else if (precision > v_len){
414
if(! flags.alternate){
415
precision = v_len
416
}
Sep 5, 2014
417
}
Mar 19, 2018
418
if(precision < dot_idx){
419
precision = dot_idx
420
}
421
return val.toFixed(precision - dot_idx)
422
}),
423
flags
424
)
Sep 5, 2014
426
Mar 19, 2018
427
var _floating_g_exp_helper = function(val, precision, flags, upper){
428
if(precision){--precision}
429
val = val.toExponential(precision)
430
// pad exponent to two digits
Mar 19, 2018
431
var e_idx = val.lastIndexOf("e")
432
if(e_idx > val.length - 4){
433
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
435
if(upper){return val.toUpperCase()}
436
return val
437
}
438
439
// fF
440
var floating_point_decimal_format = function(val, upper, flags) {
441
val = _float_helper(val, flags)
Mar 19, 2018
442
return format_padding(format_sign(val, flags) +
443
format_float_precision(val, upper, flags,
444
function(val, precision, flags) {
445
val = val.toFixed(precision)
446
if(precision === 0 && flags.alternate){
447
val += '.'
448
}
449
return val
450
}),
451
flags
452
)
453
}
454
455
var _floating_exp_helper = function(val, precision, flags, upper) {
456
val = val.toExponential(precision)
457
// pad exponent to two digits
Mar 19, 2018
458
var e_idx = val.lastIndexOf("e")
Mar 23, 2018
459
if(e_idx > val.length - 4){
Mar 19, 2018
460
val = val.substring(0, e_idx + 2) + "0" + val.substring(e_idx + 2)
Mar 19, 2018
462
if(upper){return val.toUpperCase()}
463
return val
464
}
465
466
// eE
Mar 19, 2018
467
var floating_point_exponential_format = function(val, upper, flags){
468
val = _float_helper(val, flags)
Mar 19, 2018
470
return format_padding(format_sign(val, flags) +
471
format_float_precision(val, upper, flags, _floating_exp_helper), flags)
472
}
473
Mar 19, 2018
474
var signed_hex_format = function(val, upper, flags){
476
number_check(val)
Mar 23, 2018
478
if(val.__class__ === $B.long_int){
Mar 19, 2018
479
ret = $B.long_int.to_base(val, 16)
480
}else{
481
ret = parseInt(val)
482
ret = ret.toString(16)
483
}
484
ret = format_int_precision(ret, flags)
Mar 19, 2018
485
if(upper){ret = ret.toUpperCase()}
Mar 23, 2018
486
if(flags.pad_char === "0"){
Mar 19, 2018
487
if(val < 0){
488
ret = ret.substring(1)
Mar 19, 2018
489
ret = "-" + format_padding(ret, flags, true)
490
}
491
var sign = format_sign(val, flags)
Mar 19, 2018
492
if(sign !== ""){
493
ret = sign + format_padding(ret, flags, true)
Sep 5, 2014
494
}
Mar 19, 2018
497
if(flags.alternate){
498
if(ret.charAt(0) === "-"){
499
if(upper){ret = "-0X" + ret.slice(1)}
500
else{ret = "-0x" + ret.slice(1)}
501
}else{
502
if(upper){ret = "0X" + ret}
503
else{ret = "0x" + ret}
504
}
505
}
506
return format_padding(format_sign(val, flags) + ret, flags)
507
}
Sep 5, 2014
508
509
var octal_format = function(val, flags) {
510
number_check(val)
Mar 19, 2018
513
if(val.__class__ === $B.long_int){
514
ret = $B.long_int.to_base(8)
515
}else{
516
ret = parseInt(val)
517
ret = ret.toString(8)
520
ret = format_int_precision(ret, flags)
Mar 19, 2018
522
if(flags.pad_char === "0"){
523
if(val < 0){
524
ret = ret.substring(1)
Mar 19, 2018
525
ret = "-" + format_padding(ret, flags, true)
526
}
527
var sign = format_sign(val, flags)
Mar 19, 2018
528
if(sign !== ""){
529
ret = sign + format_padding(ret, flags, true)
530
}
Sep 5, 2014
531
}
Mar 19, 2018
533
if(flags.alternate){
534
if(ret.charAt(0) === "-"){ret = "-0o" + ret.slice(1)}
535
else{ret = "0o" + ret}
Sep 5, 2014
536
}
537
return format_padding(ret, flags)
538
}
539
540
function series_of_bytes(val, flags){
541
if(val.__class__ && val.__class__.$buffer_protocol){
542
var it = _b_.iter(val),
543
ints = []
544
while(true){
545
try{
546
ints.push(_b_.next(it))
547
}catch(err){
548
if(err.__class__ === _b_.StopIteration){
549
var b = _b_.bytes.$factory(ints)
550
return format_padding(_b_.bytes.decode(b, "ascii"), flags)
551
}
552
throw err
553
}
554
}
555
}else{
556
try{
557
bytes_obj = $B.$getattr(val, "__bytes__")
558
return format_padding(_b_.bytes.decode(bytes_obj), flags)
559
}catch(err){
560
if(err.__class__ === _b_.AttributeError){
561
throw _b_.TypeError.$factory("%b does not accept '" +
562
$B.class_name(val) + "'")
563
}
564
throw err
565
}
566
}
567
}
568
Mar 19, 2018
569
var single_char_format = function(val, flags){
570
if(isinstance(val, str) && val.length == 1){
571
return val
572
}else if(isinstance(val, bytes) && val.source.length == 1){
573
val = val.source[0]
574
}else{
575
try{
576
val = _b_.int.$factory(val) // yes, floats are valid (they are cast to int)
577
}catch (err){
578
throw _b_.TypeError.$factory("%c requires int or char")
579
}
580
}
581
return format_padding(chr(val), flags)
582
}
583
Mar 19, 2018
584
var num_flag = function(c, flags){
585
if(c === "0" && ! flags.padding && ! flags.decimal_point && ! flags.left){
586
flags.pad_char = "0"
587
return
588
}
Mar 19, 2018
589
if(!flags.decimal_point){
590
flags.padding = (flags.padding || "") + c
Mar 19, 2018
591
}else{
592
flags.precision = (flags.precision || "") + c
593
}
594
}
595
596
var decimal_point_flag = function(val, flags) {
Mar 23, 2018
597
if(flags.decimal_point){
598
// can only have one decimal point
599
throw new UnsupportedChar()
600
}
601
flags.decimal_point = true
602
}
603
Mar 19, 2018
604
var neg_flag = function(val, flags){
605
flags.pad_char = " " // overrides '0' flag
606
flags.left = true
607
}
608
Mar 19, 2018
609
var space_flag = function(val, flags){
610
flags.space = true
611
}
612
Mar 19, 2018
613
var sign_flag = function(val, flags){
614
flags.sign = true
615
}
616
Mar 19, 2018
617
var alternate_flag = function(val, flags){
618
flags.alternate = true
619
}
620
621
var char_mapping = {
Mar 19, 2018
623
"s": str_format,
624
"d": num_format,
625
"i": num_format,
626
"u": num_format,
627
"o": octal_format,
628
"r": repr_format,
629
"a": ascii_format,
630
"g": function(val, flags){
631
return floating_point_format(val, false, flags)
632
},
633
"G": function(val, flags){return floating_point_format(val, true, flags)},
634
"f": function(val, flags){
635
return floating_point_decimal_format(val, false, flags)
636
},
637
"F": function(val, flags){
638
return floating_point_decimal_format(val, true, flags)
639
},
640
"e": function(val, flags){
641
return floating_point_exponential_format(val, false, flags)
642
},
643
"E": function(val, flags){
644
return floating_point_exponential_format(val, true, flags)
645
},
646
"x": function(val, flags){return signed_hex_format(val, false, flags)},
647
"X": function(val, flags){return signed_hex_format(val, true, flags)},
648
"c": single_char_format,
649
"0": function(val, flags){return num_flag("0", flags)},
650
"1": function(val, flags){return num_flag("1", flags)},
651
"2": function(val, flags){return num_flag("2", flags)},
652
"3": function(val, flags){return num_flag("3", flags)},
653
"4": function(val, flags){return num_flag("4", flags)},
654
"5": function(val, flags){return num_flag("5", flags)},
655
"6": function(val, flags){return num_flag("6", flags)},
656
"7": function(val, flags){return num_flag("7", flags)},
657
"8": function(val, flags){return num_flag("8", flags)},
658
"9": function(val, flags){return num_flag("9", flags)},
659
"-": neg_flag,
660
" ": space_flag,
661
"+": sign_flag,
662
".": decimal_point_flag,
663
"#": alternate_flag
664
}
665
666
// exception thrown when an unsupported char is encountered in legacy format
Mar 19, 2018
667
var UnsupportedChar = function(){
668
this.name = "UnsupportedChar"
669
}
670
str
Feb 10, 2018
671
str.__mod__ = function(self, args) {
672
var length = self.length,
Mar 19, 2018
673
pos = 0 | 0,
674
argpos = null,
675
getitem
Mar 19, 2018
676
if(_b_.isinstance(args, _b_.tuple)){
677
argpos = 0 | 0
Mar 19, 2018
679
getitem = _b_.getattr(args, "__getitem__", _b_.None)
680
}
681
var ret = ''
682
var $get_kwarg_string = function(s) {
683
// returns [self, newpos]
684
++pos
685
var rslt = kwarg_key.exec(s.substring(newpos))
Mar 19, 2018
686
if(! rslt){
687
throw _b_.ValueError.$factory("incomplete format key")
688
}
689
var key = rslt[1]
690
newpos += rslt[0].length
Mar 23, 2018
691
try{
692
var self = getitem(key)
Mar 19, 2018
693
}catch(err){
694
if(err.__class__ === _b_.KeyError){
695
throw err
696
}
697
throw _b_.TypeError.$factory("format requires a mapping")
699
return get_string_value(s, self)
700
}
701
702
var $get_arg_string = function(s) {
703
// returns [self, newpos]
704
var self
706
// non-tuple args
Mar 19, 2018
707
if(argpos === null){
708
// args is the value
Mar 19, 2018
710
}else{
711
self = args[argpos++]
Mar 19, 2018
712
if(self === undefined){
713
throw _b_.TypeError.$factory(
714
"not enough arguments for format string")
Sep 5, 2014
715
}
716
}
717
return get_string_value(s, self)
719
var get_string_value = function(s, self) {
720
// todo: get flags, type
721
// todo: string value based on flags, type, value
Mar 19, 2018
722
var flags = {"pad_char": " "}
723
do{
724
var func = char_mapping[s[newpos]]
Mar 23, 2018
725
try{
Mar 19, 2018
726
if(func === undefined){
727
throw new UnsupportedChar()
Mar 19, 2018
728
}else{
729
var ret = func(self, flags)
Mar 19, 2018
730
if(ret !== undefined){
731
return ret
732
}
733
++newpos
734
}
Mar 19, 2018
735
}catch (err){
736
if(err.name == "UnsupportedChar"){
737
invalid_char = s[newpos]
Mar 19, 2018
738
if(invalid_char === undefined){
739
throw _b_.ValueError.$factory("incomplete format")
Mar 19, 2018
741
throw _b_.ValueError.$factory(
742
"unsupported format character '" + invalid_char +
743
"' (0x" + invalid_char.charCodeAt(0).toString(16) +
744
") at index " + newpos)
745
}else if(err.name === "NotANumber"){
746
var try_char = s[newpos],
747
cls = self.__class__
748
if(!cls){
749
if(typeof(self) === "string"){
750
cls = "str"
751
}else{
752
cls = typeof(self)
Mar 19, 2018
754
}else{
Mar 19, 2018
757
throw _b_.TypeError.$factory("%" + try_char +
758
" format: a number is required, not " + cls)
759
}else{
760
throw err
761
}
Sep 5, 2014
762
}
Mar 19, 2018
763
}while (true)
Sep 5, 2014
764
}
765
var nbph = 0 // number of placeholders
Mar 19, 2018
766
do{
767
var newpos = self.indexOf("%", pos)
768
if(newpos < 0){
769
ret += self.substring(pos)
770
break
771
}
772
ret += self.substring(pos, newpos)
773
++newpos
Mar 19, 2018
774
if(newpos < length){
775
if(self[newpos] === "%"){
776
ret += "%"
777
}else{
Mar 19, 2018
779
if(self[newpos] === "("){
780
++newpos
781
ret += $get_kwarg_string(self)
Mar 23, 2018
782
}else{
783
ret += $get_arg_string(self)
784
}
785
}
Mar 19, 2018
786
}else{
787
// % at end of string
788
throw _b_.ValueError.$factory("incomplete format")
789
}
790
pos = newpos + 1
Mar 19, 2018
791
}while(pos < length)
792
793
if(argpos !== null){
794
if(args.length > argpos){
795
throw _b_.TypeError.$factory(
796
"not enough arguments for format string")
797
}else if(args.length < argpos){
798
throw _b_.TypeError.$factory(
799
"not all arguments converted during string formatting")
Mar 19, 2018
801
}else if(nbph == 0){
802
throw _b_.TypeError.$factory(
803
"not all arguments converted during string formatting")
805
if($B.has_surrogate(ret)){
806
return str.$surrogate.$factory(ret)
807
}
Sep 5, 2014
810
str
Feb 10, 2018
811
str.__mro__ = [object]
Sep 5, 2014
812
str
Feb 10, 2018
813
str.__mul__ = function(){
Mar 19, 2018
814
var $ = $B.args("__mul__", 2, {self: null, other: null},
815
["self", "other"], arguments, {}, null, null)
816
if(! isinstance($.other, _b_.int)){throw _b_.TypeError.$factory(
817
"Can't multiply sequence by non-int of type '" +
Mar 19, 2018
819
var $res = ""
820
for(var i = 0; i< $.other; i++){$res += $.self.valueOf()}
Sep 5, 2014
821
return $res
822
}
823
824
str.__ne__ = function(self, other){
825
return other !== self.valueOf()
826
}
Sep 5, 2014
827
str
Feb 10, 2018
828
str.__repr__ = function(self){
830
// escape the escape char
831
res = self.replace(/\\/g, "\\\\")
832
// special cases
833
res = res.replace(new RegExp("\u0007", "g"), "\\x07").
834
replace(new RegExp("\b", "g"), "\\x08").
835
replace(new RegExp("\u000b", "g"), "\\x0b").
836
replace(new RegExp("\f", "g"), "\\x0c").
837
replace(new RegExp("\n", "g"), "\\n").
838
replace(new RegExp("\r", "g"), "\\r").
839
replace(new RegExp("\t", "g"), "\\t")
Mar 27, 2019
840
res = res.replace(combining_re, "\u200B$1")
841
// Replace unassigned code point by \uabcd...
842
// Uses function $B.is_unicode_cn() in unicode_data.js
843
var repl = ''
844
for(var i = 0; i < res.length; i++){
845
var cp = res.codePointAt(i)
846
if($B.is_unicode_cn(cp)){
847
var s = cp.toString(16)
848
while(s.length < 4){
849
s = '0' + s
850
}
851
repl += '\\u' + s
852
}else if(cp < 0x20 || (cp >= 0x7f && cp < 0xa0)){
853
cp = cp.toString(16)
854
if(cp.length < 2){
855
cp = '0' + cp
856
}
857
repl += '\\x' + cp
858
}else{
859
repl += res.charAt(i)
860
}
861
}
862
res = repl
Mar 19, 2018
863
if(res.search('"') == -1 && res.search("'") == -1){
864
return "'" + res + "'"
865
}else if(self.search('"') == -1){
866
return '"' + res + '"'
867
}
868
var qesc = new RegExp("'", "g") // to escape single quote
869
res = "'" + res.replace(qesc, "\\'") + "'"
Sep 5, 2014
870
return res
871
}
872
Mar 19, 2018
873
str.__setitem__ = function(self, attr, value){
874
throw _b_.TypeError.$factory(
875
"'str' object does not support item assignment")
Sep 5, 2014
876
}
Mar 27, 2019
877
var combining = []
878
for(var cp = 0x300; cp <= 0x36F; cp++){
879
combining.push(String.fromCharCode(cp))
880
}
881
var combining_re = new RegExp("(" + combining.join("|") + ")")
str
Feb 10, 2018
883
str.__str__ = function(self){
Mar 27, 2019
884
return self.replace(combining_re, "\u200B$1")
Sep 5, 2014
885
}
Mar 19, 2018
886
str.toString = function(){return "string!"}
Sep 5, 2014
887
888
// generate comparison methods
889
var $comp_func = function(self,other){
890
if(typeof other !== "string"){return _b_.NotImplemented}
Sep 5, 2014
891
return self > other
892
}
Mar 19, 2018
893
$comp_func += "" // source code
894
var $comps = {">": "gt", ">=": "ge", "<": "lt", "<=": "le"}
Sep 5, 2014
895
for(var $op in $comps){
Mar 19, 2018
896
eval("str.__" + $comps[$op] + '__ = ' + $comp_func.replace(/>/gm,$op))
Sep 5, 2014
897
}
898
899
// add "reflected" methods
str
Feb 10, 2018
900
$B.make_rmethods(str)
Sep 5, 2014
901
902
// unsupported operations
Mar 19, 2018
903
var $notimplemented = function(self, other){
904
throw NotImplementedError.$factory(
905
"OPERATOR not implemented for class str")
Sep 5, 2014
906
}
907
908
str.capitalize = function(self){
909
var $ = $B.args("capitalize", 1, {self}, ["self"],
910
arguments, {}, null, null)
911
if(self.length == 0){return ""}
912
return self.charAt(0).toUpperCase() + self.substr(1)
913
}
914
915
str.casefold = function(self){
916
var $ = $B.args("casefold", 1, {self}, ["self"],
917
arguments, {}, null, null),
918
res = "",
919
char,
920
cf
921
for(var i = 0, len = self.length; i < len; i++){
922
char = self.charCodeAt(i)
923
cf = $B.unicode_casefold[char]
924
if(cf){
925
cf.forEach(function(cp){
926
res += String.fromCharCode(cp)
927
})
928
}else{
929
res += self.charAt(i).toLowerCase()
930
}
931
}
932
return res
933
}
Sep 5, 2014
934
Mar 19, 2018
935
str.center = function(){
936
var $ = $B.args("center", 3, {self: null, width: null, fillchar: null},
937
["self", "width", "fillchar"],
938
arguments, {fillchar:" "}, null, null),
939
self = $.self
Mar 19, 2018
941
if($.width <= self.length) {return self}
Mar 19, 2018
943
var pad = parseInt(($.width - self.length) / 2),
944
res = $.fillchar.repeat(pad)
Sep 5, 2014
945
res += self + res
Mar 19, 2018
946
if(res.length < $.width){res += $.fillchar}
Sep 5, 2014
947
return res
948
}
949
str
Feb 10, 2018
950
str.count = function(){
Mar 19, 2018
951
var $ = $B.args("count", 4, {self:null, sub:null, start:null, stop:null},
952
["self", "sub", "start", "stop"], arguments, {start:null, stop:null},
Mar 19, 2018
954
if(!(typeof $.sub == "string")){throw _b_.TypeError.$factory(
955
"Can't convert '" + $B.class_name($.sub) +
Mar 19, 2018
956
"' object to str implicitly")}
Mar 19, 2018
958
if($.start !== null){
Mar 19, 2018
960
if($.stop !== null){_slice = _b_.slice.$factory($.start, $.stop)}
961
else{_slice = _b_.slice.$factory($.start, $.self.length)}
str
Feb 10, 2018
962
substr = str.__getitem__.apply(null, [$.self].concat(_slice))
Mar 19, 2018
964
if($.self.length + $.sub.length == 0){return 1}
Mar 19, 2018
966
if($.sub.length == 0){
967
if($.start == $.self.length){return 1}
968
else if(substr.length == 0){return 0}
969
return substr.length + 1
Mar 19, 2018
971
var n = 0,
972
pos = 0
973
while(pos < substr.length){
974
pos = substr.indexOf($.sub, pos)
975
if(pos >= 0){n++; pos += $.sub.length}
976
else{break}
Sep 5, 2014
977
}
978
return n
979
}
980
981
str.encode = function(){
982
var $ = $B.args("encode", 3, {self: null, encoding: null, errors: null},
983
["self", "encoding", "errors"], arguments,
984
{encoding: "utf-8", errors: "strict"}, null, null)
985
if($.encoding == "rot13" || $.encoding == "rot_13"){
986
// Special case : returns a string
Mar 19, 2018
987
var res = ""
988
for(var i = 0, len = $.self.length; i < len ; i++){
989
var char = $.self.charAt(i)
Mar 19, 2018
990
if(("a" <= char && char <= "m") || ("A" <= char && char <= "M")){
991
res += String.fromCharCode(String.charCodeAt(char) + 13)
992
}else if(("m" < char && char <= "z") ||
993
("M" < char && char <= "Z")){
994
res += String.fromCharCode(String.charCodeAt(char) - 13)
995
}else{res += char}
996
}
997
return res
998
}
999
return _b_.bytes.__new__(_b_.bytes, $.self, $.encoding, $.errors)
Sep 5, 2014
1000
}
1001
str
Feb 10, 2018
1002
str.endswith = function(){
1003
// Return True if the string ends with the specified suffix, otherwise
1004
// return False. suffix can also be a tuple of suffixes to look for.
1005
// With optional start, test beginning at that position. With optional
Sep 5, 2014
1006
// end, stop comparing at that position.
Mar 19, 2018
1007
var $ = $B.args("endswith", 4,
1008
{self:null, suffix:null, start:null, end:null},
Mar 19, 2018
1009
["self", "suffix", "start", "end"],
1010
arguments, {start: 0, end: null}, null, null)
Sep 20, 2015
1011
1012
normalize_start_end($)
1013
1014
var suffixes = $.suffix
Mar 19, 2018
1015
if(! isinstance(suffixes,_b_.tuple)){suffixes = [suffixes]}
Mar 19, 2018
1017
var s = $.self.substring($.start, $.end)
1018
for(var i = 0, len = suffixes.length; i < len; i++){
1019
var suffix = suffixes[i]
Mar 19, 2018
1020
if(! _b_.isinstance(suffix, str)){throw _b_.TypeError.$factory(
Sep 20, 2015
1021
"endswith first arg must be str or a tuple of str, not int")}
Mar 19, 2018
1022
if(suffix.length <= s.length &&
1023
s.substr(s.length - suffix.length) == suffix){return true}
Sep 5, 2014
1024
}
1025
return false
1026
}
1027
str
Feb 10, 2018
1028
str.expandtabs = function(self, tabsize) {
Mar 19, 2018
1029
var $ = $B.args("expandtabs", 2, {self: null, tabsize: null},
1030
["self", "tabsize"], arguments, {tabsize: 8}, null, null)
1031
var s = $B.$GetInt($.tabsize),
1032
col = 0,
1033
pos = 0,
1034
res = ""
1035
if(s == 1){return self.replace(/\t/g," ")}
1036
while(pos < self.length){
1037
var car = self.charAt(pos)
1038
switch(car){
Mar 19, 2018
1039
case "\t":
Mar 21, 2018
1040
while(col % s > 0){res += " "; col++}
Mar 19, 2018
1042
case "\r":
1043
case "\n":
1044
res += car
1045
col = 0
1046
break
1047
default:
1048
res += car
1049
col++
1050
break
1051
}
1052
pos++
1053
}
Sep 5, 2014
1056
}
1057
str
Feb 10, 2018
1058
str.find = function(){
1059
// Return the lowest index in the string where substring sub is found,
1060
// such that sub is contained in the slice s[start:end]. Optional
1061
// arguments start and end are interpreted as in slice notation.
Sep 5, 2014
1062
// Return -1 if sub is not found.
Mar 19, 2018
1063
var $ = $B.args("str.find", 4,
1064
{self: null, sub: null, start: null, end: null},
1065
["self", "sub", "start", "end"],
1066
arguments, {start: 0, end: null}, null, null)
1067
check_str($.sub)
Mar 19, 2018
1070
if(!isinstance($.start, _b_.int)||!isinstance($.end, _b_.int)){
1071
throw _b_.TypeError.$factory("slice indices must be " +
1072
"integers or None or have an __index__ method")}
1073
// Can't use string.substring(start, end) because if end < start,
1074
// Javascript transforms it into substring(end, start)...
1075
var s = ""
1076
for(var i = $.start; i < $.end; i++){
1077
s += $.self.charAt(i)
1078
}
Mar 19, 2018
1080
if($.sub.length == 0 && $.start == $.self.length){return $.self.length}
1081
if(s.length + $.sub.length == 0){return -1}
Mar 19, 2018
1083
var last_search = s.length - $.sub.length
1084
for(var i = 0; i <= last_search; i++){
1085
if(s.substr(i, $.sub.length) == $.sub){return $.start + i}
Sep 5, 2014
1086
}
Sep 5, 2014
1088
}
1089
1090
// Next function used by method .format()
1091
1092
$B.parse_format = function(fmt_string){
Sep 5, 2014
1093
1094
// Parse a "format string", as described in the Python documentation
1095
// Return a format object. For the format string
1096
// a.x[z]!r:...
1097
// the object has attributes :
1098
// - name : "a"
1099
// - name_ext : [".x", "[z]"]
1100
// - conv : r
1101
// - spec : rest of string after :
Sep 5, 2014
1102
Mar 19, 2018
1103
var elts = fmt_string.split(":"),
1104
name,
1105
conv,
1106
spec,
Mar 19, 2018
1107
name_ext = []
Mar 19, 2018
1108
if(elts.length == 1){
1109
// No : in the string : it only contains a name
1110
name = fmt_string
1111
}else{
1112
// name is before the first ":"
1113
// spec (the format specification) is after
1114
name = elts[0]
Mar 19, 2018
1115
spec = elts.splice(1).join(":")
Mar 19, 2018
1118
var elts = name.split("!")
1119
if(elts.length > 1){
1120
name = elts[0]
1121
conv = elts[1] // conversion flag
Sep 5, 2014
1123
Mar 19, 2018
1124
if(name !== undefined){
1125
// "name' may be a subscription or attribute
1126
// Put these "extensions" in the list "name_ext"
1127
function name_repl(match){
1128
name_ext.push(match)
Mar 19, 2018
1129
return ""
1130
}
1131
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1132
name = name.replace(name_ext_re, name_repl)
1133
}
Sep 5, 2014
1134
1135
return {name: name, name_ext: name_ext,
1136
conv: conv, spec: spec || "", string: fmt_string}
Sep 5, 2014
1138
1139
$B.split_format = function(self){
1140
// Parse self to detect formatting instructions
1141
// Create a list "parts" made of sections of the string :
1142
// - elements of even rank are literal text
1143
// - elements of odd rank are "format objects", built from the
1144
// format strings in self (of the form {...})
Mar 19, 2018
1145
var pos = 0,
1146
_len = self.length,
Mar 19, 2018
1148
text = "",
1149
parts = [],
1150
rank = 0
1151
while(pos < _len){
1152
car = self.charAt(pos)
Mar 21, 2018
1153
if(car == "{" && self.charAt(pos + 1) == "{"){
1154
// replace {{ by literal {
Mar 19, 2018
1155
text += "{"
1156
pos += 2
1157
}else if(car == "}" && self.charAt(pos + 1) == "}"){
1158
// replace }} by literal }
Mar 19, 2018
1159
text += "}"
1160
pos += 2
1161
}else if(car == "{"){
1162
// Start of a format string
1164
// Store current literal text
1165
parts.push(text)
1166
1167
// Search the end of the format string, ie the } closing the
1168
// opening {. Since the string can contain other pairs {} for
1169
// nested formatting, an integer nb is incremented for each { and
1170
// decremented for each } ; the end of the format string is
Mar 19, 2018
1171
// reached when nb == 0
1172
var end = pos + 1,
1173
nb = 1
1174
while(end < _len){
1175
if(self.charAt(end) == "{"){nb++; end++}
1176
else if(self.charAt(end) == "}"){
1177
nb--; end++
1178
if(nb == 0){
1179
// End of format string
Mar 19, 2018
1180
var fmt_string = self.substring(pos + 1, end - 1)
1181
1182
// Create a format object, by function parse_format
1183
var fmt_obj = $B.parse_format(fmt_string)
1184
fmt_obj.raw_name = fmt_obj.name
1185
fmt_obj.raw_spec = fmt_obj.spec
1186
1187
// If no name is explicitely provided, use the rank
1188
if(!fmt_obj.name){
Mar 19, 2018
1189
fmt_obj.name = rank + ""
Sep 5, 2014
1192
Mar 19, 2018
1193
if(fmt_obj.spec !== undefined){
1194
// "spec" may contain "nested replacement fields"
1195
// Replace empty fields by the rank in positional
1196
// arguments
1197
function replace_nested(name, key){
1198
if(key == ""){
1199
// Use implicit rank
1200
return "{" + rank++ + "}"
1204
fmt_obj.spec = fmt_obj.spec.replace(/\{(.*?)\}/g,
1205
replace_nested)
1206
}
1208
// Store format object in list "parts"
1209
parts.push(fmt_obj)
Mar 19, 2018
1210
text = ""
1211
break
1212
}
1213
}else{end++}
Sep 5, 2014
1214
}
Mar 19, 2018
1215
if(nb > 0){throw ValueError.$factory("wrong format " + self)}
Mar 19, 2018
1217
}else{text += car; pos++}
Sep 5, 2014
1218
}
1219
if(text){parts.push(text)}
1220
return parts
1221
}
1222
1223
str.format = function(self) {
1224
// Special management of keyword arguments if str.format is called by
1225
// str.format_map(mapping) : the argument "mapping" might not be a
1226
// dictionary
1227
var last_arg = $B.last(arguments)
1228
if(last_arg.$nat == "mapping"){
1229
var mapping = last_arg.mapping,
1230
getitem = $B.$getattr(mapping, "__getitem__")
1231
// Get the rest of the arguments
1232
var args = []
1233
for(var i = 0, len = arguments.length - 1; i < len; i++){
1234
args.push(arguments[i])
1235
}
1236
var $ = $B.args("format", 1, {self: null}, ["self"],
1237
args, {}, "$args", null)
1238
}else{
1239
var $ = $B.args("format", 1, {self: null}, ["self"],
1240
arguments, {}, "$args", "$kw"),
1241
mapping = $.$kw, // dictionary
1242
getitem = function(key){
1243
return _b_.dict.$getitem(mapping, key)
1244
}
1245
}
1246
var parts = $B.split_format($.self)
1247
1248
// Apply formatting to the values passed to format()
Mar 19, 2018
1249
var res = "",
1250
fmt
Mar 19, 2018
1252
for(var i = 0; i < parts.length; i++){
1253
// Literal text is added unchanged
Mar 19, 2018
1254
if(typeof parts[i] == "string"){res += parts[i]; continue}
1256
// Format objects
1257
fmt = parts[i]
1258
1259
if(fmt.spec !== undefined){
1260
// "spec" may contain "nested replacement fields"
1261
// In this case, evaluate them using the positional
1262
// or keyword arguments passed to format()
1263
function replace_nested(name, key){
1264
if(/\d+/.exec(key)){
1265
// If key is numeric, search in positional
1266
// arguments
1267
return _b_.tuple.__getitem__($.$args,
1268
parseInt(key))
1269
}else{
1270
// Else try in keyword arguments
1271
return _b_.dict.__getitem__($.$kw, key)
1272
}
1273
}
1274
fmt.spec = fmt.spec.replace(/\{(.*?)\}/g,
1275
replace_nested)
1276
}
Mar 21, 2018
1277
if(fmt.name.charAt(0).search(/\d/) > -1){
1278
// Numerical reference : use positional arguments
1279
var pos = parseInt(fmt.name),
Feb 11, 2018
1280
value = _b_.tuple.__getitem__($.$args, pos)
1281
}else{
1282
// Use keyword arguments
1283
var value = getitem(fmt.name)
1284
}
1285
// If name has extensions (attributes or subscriptions)
Mar 19, 2018
1286
for(var j = 0; j < fmt.name_ext.length; j++){
1287
var ext = fmt.name_ext[j]
Mar 19, 2018
1288
if(ext.charAt(0) == "."){
1289
// Attribute
1290
value = _b_.getattr(value, ext.substr(1))
1291
}else{
1292
// Subscription
Mar 19, 2018
1293
var key = ext.substr(1, ext.length - 2)
1294
// An index made of digits is transformed into an integer
Mar 19, 2018
1295
if(key.charAt(0).search(/\d/) > -1){key = parseInt(key)}
1296
value = _b_.getattr(value, "__getitem__")(key)
Feb 12, 2018
1299
1300
// If the conversion flag is set, first call a function to convert
1301
// the value
Mar 19, 2018
1302
if(fmt.conv == "a"){value = _b_.ascii(value)}
1303
else if(fmt.conv == "r"){value = _b_.repr(value)}
1304
else if(fmt.conv == "s"){value = _b_.str.$factory(value)}
1306
// Call attribute __format__ to perform the actual formatting
1307
if(value.$is_class || value.$factory){
1308
// For classes, don't use the class __format__ method
1309
res += value.__class__.__format__(value, fmt.spec)
1311
res += $B.$getattr(value, "__format__")(fmt.spec)
Sep 5, 2014
1313
}
Sep 5, 2014
1315
}
1316
1317
str.format_map = function(self, mapping){
1318
var $ = $B.args("format_map", 2, {self: null, mapping: null},
1319
['self', 'mapping'], arguments, {}, null, null)
1320
return str.format(self, {$nat: 'mapping', mapping})
Sep 5, 2014
1321
}
1322
str
Feb 10, 2018
1323
str.index = function(self){
Sep 5, 2014
1324
// Like find(), but raise ValueError when the substring is not found.
1325
var res = str.find.apply(null, arguments)
Mar 19, 2018
1326
if(res === -1){throw _b_.ValueError.$factory("substring not found")}
Sep 5, 2014
1327
return res
1328
}
1329
1330
str.isascii = function(self){
1331
/* Return true if the string is empty or all characters in the string are
1332
ASCII, false otherwise. ASCII characters have code points in the range
1333
U+0000-U+007F. */
1334
for(var i = 0, len = self.length; i < len; i++){
1335
if(self.charCodeAt(i) > 127){return false}
1336
}
1337
return true
1338
}
1339
1340
str.isalnum = function(self){
1341
/* Return true if all characters in the string are alphanumeric and there
1342
is at least one character, false otherwise. A character c is alphanumeric
1343
if one of the following returns True: c.isalpha(), c.isdecimal(),
1344
c.isdigit(), or c.isnumeric(). */
1345
var $ = $B.args("isalnum", 1, {self: null}, ["self"],
1346
arguments, {}, null, null),
1347
char
1348
for(var i = 0, len = self.length; i < len; i++){
1349
char = self.charCodeAt(i)
1350
if(unicode_tables.Ll[char] ||
1351
unicode_tables.Lu[char] ||
1352
unicode_tables.Lm[char] ||
1353
unicode_tables.Lt[char] ||
1354
unicode_tables.Lo[char] ||
1355
unicode_tables.Nd[char] ||
1356
unicode_tables.digits[char] ||
1357
unicode_tables.numeric[char]){
1358
continue
1359
}
1360
return false
1361
}
1362
return true
1363
}
1364
1365
str.isalpha = function(self){
1366
/* Return true if all characters in the string are alphabetic and there is
1367
at least one character, false otherwise. Alphabetic characters are those
1368
characters defined in the Unicode character database as "Letter", i.e.,
1369
those with general category property being one of "Lm", "Lt", "Lu", "Ll",
1370
or "Lo". */
1371
var $ = $B.args("isalpha", 1, {self: null}, ["self"],
1372
arguments, {}, null, null),
1373
char
1374
for(var i = 0, len = self.length; i < len; i++){
1375
char = self.charCodeAt(i)
1376
if(unicode_tables.Ll[char] ||
1377
unicode_tables.Lu[char] ||
1378
unicode_tables.Lm[char] ||
1379
unicode_tables.Lt[char] ||
1380
unicode_tables.Lo[char]){
1381
continue
1382
}
1383
return false
1384
}
1385
return true
1386
}
1387
1388
str.isdecimal = function(self){
1389
/* Return true if all characters in the string are decimal characters and
1390
there is at least one character, false otherwise. Decimal characters are
1391
those that can be used to form numbers in base 10, e.g. U+0660,
1392
ARABIC-INDIC DIGIT ZERO. Formally a decimal character is a character in
1393
the Unicode General Category "Nd". */
1394
var $ = $B.args("isdecimal", 1, {self: null}, ["self"],
1395
arguments, {}, null, null),
1396
char
1397
for(var i = 0, len = self.length; i < len; i++){
1398
char = self.charCodeAt(i)
1399
if(! unicode_tables.Nd[char]){
1400
return false
1401
}
1402
}
1403
return self.length > 0
1404
}
1405
1406
str.isdigit = function(self){
1407
/* Return true if all characters in the string are digits and there is at
1408
least one character, false otherwise. */
1409
var $ = $B.args("isdigit", 1, {self: null}, ["self"],
1410
arguments, {}, null, null),
1411
char
1412
for(var i = 0, len = self.length; i < len; i++){
1413
char = self.charCodeAt(i)
1414
if(! unicode_tables.digits[char]){
1415
return false
1416
}
1417
}
1418
return self.length > 0
1419
}
1420
1421
str.isidentifier = function(self){
1422
/* Return true if the string is a valid identifier according to the
1423
language definition. */
1424
var $ = $B.args("isidentifier", 1, {self: null}, ["self"],
1425
arguments, {}, null, null),
1426
char
1427
if(self.length == 0){
1428
return false
1429
}else if(unicode_tables.XID_Start[self.charCodeAt(0)] === undefined){
1430
return false
1431
}else{
1432
for(var i = 1, len = self.length; i < len; i++){
1433
if(unicode_tables.XID_Continue[self.charCodeAt(i)] === undefined){
1434
return false
1435
}
1436
}
1437
}
1438
return true
1439
}
1440
1441
str.islower = function(self){
1442
/* Return true if all cased characters 4 in the string are lowercase and
1443
there is at least one cased character, false otherwise. */
1444
var $ = $B.args("islower", 1, {self: null}, ["self"],
1445
arguments, {}, null, null),
1446
has_cased = false,
1447
char
1448
1449
for(var i = 0, len = self.length; i < len; i++){
1450
char = self.charCodeAt(i)
1451
if(unicode_tables.Ll[char]){has_cased = true; continue}
1452
else if(unicode_tables.Lu[char] || unicode_tables.Lt[char]){
1453
return false
1454
}
1455
}
1456
return has_cased
1457
}
1458
1459
str.isnumeric = function(self){
1460
/* Return true if all characters in the string are numeric characters, and
1461
there is at least one character, false otherwise. Numeric characters
1462
include digit characters, and all characters that have the Unicode numeric
1463
value property, e.g. U+2155, VULGAR FRACTION ONE FIFTH. Formally, numeric
1464
characters are those with the property value Numeric_Type=Digit,
1465
Numeric_Type=Decimal or Numeric_Type=Numeric.*/
1466
var $ = $B.args("isnumeric", 1, {self: null}, ["self"],
1467
arguments, {}, null, null)
1468
for(var i = 0, len = self.length; i < len; i++){
1469
if(! unicode_tables.numeric[self.charCodeAt(i)]){
1470
return false
1471
}
1472
}
1473
return self.length > 0
1474
}
1475
1476
var unprintable = {},
1477
unprintable_gc = ['Cc', 'Cf', 'Co', 'Cs','Zl', 'Zp', 'Zs']
1478
1479
str.isprintable = function(self){
1480
/* Return true if all characters in the string are printable or the string
1481
is empty, false otherwise. Nonprintable characters are those characters
1482
defined in the Unicode character database as "Other" or "Separator",
1483
excepting the ASCII space (0x20) which is considered printable. */
1484
1485
// Set unprintable if not set yet
1486
if(Object.keys(unprintable).length == 0){
1487
for(var i = 0; i < unprintable_gc.length; i++){
1488
var table = unicode_tables[unprintable_gc[i]]
1490
unprintable[cp] = true
1493
unprintable[32] = true
1494
}
1495
var $ = $B.args("isprintable", 1, {self: null}, ["self"],
1496
arguments, {}, null, null)
1497
for(var i = 0, len = self.length; i < len; i++){
1498
if(unprintable[self.charCodeAt(i)]){
1499
return false
1500
}
1501
}
1502
return true
1503
}
1504
1505
str.isspace = function(self){
1506
/* Return true if there are only whitespace characters in the string and
1507
there is at least one character, false otherwise.
1508
1509
A character is whitespace if in the Unicode character database, either its
1510
general category is Zs ("Separator, space"), or its bidirectional class is
1511
one of WS, B, or S.*/
1512
var $ = $B.args("isspace", 1, {self: null}, ["self"],
1513
arguments, {}, null, null),
1514
char
1515
for(var i = 0, len = self.length; i < len; i++){
1516
char = self.charCodeAt(i)
1517
if(! unicode_tables.Zs[char] &&
1518
$B.unicode_bidi_whitespace.indexOf(char) == -1){
1519
return false
1520
}
1521
}
1522
return self.length > 0
1523
}
1524
1525
str.istitle = function(self){
1526
/* Return true if the string is a titlecased string and there is at least
1527
one character, for example uppercase characters may only follow uncased
1528
characters and lowercase characters only cased ones. Return false
1529
otherwise. */
1530
var $ = $B.args("istitle", 1, {self: null}, ["self"],
1531
arguments, {}, null, null)
1532
return self.length > 0 && str.title(self) == self
1533
}
1534
1535
str.isupper = function(self){
1536
/* Return true if all cased characters 4 in the string are lowercase and
1537
there is at least one cased character, false otherwise. */
1538
var $ = $B.args("islower", 1, {self: null}, ["self"],
1539
arguments, {}, null, null),
1540
has_cased = false,
1541
char
1542
1543
for(var i = 0, len = self.length; i < len; i++){
1544
char = self.charCodeAt(i)
1545
if(unicode_tables.Lu[char]){has_cased = true; continue}
1546
else if(unicode_tables.Ll[char] || unicode_tables.Lt[char]){
1547
return false
1548
}
1549
}
1550
return has_cased
1551
}
1552
1553
str
Feb 10, 2018
1554
str.join = function(){
Mar 19, 2018
1555
var $ = $B.args("join", 2, {self: null, iterable: null},
Mar 19, 2018
1556
["self", "iterable"], arguments, {}, null, null)
Mar 19, 2018
1558
var iterable = _b_.iter($.iterable),
Mar 19, 2018
1559
res = [],
Sep 5, 2014
1561
while(1){
1562
try{
1563
var obj2 = _b_.next(iterable)
Mar 19, 2018
1564
if(! isinstance(obj2, str)){throw _b_.TypeError.$factory(
1565
"sequence item " + count + ": expected str instance, " +
1566
$B.class_name(obj2) + " found")}
1567
res.push(obj2)
Sep 5, 2014
1568
}catch(err){
1569
if(_b_.isinstance(err, _b_.StopIteration)){
1570
break
1571
}
Sep 5, 2014
1572
else{throw err}
1573
}
1574
}
1575
return res.join($.self)
Sep 5, 2014
1576
}
1577
str
Feb 10, 2018
1578
str.ljust = function(self) {
Mar 19, 2018
1579
var $ = $B.args("ljust", 3, {self: null, width: null, fillchar:null},
1580
["self", "width", "fillchar"],
1581
arguments, {fillchar: " "}, null, null)
Mar 19, 2018
1583
if($.width <= self.length){return self}
1584
return self + $.fillchar.repeat($.width - self.length)
Sep 5, 2014
1585
}
1586
1587
str.lower = function(self){
1588
var $ = $B.args("lower", 1, {self: null}, ["self"],
1589
arguments, {}, null, null)
1590
return self.toLowerCase()
1591
}
1592
str
Feb 10, 2018
1593
str.lstrip = function(self,x){
Mar 19, 2018
1594
var $ = $B.args("lstrip", 2, {self: null, chars: null}, ["self", "chars"],
1595
arguments, {chars:_b_.None}, null, null)
1596
if($.chars === _b_.None){return $.self.trimLeft()}
1597
for(var i = 0; i < $.self.length; i++){
1598
if($.chars.indexOf($.self.charAt(i)) === -1){
1599
return $.self.substring(i)
Mar 19, 2018
1602
return ""
Sep 5, 2014
1603
}
1604
1605
// note, maketrans should be a static function.
str
Feb 10, 2018
1606
str.maketrans = function() {
Mar 19, 2018
1607
var $ = $B.args("maketrans", 3, {x: null, y: null, z: null},
1608
["x", "y", "z"], arguments, {y: null, z: null}, null, null)
Mar 19, 2018
1612
if($.y === null && $.z === null){
1613
// If there is only one argument, it must be a dictionary mapping
1614
// Unicode ordinals (integers) or characters (strings of length 1) to
1615
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1616
// keys will then be converted to ordinals.
Mar 19, 2018
1617
if(! _b_.isinstance($.x, _b_.dict)){
1618
throw _b_.TypeError.$factory(
1619
"maketrans only argument must be a dict")
Feb 11, 2018
1621
var items = _b_.list.$factory(_b_.dict.items($.x))
Mar 19, 2018
1622
for(var i = 0, len = items.length; i < len; i++){
1623
var k = items[i][0],
1624
v = items[i][1]
1625
if(! _b_.isinstance(k, _b_.int)){
1626
if(_b_.isinstance(k, _b_.str) && k.length == 1){
1627
k = _b_.ord(k)
1628
}else{throw _b_.TypeError.$factory("dictionary key " + k +
1629
" is not int or 1-char string")}
1630
}
Mar 19, 2018
1631
if(v !== _b_.None && ! _b_.isinstance(v, [_b_.int, _b_.str])){
1632
throw _b_.TypeError.$factory("dictionary value " + v +
1633
" is not None, integer or string")
1634
}
1635
_b_.dict.$setitem(_t, k, v)
1636
}
1637
return _t
1638
}else{
1639
// If there are two arguments, they must be strings of equal length,
1640
// and in the resulting dictionary, each character in x will be mapped
1641
// to the character at the same position in y
Mar 19, 2018
1642
if(! (_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1643
throw _b_.TypeError.$factory("maketrans arguments must be strings")
Mar 19, 2018
1644
}else if($.x.length !== $.y.length){
1645
throw _b_.TypeError.$factory(
1646
"maketrans arguments must be strings or same length")
1647
}else{
1648
var toNone = {}
Mar 19, 2018
1649
if($.z !== null){
1650
// If there is a third argument, it must be a string, whose
1651
// characters will be mapped to None in the result
Mar 19, 2018
1652
if(! _b_.isinstance($.z, _b_.str)){
1653
throw _b_.TypeError.$factory(
1654
"maketrans third argument must be a string")
Mar 19, 2018
1656
for(var i = 0, len = $.z.length; i < len; i++){
1657
toNone[_b_.ord($.z.charAt(i))] = true
1658
}
Mar 19, 2018
1660
for(var i = 0, len = $.x.length; i < len; i++){
1661
var key = _b_.ord($.x.charAt(i)),
1663
_b_.dict.$setitem(_t, key, value)
1664
}
1665
for(var k in toNone){
1666
_b_.dict.$setitem(_t, parseInt(k), _b_.None)
1667
}
1668
return _t
1669
}
1670
}
Sep 5, 2014
1671
}
1672
1673
str.maketrans.$type = "staticmethod"
1674
str
Feb 10, 2018
1675
str.partition = function() {
Mar 19, 2018
1676
var $ = $B.args("partition", 2, {self: null, sep: null}, ["self", "sep"],
1677
arguments, {}, null, null)
Mar 19, 2018
1678
if($.sep == ""){throw _b_.ValueError.$factory("empty separator")}
Mar 19, 2018
1679
check_str($.sep)
1680
var i = $.self.indexOf($.sep)
Mar 23, 2018
1681
if(i == -1){return _b_.tuple.$factory([$.self, "", ""])}
Mar 19, 2018
1682
return _b_.tuple.$factory([$.self.substring(0, i), $.sep,
1683
$.self.substring(i + $.sep.length)])
1684
}
1685
1686
str.removeprefix = function(){
1687
var $ = $B.args("removeprefix", 2, {self: null, prefix: null},
1688
["self", "prefix"], arguments, {}, null, null)
1689
if(!_b_.isinstance($.prefix, str)){
1690
throw _b_.ValueError.$factory("prefix should be str, not " +
1691
`'${$B.class_name($.prefix)}'`)
1692
}
1693
if(str.startswith($.self, $.prefix)){
1694
return $.self.substr($.prefix.length)
1695
}
1696
return $.self.substr(0)
1697
}
1698
1699
str.removesuffix = function(){
1700
var $ = $B.args("removesuffix", 2, {self: null, prefix: null},
1701
["self", "suffix"], arguments, {}, null, null)
1702
if(!_b_.isinstance($.suffix, str)){
1703
throw _b_.ValueError.$factory("suffix should be str, not " +
1704
`'${$B.class_name($.prefix)}'`)
1705
}
1706
if($.suffix.length > 0 && str.endswith($.self, $.suffix)){
1707
return $.self.substr(0, $.self.length - $.suffix.length)
1708
}
1709
return $.self.substr(0)
1710
}
1711
Mar 19, 2018
1712
function $re_escape(str){
1713
var specials = "[.*+?|()$^"
1714
for(var i = 0, len = specials.length; i < len; i++){
1715
var re = new RegExp("\\"+specials.charAt(i), "g")
1716
str = str.replace(re, "\\"+specials.charAt(i))
1717
}
1718
return str
Sep 5, 2014
1719
}
1720
str
Feb 10, 2018
1721
str.replace = function(self, old, _new, count) {
1722
// Replaces occurrences of 'old' by '_new'. Count references
1723
// the number of times to replace. In CPython, negative or undefined
1724
// values of count means replace all.
Mar 19, 2018
1725
var $ = $B.args("replace", 4,
1726
{self: null, old: null, $$new: null, count: null},
1727
["self", "old", "$$new", "count"],
1728
arguments, {count: -1}, null, null),
1729
count = $.count,
1730
self = $.self,
1731
old = $.old,
1732
_new = $.$$new
1733
// Validate type of old
1734
check_str(old)
1735
check_str(_new)
1736
// Validate instance type of 'count'
Mar 23, 2018
1737
if(! isinstance(count,[_b_.int, _b_.float])){
1738
throw _b_.TypeError.$factory("'" + $B.class_name(count) +
Mar 19, 2018
1739
"' object cannot be interpreted as an integer")
1740
}else if(isinstance(count, _b_.float)){
1741
throw _b_.TypeError.$factory("integer argument expected, got float")
1742
}
1743
if(count == 0){return self}
1744
if(count.__class__ == $B.long_int){count = parseInt(count.value)}
1745
if(old == ""){
1746
if(_new == ""){return self}
1747
if(self == ""){return _new}
1748
var elts = self.split("")
1749
if(count > -1 && elts.length >= count){
1750
var rest = elts.slice(count).join("")
1751
return _new + elts.slice(0, count).join(_new) + rest
1752
}else{return _new + elts.join(_new) + _new}
Mar 19, 2018
1754
var elts = str.split(self, old, count)
Sep 5, 2014
1755
}
Mar 19, 2018
1757
var res = self,
1758
pos = -1
1759
if(old.length == 0){
Mar 19, 2018
1761
for(var i = 0; i < elts.length; i++){
1762
res += elts[i] + _new
Mar 19, 2018
1764
return res + rest
Mar 19, 2018
1767
if(count < 0){count = res.length}
1768
while(count > 0){
1769
pos = res.indexOf(old, pos)
1770
if(pos < 0){break}
1771
res = res.substr(0, pos) + _new + res.substr(pos + old.length)
1772
pos = pos + _new.length
1773
count--
Mar 19, 2018
1775
return res
Sep 5, 2014
1776
}
1777
1778
str.rfind = function(self, substr){
1779
// Return the highest index in the string where substring sub is found,
1780
// such that sub is contained within s[start:end]. Optional arguments
Sep 5, 2014
1781
// start and end are interpreted as in slice notation. Return -1 on failure.
1782
if(arguments.length == 2 && typeof substr == "string"){
1783
return self.lastIndexOf(substr)
1784
}
Mar 19, 2018
1785
var $ = $B.args("rfind", 4,
Mar 19, 2018
1786
{self: null, sub: null, start: null, end: null},
1787
["self", "sub", "start", "end"],
1788
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
1789
1792
check_str($.sub)
Mar 19, 2018
1794
if($.sub.length == 0){
1795
if($.start > $.self.length){return -1}
1796
else{return $.self.length}
1797
}
1798
var sublen = $.sub.length
Mar 19, 2018
1800
for(var i = $.end - sublen; i >= $.start; i--){
1801
if($.self.substr(i, sublen) == $.sub){return i}
Sep 5, 2014
1804
}
1805
str
Feb 10, 2018
1806
str.rindex = function(){
Sep 5, 2014
1807
// Like rfind() but raises ValueError when the substring sub is not found
Mar 19, 2018
1808
var res = str.rfind.apply(null, arguments)
1809
if(res == -1){throw _b_.ValueError.$factory("substring not found")}
Sep 5, 2014
1810
return res
1811
}
1812
str
Feb 10, 2018
1813
str.rjust = function(self) {
Mar 19, 2018
1814
var $ = $B.args("rjust",3,
1815
{self: null, width: null, fillchar: null},
1816
["self", "width", "fillchar"],
1817
arguments, {fillchar: " "}, null, null)
Sep 5, 2014
1818
Mar 19, 2018
1819
if($.width <= self.length){return self}
Sep 5, 2014
1820
1821
return $.fillchar.repeat($.width - self.length) + self
Sep 5, 2014
1822
}
1823
str
Feb 10, 2018
1824
str.rpartition = function(self,sep) {
Mar 19, 2018
1825
var $ = $B.args("rpartition", 2, {self: null, sep: null}, ["self", "sep"],
1826
arguments, {}, null, null)
1827
check_str($.sep)
1828
var self = reverse($.self),
1829
sep = reverse($.sep)
Mar 19, 2018
1830
var items = str.partition(self, sep).reverse()
1831
for(var i = 0; i < items.length; i++){
1832
items[i] = items[i].split("").reverse().join("")
1833
}
1834
return items
Sep 5, 2014
1835
}
1836
str
Feb 10, 2018
1837
str.rsplit = function(self) {
Mar 19, 2018
1838
var $ = $B.args("rsplit", 3, {self: null, sep: null, maxsplit: null},
1839
["self", "sep", "maxsplit"], arguments,
1840
{sep: _b_.None, maxsplit: -1}, null, null),
1841
sep = $.sep
1842
1843
// Use split on the reverse of the string and of separator
1844
var rev_str = reverse($.self),
1845
rev_sep = sep === _b_.None ? sep : reverse($.sep),
str
Feb 10, 2018
1846
rev_res = str.split(rev_str, rev_sep, $.maxsplit)
1848
// Reverse the list, then each string inside the list
1849
rev_res.reverse()
Mar 19, 2018
1850
for(var i = 0; i < rev_res.length; i++){
1851
rev_res[i] = reverse(rev_res[i])
Sep 5, 2014
1854
}
1855
Mar 19, 2018
1856
str.rstrip = function(self, x){
1857
var $ = $B.args("rstrip", 2, {self: null, chars: null}, ["self", "chars"],
Mar 19, 2018
1858
arguments, {chars: _b_.None}, null, null)
1859
if($.chars === _b_.None){return $.self.trimRight()}
Mar 21, 2018
1860
for(var j = $.self.length - 1; j >= 0; j--){
Mar 19, 2018
1861
if($.chars.indexOf($.self.charAt(j)) == -1){
1862
return $.self.substring(0, j + 1)
Mar 19, 2018
1865
return ""
Sep 5, 2014
1866
}
1867
str
Feb 10, 2018
1868
str.split = function(){
Mar 19, 2018
1869
var $ = $B.args("split", 3, {self: null, sep: null, maxsplit: null},
1870
["self", "sep", "maxsplit"], arguments,
1871
{sep: _b_.None, maxsplit: -1}, null, null),
1872
sep = $.sep,
1873
maxsplit = $.maxsplit,
1874
self = $.self,
1875
pos = 0
1876
if(maxsplit.__class__ === $B.long_int){maxsplit = parseInt(maxsplit.value)}
1877
if(sep == ""){throw _b_.ValueError.$factory("empty separator")}
1878
if(sep === _b_.None){
Sep 5, 2014
1879
var res = []
Mar 19, 2018
1880
while(pos < self.length && self.charAt(pos).search(/\s/) > -1){pos++}
1881
if(pos === self.length - 1){return [self]}
1882
var name = ""
Sep 5, 2014
1883
while(1){
Mar 19, 2018
1884
if(self.charAt(pos).search(/\s/) == -1){
1885
if(name == ""){name = self.charAt(pos)}
1886
else{name += self.charAt(pos)}
Sep 5, 2014
1887
}else{
Mar 19, 2018
1888
if(name !== ""){
Sep 5, 2014
1889
res.push(name)
Mar 19, 2018
1890
if(maxsplit !== -1 && res.length == maxsplit + 1){
Sep 5, 2014
1891
res.pop()
Mar 19, 2018
1892
res.push(name + self.substr(pos))
Sep 5, 2014
1893
return res
1894
}
Mar 19, 2018
1895
name = ""
Sep 5, 2014
1896
}
1897
}
1898
pos++
Mar 19, 2018
1899
if(pos > self.length - 1){
Sep 5, 2014
1900
if(name){res.push(name)}
1901
break
1902
}
1903
}
1904
return res
1905
}else{
Mar 19, 2018
1906
var res = [],
1907
s = "",
1908
seplen = sep.length
1909
if(maxsplit == 0){return [self]}
1910
while(pos < self.length){
1911
if(self.substr(pos, seplen) == sep){
Mar 19, 2018
1914
if(maxsplit > -1 && res.length >= maxsplit){
1915
res.push(self.substr(pos))
1916
return res
1917
}
Mar 19, 2018
1918
s = ""
1919
}else{
1920
s += self.charAt(pos)
1921
pos++
Sep 5, 2014
1922
}
1923
}
Sep 5, 2014
1926
}
1927
}
1928
1929
str.splitlines = function(self) {
1930
var $ = $B.args('splitlines', 2, {self: null, keepends: null},
1931
['self','keepends'], arguments, {keepends: false},
1932
null, null)
1933
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1934
throw _b_.TypeError('integer argument expected, got '+
1935
$B.get_class($.keepends).__name)
1936
}
1937
var keepends = _b_.int.$factory($.keepends),
1938
res = [],
1939
self = $.self,
1940
start = 0,
1941
pos = 0
1942
if(!self.length){
1943
return res
1944
}
1945
while (pos < self.length) {
1946
if(self.substr(pos, 2) == '\r\n'){
1947
res.push(self.slice(start, keepends ? pos + 2 : pos))
1948
start = pos = pos+2
1949
}else if(self[pos] == '\r' || self[pos] == '\n'){
1950
res.push(self.slice(start, keepends ? pos+1 : pos))
1951
start = pos = pos+1
1952
}else{
1953
pos++
1954
}
1955
}
1956
if(start < self.length){
1957
res.push(self.slice(start))
1958
}
1959
return res
1960
}
Sep 5, 2014
1961
str
Feb 10, 2018
1962
str.startswith = function(){
1963
// Return True if string starts with the prefix, otherwise return False.
1964
// prefix can also be a tuple of prefixes to look for. With optional
1965
// start, test string beginning at that position. With optional end,
Sep 5, 2014
1966
// stop comparing string at that position.
Mar 19, 2018
1967
var $ = $B.args("startswith", 4,
1968
{self: null, prefix: null, start: null, end: null},
1969
["self", "prefix", "start", "end"],
1970
arguments, {start: 0, end: null}, null, null)
Sep 5, 2014
1971
1972
normalize_start_end($)
1973
1974
var prefixes = $.prefix
Mar 19, 2018
1975
if(! isinstance(prefixes, _b_.tuple)){prefixes = [prefixes]}
Mar 19, 2018
1977
var s = $.self.substring($.start, $.end)
1978
for(var i = 0, len = prefixes.length; i < len; i++){
1979
var prefix = prefixes[i]
Mar 19, 2018
1980
if(! _b_.isinstance(prefix, str)){throw _b_.TypeError.$factory(
1981
"endswith first arg must be str or a tuple of str, not int")}
Mar 19, 2018
1982
if(s.substr(0, prefix.length) == prefix){return true}
Sep 5, 2014
1983
}
1984
return false
1985
Sep 5, 2014
1986
}
1987
str
Feb 10, 2018
1988
str.strip = function(){
Mar 19, 2018
1989
var $ = $B.args("strip", 2, {self: null, chars: null}, ["self", "chars"],
1990
arguments, {chars: _b_.None}, null, null)
1991
if($.chars === _b_.None){return $.self.trim()}
1992
for(var i = 0; i < $.self.length; i++){
1993
if($.chars.indexOf($.self.charAt(i)) == -1){
1994
break
Mar 19, 2018
1997
for(var j = $.self.length - 1; j >= i; j--){
1998
if($.chars.indexOf($.self.charAt(j)) == -1){
1999
break
Mar 19, 2018
2002
return $.self.substring(i, j + 1)
Sep 5, 2014
2003
}
2004
2005
str.swapcase = function(self){
2006
var $ = $B.args("swapcase", 1, {self}, ["self"],
2007
arguments, {}, null, null),
2008
res = "",
2009
char
2010
2011
for(var i = 0, len = self.length; i < len; i++){
2012
char = self.charCodeAt(i)
2013
if(unicode_tables.Ll[char]){
2014
res += self.charAt(i).toUpperCase()
2015
}else if(unicode_tables.Lu[char]){
2016
res += self.charAt(i).toLowerCase()
2017
}else{
2018
res += self.charAt(i)
2019
}
2020
}
2021
return res
2022
}
2023
2024
str.title = function(self){
2025
var $ = $B.args("title", 1, {self}, ["self"],
2026
arguments, {}, null, null),
2027
state,
2028
char,
2029
res = ""
2030
for(var i = 0, len = self.length; i < len; i++){
2031
char = self.charCodeAt(i)
2032
if(unicode_tables.Ll[char]){
2033
if(! state){
2034
res += self.charAt(i).toUpperCase()
2035
state = "word"
2036
}else{
2037
res += self.charAt(i)
2038
}
2039
}else if(unicode_tables.Lu[char] || unicode_tables.Lt[char]){
2040
res += state ? self.charAt(i).toLowerCase() : self.charAt(i)
2041
state = "word"
2042
}else{
2043
state = null
2044
res += self.charAt(i)
2045
}
2046
}
2047
return res
2048
}
2049
2050
str.translate = function(self, table){
Mar 19, 2018
2051
var res = [],
2052
getitem = $B.$getattr(table, "__getitem__")
2053
for(var i = 0, len = self.length; i < len; i++){
2054
try{
2055
var repl = getitem(self.charCodeAt(i))
2056
if(repl !== _b_.None){
2057
if(typeof repl == "string"){
2058
res.push(repl)
2059
}else if(typeof repl == "number"){
2060
res.push(String.fromCharCode(repl))
2061
}
2062
}
2063
}catch(err){
2064
res.push(self.charAt(i))
2065
}
Sep 5, 2014
2066
}
Mar 19, 2018
2067
return res.join("")
Sep 5, 2014
2068
}
2069
2070
str.upper = function(self){
2071
var $ = $B.args("upper", 1, {self: null}, ["self"],
2072
arguments, {}, null, null)
2073
return self.toUpperCase()
2074
}
2075
Mar 19, 2018
2076
str.zfill = function(self, width){
Mar 19, 2018
2077
var $ = $B.args("zfill", 2, {self: null, width: null},
Mar 19, 2018
2078
["self", "width"], arguments, {}, null, null)
2079
if($.width <= self.length){return self}
Mar 19, 2018
2081
case "+":
2082
case "-":
2083
return self.charAt(0) +
2084
"0".repeat($.width - self.length) + self.substr(1)
Mar 19, 2018
2086
return "0".repeat(width - self.length) + self
Sep 5, 2014
2088
}
2089
2090
str.$factory = function(arg, encoding, errors){
2091
if(arguments.length == 0){return ""}
2093
return $B.UndefinedClass.__str__()
2094
}else if(arg === null){
2095
return '<Javascript null>'
2097
if(encoding !== undefined){
2098
// Arguments may be passed as keywords (cf. issue #1060)
2099
var $ = $B.args("str", 3, {arg: null, encoding: null, errors: null},
2100
["arg", "encoding", "errors"], arguments,
2101
{encoding: "utf-8", errors: "strict"}, null, null),
2102
encoding = $.encoding,
2103
errors = $.errors
2104
}
2105
switch(typeof arg) {
Mar 19, 2018
2106
case "string":
Mar 27, 2019
2107
return str.__str__(arg)
Mar 19, 2018
2108
case "number":
2109
if(isFinite(arg)){return arg.toString()}
2112
if(arg.$is_class || arg.$factory){
2113
// arg is a class
2114
// In this case, str() doesn't use the attribute __str__ of the
2115
// class or its subclasses, but the attribute __str__ of the
2116
// class metaclass (usually "type") or its subclasses (usually
2117
// "object")
2118
// The metaclass is the attribute __class__ of the class dictionary
Mar 19, 2018
2119
var func = $B.$getattr(arg.__class__, "__str__")
2121
}
2123
if(arg.__class__ && arg.__class__ === _b_.bytes &&
2124
encoding !== undefined){
2125
// str(bytes, encoding, errors) is equal to
2126
// bytes.decode(encoding, errors)
2127
return _b_.bytes.decode(arg, $.encoding, $.errors)
2129
// Implicit invocation of __str__ uses method __str__ on the class,
2130
// even if arg has an attribute __str__
2131
var klass = arg.__class__ || $B.get_class(arg)
2133
return $B.JSObj.__str__($B.JSObj.$factory(arg))
2135
var method = $B.$getattr(klass , "__str__", null)
2136
if(method === null ||
2137
// if not better than object.__str__, try __repr__
2138
(arg.__class__ && arg.__class__ !== _b_.object &&
2139
method.$infos && method.$infos.__func__ === _b_.object.__str__)){
2140
var method = $B.$getattr(klass, "__repr__")
Sep 5, 2014
2142
}
2143
catch(err){
2144
console.log("no __str__ for", arg)
Mar 19, 2018
2145
console.log("err ", err)
2146
if($B.debug > 1){console.log(err)}
2147
console.log("Warning - no method __str__ or __repr__, " +
2148
"default to toString", arg)
May 20, 2019
2149
throw err
Sep 5, 2014
2150
}
2151
return $B.$call(method)(arg)
Sep 5, 2014
2152
}
str
Feb 10, 2018
2153
2154
str.__new__ = function(cls){
Mar 19, 2018
2155
if(cls === undefined){
2156
throw _b_.TypeError.$factory("str.__new__(): not enough arguments")
Sep 5, 2014
2157
}
Mar 19, 2018
2158
return {__class__: cls}
Sep 5, 2014
2159
}
2160
str
Feb 10, 2018
2161
$B.set_func_names(str, "builtins")
Sep 5, 2014
2163
// dictionary and factory for subclasses of string
str
Feb 10, 2018
2164
var StringSubclass = $B.StringSubclass = {
Mar 19, 2018
2165
__class__: _b_.type,
str
Feb 10, 2018
2166
__mro__: [object],
2167
$infos: {
2168
__module__: "builtins",
2169
__name__: "str"
2170
},
str
Feb 10, 2018
2171
$is_class: true
Sep 5, 2014
2172
}
2173
str
Feb 10, 2018
2174
// the methods in subclass apply the methods in str to the
Sep 5, 2014
2175
// result of instance.valueOf(), which is a Javascript string
str
Feb 10, 2018
2176
for(var $attr in str){
Mar 19, 2018
2177
if(typeof str[$attr] == "function"){
Mar 19, 2018
2178
StringSubclass[$attr] = (function(attr){
Sep 5, 2014
2179
return function(){
Mar 19, 2018
2180
var args = [],
2181
pos = 0
2182
if(arguments.length > 0){
2183
var args = [arguments[0].valueOf()],
2184
pos = 1
2185
for(var i = 1, len = arguments.length; i < len; i++){
2186
args[pos++] = arguments[i]
Sep 5, 2014
2187
}
2188
}
Mar 19, 2018
2189
return str[attr].apply(null, args)
Sep 5, 2014
2190
}
2191
})($attr)
2192
}
2193
}
2194
str
Feb 10, 2018
2195
StringSubclass.__new__ = function(cls){
Sep 5, 2014
2198
str
Feb 10, 2018
2199
$B.set_func_names(StringSubclass, "builtins")
Sep 5, 2014
2201
_b_.str = str
2202
2203
// Function to parse the 2nd argument of format()
2204
$B.parse_format_spec = function(spec){
Mar 19, 2018
2205
if(spec == ""){this.empty = true}
2206
else{
Mar 19, 2018
2207
var pos = 0,
2208
aligns = "<>=^",
2209
digits = "0123456789",
2210
types = "bcdeEfFgGnosxX%",
2211
align_pos = aligns.indexOf(spec.charAt(0))
Mar 19, 2018
2212
if(align_pos != -1){
2213
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1)) != -1){
2214
// If the second char is also an alignment specifier, the
2215
// first char is the fill value
2216
this.fill = spec.charAt(0)
2217
this.align = spec.charAt(1)
2218
pos = 2
2219
}else{
2220
// The first character defines alignment : fill defaults to ' '
Mar 19, 2018
2221
this.align = aligns[align_pos]
2222
this.fill = " "
2223
pos++
2224
}
2225
}else{
2226
align_pos = aligns.indexOf(spec.charAt(1))
Mar 19, 2018
2227
if(spec.charAt(1) && align_pos != -1){
2228
// The second character defines alignment : fill is the first one
Mar 19, 2018
2229
this.align = aligns[align_pos]
2230
this.fill = spec.charAt(0)
2231
pos = 2
2232
}
2233
}
2234
var car = spec.charAt(pos)
Mar 19, 2018
2235
if(car == "+" || car == "-" || car == " "){
2236
this.sign = car
2237
pos++
2238
car = spec.charAt(pos)
Mar 19, 2018
2240
if(car == "#"){this.alternate = true; pos++; car = spec.charAt(pos)}
2241
if(car == "0"){
Mar 19, 2018
2242
// sign-aware : equivalent to fill = 0 and align == "="
Mar 19, 2018
2243
this.fill = "0"
2244
if(align_pos == -1){
2245
this.align = "="
2246
}
Mar 19, 2018
2247
pos++
2248
car = spec.charAt(pos)
2249
}
Mar 19, 2018
2250
while(car && digits.indexOf(car) > -1){
2251
if(this.width === undefined){this.width = car}
2252
else{this.width += car}
2253
pos++
2254
car = spec.charAt(pos)
Mar 19, 2018
2256
if(this.width !== undefined){this.width = parseInt(this.width)}
2257
if(this.width === undefined && car == "{"){
2258
// Width is determined by a parameter
2259
var end_param_pos = spec.substr(pos).search("}")
2260
this.width = spec.substring(pos, end_param_pos)
2261
console.log("width", "[" + this.width + "]")
2262
pos += end_param_pos + 1
2263
}
Mar 19, 2018
2264
if(car == ","){this.comma = true; pos++; car = spec.charAt(pos)}
2265
if(car == "."){
2266
if(digits.indexOf(spec.charAt(pos + 1)) == -1){
2267
throw _b_.ValueError.$factory(
2268
"Missing precision in format spec")
Mar 19, 2018
2270
this.precision = spec.charAt(pos + 1)
2271
pos += 2
2272
car = spec.charAt(pos)
2273
while(car && digits.indexOf(car) > -1){
Mar 21, 2018
2274
this.precision += car
Mar 19, 2018
2275
pos++
2276
car = spec.charAt(pos)
2277
}
2278
this.precision = parseInt(this.precision)
2279
}
Mar 19, 2018
2280
if(car && types.indexOf(car) > -1){
2281
this.type = car
2282
pos++
2283
car = spec.charAt(pos)
2284
}
2285
if(pos !== spec.length){
2286
throw _b_.ValueError.$factory("Invalid format specifier: " + spec)
2290
this.toString = function(){
Mar 19, 2018
2291
return (this.fill === undefined ? "" : _b_.str.$factory(this.fill)) +
2292
(this.align || "") +
2293
(this.sign || "") +
2294
(this.alternate ? "#" : "") +
2295
(this.sign_aware ? "0" : "") +
2296
(this.width || "") +
2297
(this.comma ? "," : "") +
2298
(this.precision ? "." + this.precision : "") +
2299
(this.type || "")
2300
}
2301
}
2302
2303
$B.format_width = function(s, fmt){
Mar 19, 2018
2304
if(fmt.width && s.length < fmt.width){
2305
var fill = fmt.fill || " ",
2306
align = fmt.align || "<",
2307
missing = fmt.width - s.length
2308
switch(align){
Mar 19, 2018
2309
case "<":
2310
return s + fill.repeat(missing)
2311
case ">":
2312
return fill.repeat(missing) + s
2313
case "=":
2314
if("+-".indexOf(s.charAt(0)) > -1){
2315
return s.charAt(0) + fill.repeat(missing) + s.substr(1)
2316
}else{
Mar 19, 2018
2317
return fill.repeat(missing) + s
Mar 19, 2018
2319
case "^":
2320
var left = parseInt(missing / 2)
2321
return fill.repeat(left) + s + fill.repeat(missing - left)
2322
}
2323
}
2324
return s
2325
}
2326
2327
function fstring_expression(){
Mar 19, 2018
2328
this.type = "expression"
2329
this.expression = ""
2330
this.conversion = null
2331
this.fmt = null
2332
}
2333
2334
function fstring_error(msg, pos){
2335
error = Error(msg)
2336
error.position = pos
2337
throw error
2338
}
2339
2340
$B.parse_fstring = function(string){
2341
// Parse a f-string
2342
var elts = [],
2343
pos = 0,
Mar 19, 2018
2344
current = "",
2345
ctype = null,
2346
nb_braces = 0,
2347
car
2348
Mar 19, 2018
2349
while(pos < string.length){
2350
if(ctype === null){
2351
car = string.charAt(pos)
Mar 19, 2018
2352
if(car == "{"){
Mar 21, 2018
2353
if(string.charAt(pos + 1) == "{"){
Mar 19, 2018
2354
ctype = "string"
2355
current = "{"
2356
pos += 2
2357
}else{
Mar 19, 2018
2358
ctype = "expression"
2359
nb_braces = 1
2360
pos++
2361
}
Mar 19, 2018
2362
}else if(car == "}"){
Mar 21, 2018
2363
if(string.charAt(pos + 1) == car){
Mar 19, 2018
2364
ctype = "string"
2365
current = "}"
2366
pos += 2
2367
}else{
2368
fstring_error(" f-string: single '}' is not allowed",
2369
pos)
2370
}
2371
}else{
Mar 19, 2018
2372
ctype = "string"
2373
current = car
2374
pos++
Mar 19, 2018
2376
}else if(ctype == "string"){
2377
// end of string is the first single { or end of string
Mar 19, 2018
2378
var i = pos
2379
while(i < string.length){
2380
car = string.charAt(i)
Mar 19, 2018
2381
if(car == "{"){
Mar 21, 2018
2382
if(string.charAt(i + 1) == "{"){
Mar 19, 2018
2383
current += "{"
2384
i += 2
2385
}else{
2386
elts.push(current)
Mar 19, 2018
2387
ctype = "expression"
2388
pos = i + 1
2389
break
2390
}
Mar 19, 2018
2391
}else if(car == "}"){
2392
if(string.charAt(i + 1) == car){
2393
current += car
2394
i += 2
2395
}else{
2396
fstring_error(" f-string: single '}' is not allowed",
2397
pos)
2398
}
2399
}else{
2400
current += car
2401
i++
2402
}
2403
}
Mar 19, 2018
2404
pos = i + 1
2405
}else if(ctype == "debug"){
2406
// after the equal sign, whitespace are ignored and the only
2407
// valid characters are } and :
2408
while(string.charAt(i) == " "){i++}
2409
if(string.charAt(i) == "}"){
2410
// end of debug expression
2411
elts.push(current)
2412
ctype = null
2413
current = ""
2414
pos = i + 1
2415
}
2416
}else{
2417
// End of expression is the } matching the opening {
2418
// There may be nested braces
2419
var i = pos,
2420
nb_braces = 1,
2421
nb_paren = 0,
2422
current = new fstring_expression()
Mar 19, 2018
2423
while(i < string.length){
2424
car = string.charAt(i)
Mar 19, 2018
2425
if(car == "{" && nb_paren == 0){
2426
nb_braces++
2427
current.expression += car
2428
i++
Mar 19, 2018
2429
}else if(car == "}" && nb_paren == 0){
2430
nb_braces -= 1
Mar 19, 2018
2431
if(nb_braces == 0){
2432
// end of expression
2433
if(current.expression == ""){
2434
fstring_error("f-string: empty expression not allowed",
2435
pos)
2436
}
2437
elts.push(current)
2438
ctype = null
Mar 19, 2018
2439
current = ""
2440
pos = i + 1
2443
current.expression += car
2444
i++
Mar 19, 2018
2445
}else if(car == "\\"){
2446
// backslash is not allowed in expressions
2447
throw Error("f-string expression part cannot include a" +
2448
" backslash")
Mar 19, 2018
2449
}else if(nb_paren == 0 && car == "!" && current.fmt === null &&
Mar 21, 2018
2450
":}".indexOf(string.charAt(i + 2)) > -1){
Mar 19, 2018
2451
if(current.expression.length == 0){
2452
throw Error("f-string: empty expression not allowed")
2453
}
Mar 19, 2018
2454
if("ars".indexOf(string.charAt(i + 1)) == -1){
2455
throw Error("f-string: invalid conversion character:" +
2456
" expected 's', 'r', or 'a'")
2457
}else{
Mar 19, 2018
2458
current.conversion = string.charAt(i + 1)
2459
i += 2
2460
}
Mar 19, 2018
2461
}else if(car == "("){
2462
nb_paren++
2463
current.expression += car
2464
i++
Mar 19, 2018
2465
}else if(car == ")"){
2466
nb_paren--
2467
current.expression += car
2468
i++
Mar 19, 2018
2469
}else if(car == '"'){
2470
// triple string ?
Mar 19, 2018
2471
if(string.substr(i, 3) == '"""'){
2472
var end = string.indexOf('"""', i + 3)
2473
if(end == -1){
2474
fstring_error("f-string: unterminated string", pos)
Mar 19, 2018
2475
}else{
2476
var trs = string.substring(i, end + 3)
2477
trs = trs.replace("\n", "\\n\\")
2478
current.expression += trs
Mar 19, 2018
2479
i = end + 3
2480
}
2481
}else{
Mar 19, 2018
2482
var end = string.indexOf('"', i + 1)
2483
if(end == -1){
2484
fstring_error("f-string: unterminated string", pos)
Mar 19, 2018
2485
}else{
2486
current.expression += string.substring(i, end + 1)
2487
i = end + 1
2488
}
2489
}
Mar 19, 2018
2490
}else if(nb_paren == 0 && car == ":"){
2491
current.fmt = true
2492
current.expression += car
2493
i++
2494
}else if(car == "="){
2495
// might be a "debug expression", eg f"{x=}"
2496
var ce = current.expression,
2497
last_char = ce.charAt(ce.length - 1),
2498
last_char_re = ('()'.indexOf(last_char) > -1 ? "\\" : "") + last_char
2502
string.charAt(i + 1) == "=" ||
2503
"=!<>:".search(last_char_re) > -1){
2504
current.expression += car //+ string.charAt(i + 1)
2505
i += 1
2506
}else{
2507
// add debug string
2508
tail = car
2509
while(string.charAt(i + 1).match(/\s/)){
2510
tail += string.charAt(i + 1)
2511
i++
2512
}
2513
elts.push(current.expression + tail)
2514
// remove trailing whitespace from expression
2515
while(ce.match(/\s$/)){
2516
ce = ce.substr(0, ce.length - 1)
2517
}
2518
current.expression = ce
2519
ctype = "debug"
2520
i++
2521
}
2522
}else{
2523
current.expression += car
2524
i++
2525
}
2526
}
Mar 21, 2018
2527
if(nb_braces > 0){
2528
fstring_error("f-string: expected '}'", pos)
2529
}
2530
}
2531
}
Mar 19, 2018
2532
if(current.length > 0){elts.push(current)}
2533
return elts
2534
}
2535
2536
// Class for strings with surrogate pairs. We can't rely on Javascript
2537
// strings in this case because they don't count characters like Python
2538
2539
var surrogate = str.$surrogate = $B.make_class("surrogate_string", function(s){
2540
// create an instance of str subclass for strings with surrogate pairs
2541
var items = []
2542
for(var i = 0, len = s.length; i < len; i++){
2543
var code = s.charCodeAt(i)
2544
if(code >= 0xD800 && code <= 0xDBFF){
2545
i++
2546
var low = s.charCodeAt(i)
2547
code = ((code - 0xD800) * 0x400) + (low - 0xDC00) + 0x10000
2548
}
2549
items.push(String.fromCodePoint(code))
2550
}
2551
return {
2552
__class__: str.$surrogate,
2553
items: items
2554
}
2555
})
2556
2557
surrogate.__mro__ = [str, object]
2558
2559
surrogate.__add__ = function(self, other){
2560
if(other.__class__ === str.$surrogate){
2561
var res = str.$surrogate.$factory('')
2562
res.items = self.items.concat(other.items)
2563
return res
2564
}else if(_b_.isinstance(other, str)){
2565
var res = str.$surrogate.$factory('')
2566
res.items = self.items
2567
for(const char of other + ''){
2568
res.items.push(char)
2569
}
2570
return res
2571
}
2572
}
2573
2574
surrogate.__contains__ = function(self, other){
2575
return str.__contains__(self.items.join(''), other)
2576
}
2577
2578
surrogate.__eq__ = function(self, other){
2579
if(other.__class__ !== surrogate){
2580
return _b_.NotImplemented
2581
}
2582
var res = true
2583
if(self.items.length == other.items.length){
2584
for(var i = 0, len = self.items.length; i < len; i++){
2585
if(self.items[i] != other.items[i]){
2586
return false
2587
}
2588
}
2589
return true
2590
}else{
2591
return false
2592
}
2593
}
2594
2595
surrogate.__getitem__ = function(self, arg){
2596
if(isinstance(arg, _b_.int)){
2597
var pos = arg
2598
if(arg < 0){
2599
pos += self.items.length
2600
}
2601
if(pos >= 0 && pos < self.items.length){
2602
if(self.items[pos].length == 2){
2603
return surrogate.$factory(self.items[pos])
2604
}
2605
return self.items[pos]
2606
}
2607
throw _b_.IndexError.$factory("string index out of range")
2608
}
2609
if(isinstance(arg, slice)) {
2610
var s = _b_.slice.$conv_for_seq(arg, self.items.length),
2611
start = s.start,
2612
stop = s.stop,
2613
step = s.step
2614
var res = "",
2615
i = null
2616
if(step > 0){
2617
if(stop <= start){return ""}
2618
for(var i = start; i < stop; i += step){
2619
res += self.items[i]
2620
}
2621
}else{
2622
if(stop >= start){return ''}
2623
for(var i = start; i > stop; i += step){
2624
res += self.items[i]
2625
}
2626
}
2627
return res
2628
}
2629
if(isinstance(arg, _b_.bool)){
2630
return surrogate.__getitem__(self, _b_.int.$factory(arg))
2631
}
2632
throw _b_.TypeError.$factory("string indices must be integers")
2633
}
2634
2635
surrogate.__hash__ = function(self){
2636
return str.__hash__(self.items.join(''))
2637
}
2638
2639
surrogate.__iter__ = function(self){
2640
return str_iterator.$factory(self.items)
2641
}
2642
2643
surrogate.__len__ = function(self){
2644
return self.items.length
2645
}
2646
2647
surrogate.__mul__ = function(self, num){
2648
try{
2649
num = _b_.int.$factory(num)
2650
}catch(err){
2651
return _b_.NotImplemented
2652
}
2653
var items = []
2654
for(var i = 0; i < num; i++){
2655
items = items.concat(self.items)
2656
}
2657
return {
2658
__class__: surrogate,
2659
items
2660
}
2661
}
2662
2663
surrogate.__ne__ = function(self, other){
2664
return ! surrogate.__eq__(self, other)
2665
}
2666
2667
surrogate.__repr__ = function(self){
2668
return str.__repr__(self.items.join(''))
2669
}
2670
2671
surrogate.__str__ = function(self){
2672
return str.__str__(self.items.join(''))
2673
}
2674
2675
function _chr(i){
2676
if(i >= 0x10000 && i <= 0x10FFFF){
2677
var code = (i - 0x10000)
2678
return String.fromCodePoint(0xD800 | (code >> 10)) +
2679
String.fromCodePoint(0xDC00 | (code & 0x3FF))
2680
}else{
2681
return String.fromCodePoint(i)
2682
}
2683
}
2684
function _ord(c){
2685
if(c.length == 1){
2686
return c.charCodeAt(0)
2687
}
2688
var code = 0x10000
2689
code += (c.charCodeAt(0) & 0x03FF) << 10
2690
code += (c.charCodeAt(1) & 0x03FF)
2691
return code
2692
}
2693
2694
surrogate.lower = function(self){
2695
var res = surrogate.$factory('')
2696
for(var char of self.items){
2697
res.items.push(_chr(_ord(char.toLowerCase())))
2698
}
2699
return res
2700
}
2701
2702
surrogate.upper = function(self){
2703
var res = surrogate.$factory('')
2704
for(var char of self.items){
2705
res.items.push(_chr(_ord(char.toUpperCase())))
2706
}
2707
return res
2708
}
2709
2710
$B.set_func_names(surrogate, "builtins")
2711
2712
Sep 5, 2014
2713
})(__BRYTHON__)