Skip to content
Permalink
Newer
Older
100644 1947 lines (1780 sloc) 63.2 KB
Sep 5, 2014
1
;(function($B){
2
3
eval($B.InjectBuiltins())
Sep 5, 2014
4
5
if (!String.prototype.trim) {
6
// Polyfill for older browsers
7
// The code does not use a regex to make it a bit faster.
8
// Implementation taken from a comment by Timo on the blog:
9
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
10
String.prototype.trim = function () {
11
var c;
12
for (var i = 0; i < this.length; i++) {
13
c = this.charCodeAt(i);
14
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
15
continue; else break;
16
}
17
for (var j = this.length - 1; j >= i; j--) {
18
c = this.charCodeAt(j);
19
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
20
continue; else break;
21
}
22
return this.substring(i, j + 1);
23
}
24
}
25
if (!String.prototype.trimLeft) {
26
// Convenience method for browsers which do not have a native trimLeft
27
// (which is a nonstandard extension in Firefox and Chrome)
28
String.prototype.trimLeft = function () {
29
var c;
30
for (var i = 0; i < this.length; i++) {
31
c = this.charCodeAt(i);
32
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
33
continue; else break;
34
}
35
return this.substring(i);
36
};
37
}
38
if (!String.prototype.trimRight) {
39
String.prototype.trimRight = function () {
40
// Convenience method for browsers which do not have a native trimRight
41
// (which is a nonstandard extension in Firefox and Chrome)
42
var c;
43
for (var j = this.length - 1; j >= 0; j--) {
44
c = this.charCodeAt(j);
45
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
46
continue; else break;
47
}
48
return this.substring(0, j + 1);
49
};
50
}
Sep 5, 2014
53
str
Feb 10, 2018
54
var str = {
Feb 11, 2018
55
__class__:_b_.type,
Sep 5, 2014
57
__name__:'str',
str
Feb 10, 2018
58
$is_class: true,
Sep 5, 2014
59
$native:true
60
}
61
62
function normalize_start_end($){
63
if($.start===null||$.start===_b_.None){$.start = 0}
64
else if($.start<0){$.start += $.self.length; $.start=Math.max(0, $.start)}
65
if($.end===null||$.end===_b_.None){$.end = $.self.length}
66
else if($.end<0){$.end += $.self.length; $.end=Math.max(0, $.end)}
67
68
if(!isinstance($.start,_b_.int)||!isinstance($.end,_b_.int)){
69
throw _b_.TypeError.$factory(
70
"slice indices must be integers or None or have an __index__ method")}
71
72
}
73
74
function reverse(s){
75
// Reverse a string
76
return s.split('').reverse().join('')
77
}
78
79
function check_str(obj){
80
if(!_b_.isinstance(obj,str)){throw _b_.TypeError.$factory("can't convert '"+
81
$B.get_class(obj).__name__+"' object to str implicitely")}
str
Feb 10, 2018
84
str.__add__ = function(self,other){
Sep 5, 2014
85
if(!(typeof other==="string")){
86
try{return getattr(other,'__radd__')(self)}
87
catch(err){throw _b_.TypeError.$factory(
Sep 5, 2014
88
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
89
}
90
return self+other
91
}
92
str
Feb 10, 2018
93
str.__contains__ = function(self,item){
94
if(!(typeof item==="string")){throw _b_.TypeError.$factory(
Sep 5, 2014
95
"'in <string>' requires string as left operand, not "+item.__class__)}
96
var nbcar = item.length
97
if(nbcar==0) return true // a string contains the empty string
98
if(self.length==0) return nbcar==0
99
for(var i=0, _len_i = self.length; i < _len_i;i++){
Sep 5, 2014
100
if(self.substr(i,nbcar)==item) return true
101
}
102
return false
103
}
104
str
Feb 10, 2018
105
str.__delitem__ = function(){
106
throw _b_.TypeError.$factory("'str' object doesn't support item deletion")
Sep 5, 2014
107
}
108
109
// __dir__must be assigned explicitely because attribute resolution for builtin
110
// classes doesn't use __mro__
str
Feb 10, 2018
111
str.__dir__ = object.__dir__
str
Feb 10, 2018
113
str.__eq__ = function(self,other){
Sep 5, 2014
114
if(other===undefined){ // compare object "self" to class "str"
115
return self===str
116
}
117
if (_b_.isinstance(other, _b_.str)) {
118
return other.valueOf() == self.valueOf()
119
}
Sep 5, 2014
120
return other===self.valueOf()
121
}
122
123
function preformat(self, fmt){
str
Feb 10, 2018
124
if(fmt.empty){return _b_.str.$factory(self)}
125
if(fmt.type && fmt.type!='s'){
126
throw _b_.ValueError.$factory("Unknown format code '"+fmt.type+
127
"' for object of type 'str'")
129
return self
130
}
131
str
Feb 10, 2018
132
str.__format__ = function(self, format_spec) {
133
var fmt = new $B.parse_format_spec(format_spec)
134
if(fmt.sign!==undefined){
135
throw _b_.ValueError.$factory("Sign not allowed in string format specifier")
137
// For strings, alignment default to left
138
fmt.align = fmt.align || '<'
139
return $B.format_width(preformat(self, fmt), fmt)
Sep 5, 2014
140
}
141
str
Feb 10, 2018
142
str.__getitem__ = function(self,arg){
Sep 5, 2014
143
if(isinstance(arg,_b_.int)){
144
var pos = arg
145
if(arg<0) pos+=self.length
146
if(pos>=0 && pos<self.length) return self.charAt(pos)
147
throw _b_.IndexError.$factory('string index out of range')
Sep 5, 2014
148
}
149
if(isinstance(arg,slice)) {
Feb 11, 2018
150
var s=_b_.slice.$conv_for_seq(arg, self.length),
151
start=s.start, stop=s.stop, step=s.step
Sep 5, 2014
152
var res = '',i=null
153
if(step>0){
154
if(stop<=start) return ''
155
for(var i=start;i<stop;i+=step) res += self.charAt(i)
156
} else {
157
if(stop>=start) return ''
158
for(var i=start;i>stop;i+=step) res += self.charAt(i)
Sep 5, 2014
160
return res
161
}
162
if(isinstance(arg,bool)) return self.__getitem__(_b_.int.$factory(arg))
163
throw _b_.TypeError.$factory('string indices must be integers')
Sep 5, 2014
164
}
165
str
Feb 10, 2018
166
str.__hash__ = function(self) {
167
if (self === undefined) {
str
Feb 10, 2018
168
return str.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
Sep 5, 2014
171
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
172
// this implementation for strings maybe good enough for us..
173
174
var hash=1;
175
for(var i=0, _len_i = self.length; i < _len_i; i++) {
Sep 5, 2014
176
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
177
}
178
179
return hash
180
}
181
str
Feb 10, 2018
182
str.__init__ = function(self,arg){
Sep 5, 2014
183
self.valueOf = function(){return arg}
184
self.toString = function(){return arg}
Sep 5, 2014
186
}
187
188
var $str_iterator = $B.$iterator_class('str_iterator')
str
Feb 10, 2018
189
str.__iter__ = function(self){
Sep 5, 2014
190
var items = self.split('') // list of all characters in string
191
return $B.$iterator(items,$str_iterator)
192
}
193
str
Feb 10, 2018
194
str.__len__ = function(self){return self.length}
Sep 5, 2014
195
196
// Start of section for legacy formatting (with %)
197
198
var kwarg_key = new RegExp('([^\\)]*)\\)')
199
200
var NotANumber = function() {
201
this.name = 'NotANumber'
202
}
203
204
var number_check=function(s) {
205
if(!isinstance(s,[_b_.int,_b_.float])){
206
throw new NotANumber()
207
}
208
}
209
210
var get_char_array = function(size, char) {
211
if (size <= 0)
212
return ''
213
return new Array(size + 1).join(char)
214
}
215
216
var format_padding = function(s, flags, minus_one) {
217
var padding = flags.padding
218
if (!padding) { // undefined
219
return s
220
}
221
s = s.toString()
222
padding = parseInt(padding, 10)
223
if (minus_one) { // numeric formatting where sign goes in front of padding
224
padding -= 1
225
}
226
if (!flags.left) {
227
return get_char_array(padding - s.length, flags.pad_char) + s
228
} else {
229
// left adjusted
230
return s + get_char_array(padding - s.length, flags.pad_char)
231
}
232
}
233
234
var format_int_precision = function(val, flags) {
235
var precision = flags.precision
236
if (!precision) {
237
return val.toString()
238
}
239
precision = parseInt(precision, 10)
Feb 11, 2018
241
if (val.__class__ === $B.long_int) {
242
s=$B.long_int.to_base(val, 10)
243
} else {
244
s=val.toString()
245
}
246
if (s[0] === '-') {
247
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
248
}
249
return get_char_array(precision - s.length, '0') + s
250
}
251
252
var format_float_precision = function(val, upper, flags, modifier) {
253
var precision = flags.precision
254
// val is a float
255
if (isFinite(val)) {
256
return modifier(val, precision, flags, upper)
257
}
258
if (val === Infinity) {
259
val = 'inf'
260
} else if (val === -Infinity) {
261
val = '-inf'
262
} else {
263
val = 'nan'
264
}
265
if (upper) {
266
return val.toUpperCase()
267
}
268
return val
270
}
271
272
var format_sign = function(val, flags) {
273
if (flags.sign) {
274
if (val >= 0) {
275
return "+"
Sep 5, 2014
276
}
277
} else if (flags.space) {
278
if (val >= 0) {
279
return " "
280
}
281
}
282
return ""
283
}
Sep 5, 2014
284
285
var str_format = function(val, flags) {
286
// string format supports left and right padding
287
flags.pad_char = " " // even if 0 padding is defined, don't use it
str
Feb 10, 2018
288
return format_padding(str.$factory(val), flags)
Sep 5, 2014
290
291
var num_format = function(val, flags) {
292
number_check(val)
Feb 11, 2018
293
if (val.__class__ === $B.long_int) {
294
val = $B.long_int.to_base(val, 10)
295
} else {
296
val = parseInt(val)
297
}
298
299
var s = format_int_precision(val, flags)
300
if (flags.pad_char === '0') {
301
if (val < 0) {
302
s = s.substring(1)
303
return '-' + format_padding(s, flags, true)
304
}
305
var sign = format_sign(val, flags)
306
if (sign !== '') {
307
return sign + format_padding(s, flags, true)
308
}
309
}
311
return format_padding(format_sign(val, flags) + s, flags)
312
}
Sep 5, 2014
313
314
var repr_format = function(val, flags) {
315
flags.pad_char = " " // even if 0 padding is defined, don't use it
316
return format_padding(repr(val), flags)
317
}
Sep 5, 2014
318
319
var ascii_format = function(val, flags) {
320
flags.pad_char = " " // even if 0 padding is defined, don't use it
321
return format_padding(ascii(val), flags)
322
}
Sep 5, 2014
323
324
// converts val to float and sets precision if missing
325
var _float_helper = function(val, flags) {
326
number_check(val)
327
if (!flags.precision) {
328
if (!flags.decimal_point) {
329
flags.precision = 6
330
} else {
331
flags.precision = 0
332
}
333
} else {
334
flags.precision = parseInt(flags.precision, 10)
335
validate_precision(flags.precision)
336
}
337
return parseFloat(val)
338
}
Sep 5, 2014
339
340
// used to capture and remove trailing zeroes
341
var trailing_zeros = /(.*?)(0+)([eE].*)/
342
var leading_zeros = /\.(0*)/
343
var trailing_dot = /\.$/
Sep 5, 2014
344
345
var validate_precision = function(precision) {
346
// force precision to limits of javascript
Sep 20, 2015
347
if (precision > 20) { precision = 20 }
348
}
349
350
// gG
351
var floating_point_format = function(val, upper, flags) {
352
val = _float_helper(val, flags)
353
var v = val.toString()
354
var v_len = v.length
355
var dot_idx = v.indexOf('.')
356
if (dot_idx < 0) {
357
dot_idx = v_len
358
}
359
if (val < 1 && val > -1) {
360
var zeros = leading_zeros.exec(v)
361
var numzeros
362
if (zeros) {
363
numzeros = zeros[1].length
364
} else {
365
numzeros = 0
366
}
367
if (numzeros >= 4) {
368
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
369
if (!flags.alternate) {
370
var trl = trailing_zeros.exec(val)
371
if (trl) {
372
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
374
} else {
375
if (flags.precision <= 1) {
376
val = val[0] + '.' + val.substring(1)
378
}
379
return format_padding(val, flags)
380
}
381
flags.precision = (flags.precision || 0) + numzeros
382
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
383
function(val, precision) {
384
return val.toFixed(min(precision, v_len - dot_idx) + numzeros)
385
}), flags)
386
}
388
if (dot_idx > flags.precision) {
389
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
390
if (!flags.alternate) {
391
var trl = trailing_zeros.exec(val)
392
if (trl) {
393
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
394
}
395
} else {
396
if (flags.precision <= 1) {
397
val = val[0] + '.' + val.substring(1)
398
}
399
}
400
return format_padding(val, flags)
401
}
402
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
403
function(val, precision) {
404
if (!flags.decimal_point) {
405
precision = min(v_len - 1, 6)
406
} else if (precision > v_len) {
407
if (!flags.alternate) {
408
precision = v_len
Sep 5, 2014
409
}
410
}
411
if (precision < dot_idx) {
412
precision = dot_idx
413
}
414
return val.toFixed(precision - dot_idx)
415
}), flags)
416
}
Sep 5, 2014
417
418
var _floating_g_exp_helper = function(val, precision, flags, upper) {
419
if (precision) {
420
--precision
421
}
422
val = val.toExponential(precision)
423
// pad exponent to two digits
424
var e_idx = val.lastIndexOf('e')
425
if (e_idx > val.length - 4) {
426
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
427
}
428
if (upper) {
429
return val.toUpperCase()
430
}
431
return val
432
}
433
434
// fF
435
var floating_point_decimal_format = function(val, upper, flags) {
436
val = _float_helper(val, flags)
437
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
438
function(val, precision, flags) {
439
val = val.toFixed(precision)
440
if (precision === 0 && flags.alternate) {
441
val += '.'
442
}
443
return val
444
}), flags)
445
}
446
447
var _floating_exp_helper = function(val, precision, flags, upper) {
448
val = val.toExponential(precision)
449
// pad exponent to two digits
450
var e_idx = val.lastIndexOf('e')
451
if (e_idx > val.length - 4) {
452
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
453
}
454
if (upper) {
455
return val.toUpperCase()
456
}
457
return val
458
}
459
460
// eE
461
var floating_point_exponential_format = function(val, upper, flags) {
462
val = _float_helper(val, flags)
464
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
465
}
466
467
var signed_hex_format = function(val, upper, flags) {
469
number_check(val)
Feb 11, 2018
471
if (val.__class__ === $B.long_int) {
472
ret=$B.long_int.to_base(val, 16)
473
} else {
474
ret = parseInt(val)
475
ret = ret.toString(16)
476
}
477
ret = format_int_precision(ret, flags)
478
if (upper) {
479
ret = ret.toUpperCase()
480
}
481
if (flags.pad_char === '0') {
482
if (val < 0) {
483
ret = ret.substring(1)
484
ret = '-' + format_padding(ret, flags, true)
485
}
486
var sign = format_sign(val, flags)
487
if (sign !== '') {
488
ret = sign + format_padding(ret, flags, true)
Sep 5, 2014
489
}
492
if (flags.alternate) {
493
if (ret.charAt(0) === '-') {
494
if (upper) {
495
ret = "-0X" + ret.slice(1)
496
} else {
497
ret = "-0x" + ret.slice(1)
498
}
499
} else {
500
if (upper) {
501
ret = "0X" + ret
502
} else {
503
ret = "0x" + ret
504
}
505
}
506
}
507
return format_padding(format_sign(val, flags) + ret, flags)
508
}
Sep 5, 2014
509
510
var octal_format = function(val, flags) {
511
number_check(val)
Feb 11, 2018
514
if (val.__class__ === $B.long_int) {
515
ret = $B.long_int.to_base(8)
516
} else {
517
ret = parseInt(val)
518
ret = ret.toString(8)
519
}
520
521
ret = format_int_precision(ret, flags)
523
if (flags.pad_char === '0') {
524
if (val < 0) {
525
ret = ret.substring(1)
526
ret = '-' + format_padding(ret, flags, true)
527
}
528
var sign = format_sign(val, flags)
529
if (sign !== '') {
530
ret = sign + format_padding(ret, flags, true)
531
}
Sep 5, 2014
532
}
534
if (flags.alternate) {
535
if (ret.charAt(0) === '-') {
536
ret = "-0o" + ret.slice(1)
537
} else {
538
ret = "0o" + ret
539
}
Sep 5, 2014
540
}
541
return format_padding(ret, flags)
542
}
543
544
var single_char_format = function(val, flags) {
545
if(isinstance(val,str) && val.length==1) return val
546
try {
547
val = _b_.int.$factory(val) // yes, floats are valid (they are cast to int)
548
} catch (err) {
549
throw _b_.TypeError.$factory('%c requires int or char')
550
}
551
return format_padding(chr(val), flags)
552
}
553
554
var num_flag = function(c, flags) {
555
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
556
flags.pad_char = '0'
557
return
558
}
559
if (!flags.decimal_point) {
560
flags.padding = (flags.padding || "") + c
561
} else {
562
flags.precision = (flags.precision || "") + c
563
}
564
}
565
566
var decimal_point_flag = function(val, flags) {
567
if (flags.decimal_point) {
568
// can only have one decimal point
569
throw new UnsupportedChar()
570
}
571
flags.decimal_point = true
572
}
573
574
var neg_flag = function(val, flags) {
575
flags.pad_char = ' ' // overrides '0' flag
576
flags.left = true
577
}
578
579
var space_flag = function(val, flags) {
580
flags.space = true
581
}
582
583
var sign_flag = function(val, flags) {
584
flags.sign = true
585
}
586
587
var alternate_flag = function(val, flags) {
588
flags.alternate = true
589
}
590
591
var char_mapping = {
592
's': str_format,
593
'd': num_format,
594
'i': num_format,
595
'u': num_format,
596
'o': octal_format,
597
'r': repr_format,
598
'a': ascii_format,
599
'g': function(val, flags) {return floating_point_format(val, false, flags)},
600
'G': function(val, flags) {return floating_point_format(val, true, flags)},
601
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
602
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
603
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
604
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
605
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
606
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
607
'c': single_char_format,
608
'0': function(val, flags) {return num_flag('0', flags)},
609
'1': function(val, flags) {return num_flag('1', flags)},
610
'2': function(val, flags) {return num_flag('2', flags)},
611
'3': function(val, flags) {return num_flag('3', flags)},
612
'4': function(val, flags) {return num_flag('4', flags)},
613
'5': function(val, flags) {return num_flag('5', flags)},
614
'6': function(val, flags) {return num_flag('6', flags)},
615
'7': function(val, flags) {return num_flag('7', flags)},
616
'8': function(val, flags) {return num_flag('8', flags)},
617
'9': function(val, flags) {return num_flag('9', flags)},
618
'-': neg_flag,
619
' ': space_flag,
620
'+': sign_flag,
621
'.': decimal_point_flag,
622
'#': alternate_flag
623
}
624
625
// exception thrown when an unsupported char is encountered in legacy format
626
var UnsupportedChar = function() {
627
this.name = "UnsupportedChar"
628
}
629
str
Feb 10, 2018
630
str.__mod__ = function(self, args) {
632
var length = self.length,
633
pos = 0 |0,
634
argpos = null,
635
getitem
636
if (_b_.isinstance(args, _b_.tuple)) {
637
argpos = 0 |0
639
getitem = _b_.getattr(args,'__getitem__', _b_.None)
640
}
641
var ret = ''
642
var $get_kwarg_string = function(s) {
643
// returns [self, newpos]
644
++pos
645
var rslt = kwarg_key.exec(s.substring(newpos))
646
if (!rslt) {
647
throw _b_.ValueError.$factory("incomplete format key")
648
}
649
var key = rslt[1]
650
newpos += rslt[0].length
651
try {
652
var self = getitem(key)
653
} catch(err) {
654
if (err.name === "KeyError") {
655
throw err
656
}
657
throw _b_.TypeError.$factory("format requires a mapping")
659
return get_string_value(s, self)
660
}
661
662
var $get_arg_string = function(s) {
663
// returns [self, newpos]
664
var self
666
// non-tuple args
667
if (argpos === null) {
668
// args is the value
670
} else {
671
self = args[argpos++]
672
if(self===undefined){
673
throw _b_.TypeError.$factory("not enough arguments for format string")
Sep 5, 2014
674
}
675
}
676
return get_string_value(s, self)
678
var get_string_value = function(s, self) {
679
// todo: get flags, type
680
// todo: string value based on flags, type, value
681
var flags = {'pad_char': ' '}
682
do {
683
var func = char_mapping[s[newpos]]
684
try {
685
if (func === undefined) {
686
throw new UnsupportedChar()
687
} else {
688
var ret = func(self, flags)
689
if (ret !== undefined) {
690
return ret
691
}
692
++newpos
693
}
694
} catch (err) {
695
if (err.name === "UnsupportedChar") {
696
invalid_char = s[newpos]
697
if (invalid_char === undefined) {
698
throw _b_.ValueError.$factory("incomplete format")
700
throw _b_.ValueError.$factory("unsupported format character '" + invalid_char +
701
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
702
} else if (err.name === "NotANumber") {
703
var try_char = s[newpos]
704
var cls = self.__class__
705
if (!cls) {
706
if (typeof(self) === 'string') {
707
cls = 'str'
708
} else {
709
cls = typeof(self)
710
}
711
} else {
712
cls = cls.__name__
713
}
714
throw _b_.TypeError.$factory("%" + try_char + " format: a number is required, not " + cls)
715
} else {
716
throw err
717
}
Sep 5, 2014
718
}
719
} while (true)
Sep 5, 2014
720
}
721
var nbph = 0 // number of placeholders
723
var newpos = self.indexOf('%', pos)
724
if (newpos < 0) {
725
ret += self.substring(pos)
726
break
727
}
728
ret += self.substring(pos, newpos)
729
++newpos
730
if (newpos < length) {
731
if (self[newpos] === '%') {
732
ret += '%'
733
} else {
735
if (self[newpos] === '(') {
736
++newpos
737
ret += $get_kwarg_string(self)
738
} else {
739
ret += $get_arg_string(self)
740
}
741
}
742
} else {
743
// % at end of string
744
throw _b_.ValueError.$factory("incomplete format")
745
}
746
pos = newpos + 1
747
} while (pos < length)
749
if(argpos!==null){
750
if(args.length>argpos){
751
throw _b_.TypeError.$factory('not enough arguments for format string')
752
}else if(args.length<argpos){
753
throw _b_.TypeError.$factory('not all arguments converted during string formatting')
754
}
755
}else if(nbph==0){
756
throw _b_.TypeError.$factory('not all arguments converted during string formatting')
Sep 5, 2014
760
str
Feb 10, 2018
761
str.__mro__ = [object]
Sep 5, 2014
762
str
Feb 10, 2018
763
str.__mul__ = function(){
764
var $=$B.args('__mul__',2,{self:null,other:null},['self','other'],
765
arguments,{},null,null)
766
if(!isinstance($.other,_b_.int)){throw _b_.TypeError.$factory(
Sep 5, 2014
767
"Can't multiply sequence by non-int of type '"+
768
$B.get_class($.other).__name__+"'")}
770
for(var i=0;i<$.other;i++){$res+=$.self.valueOf()}
Sep 5, 2014
771
return $res
772
}
773
str
Feb 10, 2018
774
str.__ne__ = function(self,other){return other!==self.valueOf()}
Sep 5, 2014
775
str
Feb 10, 2018
776
str.__repr__ = function(self){
777
var res = self.replace(/\n/g,'\\\\n')
778
// escape the escape char
779
res = res.replace(/\\/g, '\\\\')
780
if(res.search('"')==-1 && res.search("'")==-1){
781
return "'"+res+"'"
May 19, 2015
782
}else if(self.search('"')==-1){
783
return '"'+res+'"'
May 19, 2015
784
}
Sep 5, 2014
785
var qesc = new RegExp("'","g") // to escape single quote
786
res = "'"+res.replace(qesc,"\\'")+"'"
Sep 5, 2014
787
return res
788
}
789
str
Feb 10, 2018
790
str.__setitem__ = function(self,attr,value){
791
throw _b_.TypeError.$factory("'str' object does not support item assignment")
Sep 5, 2014
792
}
str
Feb 10, 2018
793
str.__str__ = function(self){
Sep 5, 2014
794
if(self===undefined) return "<class 'str'>"
795
return self.toString()
796
}
str
Feb 10, 2018
797
str.toString = function(){return 'string!'}
Sep 5, 2014
798
799
// generate comparison methods
800
var $comp_func = function(self,other){
801
if(typeof other !=="string"){throw _b_.TypeError.$factory(
Sep 5, 2014
802
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
803
return self > other
804
}
805
$comp_func += '' // source code
806
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
807
for(var $op in $comps){
str
Feb 10, 2018
808
eval("str.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
Sep 5, 2014
809
}
810
811
// add "reflected" methods
str
Feb 10, 2018
812
$B.make_rmethods(str)
Sep 5, 2014
813
814
// unsupported operations
815
var $notimplemented = function(self,other){
816
throw NotImplementedError.$factory("OPERATOR not implemented for class str")
Sep 5, 2014
817
}
818
819
// Copy static methods from unicode
820
var from_unicode = [
821
"title",
822
"capitalize",
823
"casefold",
824
"islower",
825
"isupper",
826
"istitle",
827
"isspace",
828
"isalpha",
829
"isalnum",
830
"isdecimal",
831
"isdigit",
832
"isnumeric",
833
"isidentifier",
834
"isprintable",
835
"lower",
836
"swapcase",
837
"upper"
838
]
839
for(var i=0;i<from_unicode.length;i++){
840
var name = from_unicode[i]
str
Feb 10, 2018
841
str[name] = unicode[name]
Sep 5, 2014
843
str
Feb 10, 2018
844
str.center = function(self,width,fillchar){
845
var $=$B.args("center",3,
846
{self:null, width:null, fillchar:null},
847
['self', 'width', 'fillchar'],
848
arguments,{fillchar:' '},null,null)
849
850
if($.width<=self.length) return self
852
var pad = parseInt(($.width-self.length)/2)
853
var res = $.fillchar.repeat(pad)
Sep 5, 2014
854
res += self + res
855
if(res.length<$.width){res += $.fillchar}
Sep 5, 2014
856
return res
857
}
858
str
Feb 10, 2018
859
str.count = function(){
860
var $ = $B.args('count', 4, {self:null, sub:null, start:null, stop:null},
861
['self', 'sub', 'start', 'stop'], arguments, {start:null, stop:null},
863
if(!(typeof $.sub==="string")){throw _b_.TypeError.$factory(
864
"Can't convert '"+$B.get_class($.sub).__name__+"' object to str implicitly")}
865
var substr = $.self
866
if($.start!==null){
867
var _slice
Feb 11, 2018
868
if($.stop!==null){_slice = _b_.slice.$factory($.start, $.stop)}
869
else{_slice = _b_.slice.$factory($.start,$.self.length)}
str
Feb 10, 2018
870
substr = str.__getitem__.apply(null, [$.self].concat(_slice))
871
}else{
872
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
873
}
874
if($.sub.length==0){
875
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
876
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
877
return substr.length+1
878
}
879
var n=0, pos=0
880
while(pos<substr.length){
881
pos=substr.indexOf($.sub,pos)
882
if(pos>=0){ n++; pos+=$.sub.length} else break;
Sep 5, 2014
883
}
884
return n
885
}
886
str
Feb 10, 2018
887
str.encode = function(self, encoding) {
Sep 5, 2014
888
if (encoding === undefined) encoding='utf-8'
889
if(encoding=='rot13' || encoding=='rot_13'){
890
// Special case : returns a string
891
var res = ''
892
for(var i=0, _len = self.length; i<_len ; i++){
893
var char = self.charAt(i)
894
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
895
res += String.fromCharCode(String.charCodeAt(char)+13)
896
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
897
res += String.fromCharCode(String.charCodeAt(char)-13)
898
}else{res += char}
899
}
900
return res
901
}
902
return _b_.bytes.$factory(self, encoding)
Sep 5, 2014
903
}
904
str
Feb 10, 2018
905
str.endswith = function(){
906
// Return True if the string ends with the specified suffix, otherwise
907
// return False. suffix can also be a tuple of suffixes to look for.
908
// With optional start, test beginning at that position. With optional
Sep 5, 2014
909
// end, stop comparing at that position.
Sep 20, 2015
910
var $=$B.args("endswith",4,
911
{self:null, suffix:null, start:null, end:null},
912
['self', 'suffix', 'start', 'end'],
Sep 20, 2015
913
arguments,{start:0, end:null},null,null)
914
915
normalize_start_end($)
916
917
var suffixes = $.suffix
Sep 5, 2014
918
if(!isinstance(suffixes,_b_.tuple)){suffixes=[suffixes]}
Sep 20, 2015
920
var s = $.self.substring($.start,$.end)
921
for(var i=0, _len_i = suffixes.length; i < _len_i;i++){
922
var suffix = suffixes[i]
923
if(!_b_.isinstance(suffix, str)){throw _b_.TypeError.$factory(
Sep 20, 2015
924
"endswith first arg must be str or a tuple of str, not int")}
Sep 5, 2014
925
if(suffix.length<=s.length &&
926
s.substr(s.length-suffix.length)==suffix) return true
927
}
928
return false
929
}
930
str
Feb 10, 2018
931
str.expandtabs = function(self, tabsize) {
932
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
933
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
934
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
935
if(s==1){return self.replace(/\t/g,' ')}
936
while(pos<self.length){
937
var car = self.charAt(pos)
938
switch(car){
939
case '\t':
940
while(col%s > 0){res += ' ';col++}
941
break
942
case '\r':
943
case '\n':
944
res += car
945
col = 0
946
break
947
default:
948
res += car
949
col++
950
break
951
}
952
pos++
953
}
Sep 5, 2014
956
}
957
str
Feb 10, 2018
958
str.find = function(){
959
// Return the lowest index in the string where substring sub is found,
960
// such that sub is contained in the slice s[start:end]. Optional
961
// arguments start and end are interpreted as in slice notation.
Sep 5, 2014
962
// Return -1 if sub is not found.
str
Feb 10, 2018
963
var $=$B.args("str.find",4,
964
{self:null, sub:null, start:null, end:null},
966
arguments,{start:0,end:null},null,null)
967
check_str($.sub)
970
if(!isinstance($.start,_b_.int)||!isinstance($.end,_b_.int)){
971
throw _b_.TypeError.$factory(
Sep 5, 2014
972
"slice indices must be integers or None or have an __index__ method")}
973
var s = $.self.substring($.start,$.end)
974
975
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
976
if(s.length+$.sub.length==0){return -1}
977
978
var last_search = s.length-$.sub.length
979
for(var i=0;i<=last_search;i++){
980
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
Sep 5, 2014
981
}
Sep 5, 2014
983
}
984
985
// Next function used by method .format()
986
987
function parse_format(fmt_string){
Sep 5, 2014
988
989
// Parse a "format string", as described in the Python documentation
990
// Return a format object. For the format string
991
// a.x[z]!r:...
992
// the object has attributes :
993
// - name : "a"
994
// - name_ext : [".x", "[z]"]
995
// - conv : r
996
// - spec : rest of string after :
Sep 5, 2014
997
998
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
999
if(elts.length==1){
1000
// No : in the string : it only contains a name
1001
name = fmt_string
1002
}else{
1003
// name is before the first ":"
1004
// spec (the format specification) is after
1005
name = elts[0]
1006
spec = elts.splice(1).join(':')
1007
}
1008
1009
var elts = name.split('!')
1010
if(elts.length>1){
1011
name=elts[0]
1012
conv=elts[1] // conversion flag
1013
if(conv.length!==1 || 'ras'.search(conv)==-1){
1014
throw _b_.ValueError.$factory('wrong conversion flag '+conv)
Sep 5, 2014
1017
1018
if(name!==undefined){
1019
// "name' may be a subscription or attribute
1020
// Put these "extensions" in the list "name_ext"
1021
function name_repl(match){
1022
name_ext.push(match)
1023
return ''
1024
}
1025
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1026
name = name.replace(name_ext_re, name_repl)
1027
}
Sep 5, 2014
1028
1029
return {name: name, name_ext: name_ext,
1030
conv: conv, spec: spec||''}
1031
}
Sep 5, 2014
1032
str
Feb 10, 2018
1033
str.format = function(self) {
1034
var $ = $B.args('format', 1, {self:null}, ['self'],
1035
arguments, {}, '$args', '$kw')
1036
1037
// Parse self to detect formatting instructions
1038
// Create a list "parts" made of sections of the string :
1039
// - elements of even rank are literal text
1040
// - elements of odd rank are "format objects", built from the
1041
// format strings in self (of the form {...})
1042
var pos=0,
1043
_len=self.length,
1044
car,
1045
text='',
1046
parts=[],
1048
while(pos<_len){
1049
car = self.charAt(pos)
1050
if(car=='{' && self.charAt(pos+1)=='{'){
1051
// replace {{ by literal {
1052
text += '{'
1053
pos+=2
1054
}else if(car=='}' && self.charAt(pos+1)=='}'){
1055
// replace }} by literal }
1056
text += '}'
1057
pos+=2
1058
}else if(car=='{'){
1059
// Start of a format string
1061
// Store current literal text
1062
parts.push(text)
1063
1064
// Search the end of the format string, ie the } closing the
1065
// opening {. Since the string can contain other pairs {} for
1066
// nested formatting, an integer nb is incremented for each { and
1067
// decremented for each } ; the end of the format string is
1068
// reached when nb==0
1069
var end = pos+1, nb=1
1070
while(end<_len){
1071
if(self.charAt(end)=='{'){nb++;end++}
1072
else if(self.charAt(end)=='}'){
1073
nb--;end++
1074
if(nb==0){
1075
// End of format string
1076
var fmt_string = self.substring(pos+1, end-1)
1077
1078
// Create a format object, by function parse_format
1079
var fmt_obj = parse_format(fmt_string)
1080
1081
// If no name is explicitely provided, use the rank
1082
if(!fmt_obj.name){
1083
fmt_obj.name=rank+''
1084
rank++
1085
}
Sep 5, 2014
1086
1087
if(fmt_obj.spec!==undefined){
1088
// "spec" may contain "nested replacement fields"
1089
// In this case, evaluate them using the positional
1090
// or keyword arguments passed to format()
1091
function replace_nested(name, key){
1092
if(/\d+/.exec(key)){
1093
// If key is numeric, search in positional
1094
// arguments
Feb 11, 2018
1095
return _b_.tuple.__getitem__($.$args,
1096
parseInt(key))
1097
}else{
1098
// Else try in keyword arguments
Feb 11, 2018
1099
return _b_.dict.__getitem__($.$kw, key)
1102
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1103
replace_nested)
1104
}
1106
// Store format object in list "parts"
1107
parts.push(fmt_obj)
1108
text = ''
1109
break
1110
}
1111
}else{end++}
Sep 5, 2014
1112
}
1113
if(nb>0){throw ValueError.$factory("wrong format "+self)}
1115
}else{text += car;pos++;}
Sep 5, 2014
1116
}
1117
if(text){parts.push(text)}
1118
// Apply formatting to the values passed to format()
1119
var res = '', fmt
1120
for(var i=0;i<parts.length;i++){
1121
// Literal text is added unchanged
1122
if(typeof parts[i]=='string'){res += parts[i];continue}
1124
// Format objects
1125
fmt = parts[i]
1126
if(fmt.name.charAt(0).search(/\d/)>-1){
1127
// Numerical reference : use positional arguments
1128
var pos = parseInt(fmt.name),
Feb 11, 2018
1129
value = _b_.tuple.__getitem__($.$args, pos)
1130
}else{
1131
// Use keyword arguments
Feb 11, 2018
1132
var value = _b_.dict.__getitem__($.$kw, fmt.name)
1133
}
1134
// If name has extensions (attributes or subscriptions)
1135
for(var j=0;j<fmt.name_ext.length;j++){
1136
var ext = fmt.name_ext[j]
1137
if(ext.charAt(0)=='.'){
1138
// Attribute
1139
value = _b_.getattr(value, ext.substr(1))
1140
}else{
1141
// Subscription
1142
var key = ext.substr(1, ext.length-2)
1143
// An index made of digits is transformed into an integer
1144
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1145
value = _b_.getattr(value, '__getitem__')(key)
1146
}
1147
}
1149
// If the conversion flag is set, first call a function to convert
1150
// the value
1151
if(fmt.conv=='a'){value = _b_.ascii(value)}
1152
else if(fmt.conv=='r'){value = _b_.repr(value)}
str
Feb 10, 2018
1153
else if(fmt.conv=='s'){value = _b_.str.$factory(value)}
1155
// Call attribute __format__ to perform the actual formatting
1156
if(value.$is_class || value.$factory){
1157
// For classes, don't use the class __format__ method
1158
res += value.__class__.__format__(value, fmt.spec)
1159
}else{
1160
res += _b_.getattr(value, '__format__')(fmt.spec)
1161
}
Sep 5, 2014
1162
}
Sep 5, 2014
1164
}
1165
str
Feb 10, 2018
1166
str.format_map = function(self) {
1167
throw NotImplementedError.$factory("function format_map not implemented yet");
Sep 5, 2014
1168
}
1169
str
Feb 10, 2018
1170
str.index = function(self){
Sep 5, 2014
1171
// Like find(), but raise ValueError when the substring is not found.
str
Feb 10, 2018
1172
var res = str.find.apply(null,arguments)
1173
if(res===-1) throw _b_.ValueError.$factory("substring not found")
Sep 5, 2014
1174
return res
1175
}
1176
str
Feb 10, 2018
1177
str.join = function(){
1178
var $=$B.args('join',2,{self:null,iterable:null},
1179
['self', 'iterable'], arguments, {}, null, null)
1181
var iterable=_b_.iter($.iterable)
1182
var res = [],
1183
count=0,
1184
ce = $B.current_exception
Sep 5, 2014
1185
while(1){
1186
try{
1187
var obj2 = _b_.next(iterable)
1188
if(!isinstance(obj2,str)){throw _b_.TypeError.$factory(
Sep 5, 2014
1189
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1190
res.push(obj2)
Sep 5, 2014
1191
}catch(err){
1192
if(_b_.isinstance(err, _b_.StopIteration)){
1193
$B.current_exception = ce
1194
break
1195
}
Sep 5, 2014
1196
else{throw err}
1197
}
1198
}
1199
return res.join($.self)
Sep 5, 2014
1200
}
1201
str
Feb 10, 2018
1202
str.ljust = function(self) {
1203
var $=$B.args('ljust',3,{self:null,width:null,fillchar:null},
1204
['self','width','fillchar'],arguments,{fillchar:' '},null,null)
1205
1206
if ($.width <= self.length) return self
1207
return self + $.fillchar.repeat($.width - self.length)
Sep 5, 2014
1208
}
1209
str
Feb 10, 2018
1210
str.lstrip = function(self,x){
1211
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1212
arguments,{chars:_b_.None},null,null)
1213
if($.chars===_b_.None){return $.self.trimLeft()}
1214
for (var i = 0; i < $.self.length; i++) {
1215
if ($.chars.indexOf($.self.charAt(i)) === -1) {
1216
return $.self.substring(i);
1217
}
1218
}
1219
return '';
Sep 5, 2014
1220
}
1221
1222
// note, maketrans should be a static function.
str
Feb 10, 2018
1223
str.maketrans = function() {
1224
var $ = $B.args('maketrans', 3, {x:null,y:null,z:null},['x','y','z'],
1225
arguments, {y:null, z:null}, null, null)
Feb 11, 2018
1227
var _t=_b_.dict.$factory()
1228
// make 'default' translate table
1229
for(var i=0; i < 256; i++) _t.$numeric_dict[i]=i
1230
1231
if($.y===null && $.z===null){
1232
// If there is only one argument, it must be a dictionary mapping
1233
// Unicode ordinals (integers) or characters (strings of length 1) to
1234
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1235
// keys will then be converted to ordinals.
1236
if(!_b_.isinstance($.x, _b_.dict)){
1237
throw _b_.TypeError.$factory('maketrans only argument must be a dict')
Feb 11, 2018
1239
var items = _b_.list.$factory(_b_.dict.items($.x))
1240
for(var i=0, len=items.length;i<len;i++){
1241
var k = items[i][0], v=items[i][1]
1242
if(!_b_.isinstance(k, _b_.int)){
1243
if(_b_.isinstance(k, _b_.str) && k.length==1){k = _b_.ord(k)}
1244
else{throw _b_.TypeError.$factory("dictionary key "+k+
1245
" is not int or 1-char string")}
1246
}
1247
if(v!==_b_.None && !_b_.isinstance(v, [_b_.int, _b_.str])){
1248
throw _b_.TypeError.$factory("dictionary value "+v+
1249
" is not None, integer or string")
1250
}
1251
_t.$numeric_dict[k] = v
1252
}
1253
return _t
1254
}else{
1255
// If there are two arguments, they must be strings of equal length,
1256
// and in the resulting dictionary, each character in x will be mapped
1257
// to the character at the same position in y
1258
if(!(_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1259
throw _b_.TypeError.$factory("maketrans arguments must be strings")
1260
}else if($.x.length!==$.y.length){
1261
throw _b_.TypeError.$factory("maketrans arguments must be strings or same length")
1262
}else{
1263
var toNone = {}
1264
if($.z!==null){
1265
// If there is a third argument, it must be a string, whose
1266
// characters will be mapped to None in the result
1267
if(!_b_.isinstance($.z, _b_.str)){
1268
throw _b_.TypeError.$factory('maketrans third argument must be a string')
1269
}
1270
for(var i=0,len=$.z.length;i<len;i++){
1271
toNone[_b_.ord($.z.charAt(i))] = true
1272
}
1274
for(var i=0,len=$.x.length;i<len;i++){
1275
_t.$numeric_dict[_b_.ord($.x.charAt(i))] = _b_.ord($.y.charAt(i))
1276
}
1277
for(var k in toNone){
1278
_t.$numeric_dict[k] = _b_.None
1279
}
1280
return _t
1281
}
1282
}
Sep 5, 2014
1283
}
1284
str
Feb 10, 2018
1285
str.partition = function() {
1286
var $=$B.args('partition',2,{self:null,sep:null},['self','sep'],
1287
arguments,{},null,null)
1288
if($.sep==''){throw _b_.ValueError.$factory('empty separator')}
1289
check_str($.sep)
1290
var i=$.self.indexOf($.sep)
Feb 11, 2018
1291
if (i== -1) return _b_.tuple.$factory([$.self, '', ''])
1292
return _b_.tuple.$factory([$.self.substring(0,i), $.sep,
1293
$.self.substring(i+$.sep.length)])
Sep 5, 2014
1294
}
1295
1296
function $re_escape(str)
1297
{
1298
var specials = "[.*+?|()$^"
1299
for(var i=0, _len_i = specials.length; i < _len_i;i++){
Sep 5, 2014
1300
var re = new RegExp('\\'+specials.charAt(i),'g')
1301
str = str.replace(re, "\\"+specials.charAt(i))
1302
}
1303
return str
1304
}
1305
str
Feb 10, 2018
1306
str.replace = function(self, old, _new, count) {
1307
// Replaces occurrences of 'old' by '_new'. Count references
1308
// the number of times to replace. In CPython, negative or undefined
1309
// values of count means replace all.
1310
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1311
['self','old','$$new','count'], arguments, {count:-1},null,null),
1312
count=$.count,self=$.self,old=$.old,_new=$.$$new
1313
// Validate type of old
1314
check_str(old)
1315
check_str(_new)
1316
// Validate instance type of 'count'
1317
if (!isinstance(count,[_b_.int,_b_.float])) {
1318
throw _b_.TypeError.$factory("'" + $B.get_class(count).__name__ +
1319
"' object cannot be interpreted as an integer");
1320
} else if (isinstance(count, _b_.float)) {
1321
throw _b_.TypeError.$factory("integer argument expected, got float");
1322
}
1323
if(count==0){return self}
Feb 11, 2018
1324
if(count.__class__==$B.long_int){count=parseInt(count.value)}
1325
if(old==''){
1326
if(_new==''){return self}
1327
if(self==''){return _new}
1328
var elts=self.split('')
1329
if(count>-1 && elts.length>=count){
1330
var rest = elts.slice(count).join('')
1331
return _new+elts.slice(0, count).join(_new)+rest
1332
}else{return _new+elts.join(_new)+_new}
1333
}else{
str
Feb 10, 2018
1334
var elts = str.split(self,old,count)
Sep 5, 2014
1335
}
1337
var res = self, pos = -1
1338
if(old.length==0){
1339
var res = _new
1340
for(var i=0;i<elts.length;i++){
1341
res += elts[i]+_new
1342
}
1343
return res+rest
1344
}
1346
if (count < 0) count = res.length;
1347
while (count > 0) {
1348
pos = res.indexOf(old, pos);
1349
if (pos < 0)
1350
break;
1351
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1352
pos = pos + _new.length;
1353
count--;
1354
}
1355
return res;
Sep 5, 2014
1356
}
1357
str
Feb 10, 2018
1358
str.rfind = function(self){
1359
// Return the highest index in the string where substring sub is found,
1360
// such that sub is contained within s[start:end]. Optional arguments
Sep 5, 2014
1361
// start and end are interpreted as in slice notation. Return -1 on failure.
1363
{self:null, sub:null, start:null, end:null},
1364
['self', 'sub', 'start', 'end'],
1365
arguments,{start:0, end:null},null,null)
Sep 5, 2014
1366
1369
check_str($.sub)
1371
if($.sub.length==0){
1372
if($.start>$.self.length){return -1}
1373
else{return $.self.length}
1374
}
1375
var sublen = $.sub.length
1377
for(var i=$.end-sublen;i>=$.start;i--){
1378
if($.self.substr(i, sublen)==$.sub){return i}
1379
}
1380
return -1
Sep 5, 2014
1381
}
1382
str
Feb 10, 2018
1383
str.rindex = function(){
Sep 5, 2014
1384
// Like rfind() but raises ValueError when the substring sub is not found
str
Feb 10, 2018
1385
var res = str.rfind.apply(null,arguments)
1386
if(res==-1){throw _b_.ValueError.$factory("substring not found")}
Sep 5, 2014
1387
return res
1388
}
1389
str
Feb 10, 2018
1390
str.rjust = function(self) {
1392
{self:null, width:null, fillchar:null},
1393
['self', 'width', 'fillchar'],
1394
arguments,{fillchar:' '},null,null)
Sep 5, 2014
1395
1396
if ($.width <= self.length) return self
Sep 5, 2014
1397
1398
return $.fillchar.repeat($.width - self.length) + self
Sep 5, 2014
1399
}
1400
str
Feb 10, 2018
1401
str.rpartition = function(self,sep) {
1402
var $=$B.args('rpartition',2,{self:null,sep:null},['self','sep'],
1403
arguments,{},null,null)
1404
check_str($.sep)
1405
var self = reverse($.self),
1406
sep = reverse($.sep)
str
Feb 10, 2018
1407
var items = str.partition(self,sep).reverse()
1408
for(var i=0;i<items.length;i++){
1409
items[i]=items[i].split('').reverse().join('')
1410
}
1411
return items
Sep 5, 2014
1412
}
1413
str
Feb 10, 2018
1414
str.rsplit = function(self) {
1415
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1416
['self','sep','maxsplit'],arguments,
1417
{sep:_b_.None, maxsplit:-1},null,null),
1419
1420
// Use split on the reverse of the string and of separator
1421
var rev_str = reverse($.self),
1422
rev_sep = sep === _b_.None ? sep : reverse($.sep),
str
Feb 10, 2018
1423
rev_res = str.split(rev_str, rev_sep, $.maxsplit)
1425
// Reverse the list, then each string inside the list
1426
rev_res.reverse()
1427
for(var i=0;i<rev_res.length;i++){
1428
rev_res[i] = reverse(rev_res[i])
Sep 5, 2014
1431
}
1432
str
Feb 10, 2018
1433
str.rstrip = function(self,x){
1434
var $=$B.args('rstrip',2,{self:null,chars:null},['self','chars'],
1435
arguments,{chars:_b_.None},null,null)
1436
if($.chars===_b_.None){return $.self.trimRight()}
1437
for (var j = $.self.length-1; j >= 0; j--) {
1438
if ($.chars.indexOf($.self.charAt(j)) === -1) {
1439
return $.self.substring(0,j+1);
1440
}
1441
}
1442
return '';
Sep 5, 2014
1443
}
1444
str
Feb 10, 2018
1445
str.split = function(){
1447
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1448
['self','sep','maxsplit'],arguments,
1449
{sep:_b_.None, maxsplit:-1},null,null)
1450
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
Feb 11, 2018
1451
if(maxsplit.__class__===$B.long_int){maxsplit=parseInt(maxsplit.value)}
1452
if(sep=='') throw _b_.ValueError.$factory('empty separator')
Sep 5, 2014
1454
var res = []
1455
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1456
if(pos===self.length-1){return [self]}
Sep 5, 2014
1457
var name = ''
1458
while(1){
1459
if(self.charAt(pos).search(/\s/)===-1){
1460
if(name===''){name=self.charAt(pos)}
1461
else{name+=self.charAt(pos)}
1462
}else{
1463
if(name!==''){
1464
res.push(name)
1465
if(maxsplit!==-1&&res.length===maxsplit+1){
1466
res.pop()
1467
res.push(name+self.substr(pos))
1468
return res
1469
}
1470
name=''
1471
}
1472
}
1473
pos++
1474
if(pos>self.length-1){
1475
if(name){res.push(name)}
1476
break
1477
}
1478
}
1479
return res
1480
}else{
1481
var res = [],s='',seplen=sep.length
1482
if(maxsplit==0){return [self]}
1483
while(pos<self.length){
1484
if(self.substr(pos,seplen)==sep){
1485
res.push(s)
1486
pos += seplen
1487
if(maxsplit>-1 && res.length>=maxsplit){
1488
res.push(self.substr(pos))
1489
return res
1490
}
1491
s= ''
1492
}else{
1493
s += self.charAt(pos)
1494
pos++
Sep 5, 2014
1495
}
1496
}
Sep 5, 2014
1499
}
1500
}
1501
str
Feb 10, 2018
1502
str.splitlines = function(self){
1503
var $=$B.args('splitlines',2,{self:null,keepends:null},
1504
['self','keepends'],arguments,{keepends:false},null,null)
1505
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1506
throw _b_.TypeError.$factory('integer argument expected, got '+
1507
$B.get_class($.keepends).__name)
1508
}
1509
var keepends = _b_.int.$factory($.keepends)
1510
// Remove trailing line breaks
1511
if(keepends){
1512
var res = [],
1513
start=pos,
1514
pos=0,
1515
self=$.self
1516
while(pos<self.length){
1517
if(self.substr(pos,2)=='\r\n'){
1518
res.push(self.substring(start,pos+2))
1519
start = pos+2
1520
pos = start
1521
}else if(self.charAt(pos)=='\r' || self.charAt(pos)=='\n'){
1522
res.push(self.substring(start,pos+1))
1523
start = pos+1
1524
pos = start
1525
}else{pos++}
1526
}
1527
var rest = self.substr(start)
1528
if(rest){res.push(rest)}
1529
return res
1530
}else{
1531
var self = $.self.replace(/[\r\n]$/,'')
1532
return self.split(/\n|\r\n|\r/)
1533
}
1534
}
Sep 5, 2014
1535
str
Feb 10, 2018
1536
str.startswith = function(){
1537
// Return True if string starts with the prefix, otherwise return False.
1538
// prefix can also be a tuple of prefixes to look for. With optional
1539
// start, test string beginning at that position. With optional end,
Sep 5, 2014
1540
// stop comparing string at that position.
1541
var $=$B.args("startswith",4,
1542
{self:null, prefix:null, start:null, end:null},
1543
['self', 'prefix', 'start', 'end'],
1544
arguments,{start:0, end:null},null,null)
Sep 5, 2014
1545
1546
normalize_start_end($)
1547
1548
var prefixes = $.prefix
1549
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1551
var s = $.self.substring($.start,$.end)
1552
for(var i=0, _len_i = prefixes.length; i < _len_i;i++){
1553
prefix = prefixes[i]
1554
if(!_b_.isinstance(prefix, str)){throw _b_.TypeError.$factory(
1555
"endswith first arg must be str or a tuple of str, not int")}
1556
if(s.substr(0,prefix.length)==prefix) return true
Sep 5, 2014
1557
}
1558
return false
1559
Sep 5, 2014
1560
}
1561
str
Feb 10, 2018
1562
str.strip = function(){
1563
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1564
arguments,{chars:_b_.None},null,null)
1565
if($.chars===_b_.None){return $.self.trim()}
1566
for (var i = 0; i < $.self.length; i++) {
1567
if ($.chars.indexOf($.self.charAt(i)) === -1) {
1568
break;
1569
}
1570
}
1571
for (var j = $.self.length-1; j >= i; j--) {
1572
if ($.chars.indexOf($.self.charAt(j)) === -1) {
1573
break;
1574
}
1575
}
1576
return $.self.substring(i,j+1);
Sep 5, 2014
1577
}
1578
str
Feb 10, 2018
1579
str.translate = function(self,table) {
1580
var res = [], pos=0
Sep 5, 2014
1581
if (isinstance(table, _b_.dict)) {
1582
for (var i=0, _len_i = self.length; i < _len_i; i++) {
Feb 11, 2018
1583
var repl = _b_.dict.get(table,self.charCodeAt(i),-1)
1584
if(repl==-1){res[pos++]=self.charAt(i)}
1585
else if(repl!==None){res[pos++]=_b_.chr(repl)}
Sep 5, 2014
1586
}
1587
}
1588
return res.join('')
Sep 5, 2014
1589
}
1590
str
Feb 10, 2018
1591
str.zfill = function(self, width) {
1592
var $=$B.args('zfill',2,{self:null,width:null},
1593
['self','width'],arguments,{},null,null)
1594
if ($.width <= self.length) {return self}
1595
switch(self.charAt(0)){
1596
case '+':
1597
case '-':
1598
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1599
default:
1600
return '0'.repeat(width - self.length)+self
1601
}
Sep 5, 2014
1602
}
1603
str
Feb 10, 2018
1604
str.$factory = function(arg){
1606
if(arg===undefined){console.log("undef"); return '<undefined>'}
1607
switch(typeof arg) {
1608
case 'string':
1609
return arg
1610
case 'number':
1611
if(isFinite(arg)){return arg.toString()}
1614
if(arg.$is_class || arg.$factory){
1615
// arg is a class
1616
// In this case, str() doesn't use the attribute __str__ of the
1617
// class or its subclasses, but the attribute __str__ of the
1618
// class metaclass (usually "type") or its subclasses (usually
1619
// "object")
1620
// The metaclass is the attribute __class__ of the class dictionary
1621
var func = $B.$getattr(arg.__class__, '__str__')
1623
}
Sep 5, 2014
1624
var f = getattr(arg,'__str__')
1625
// XXX fix : if not better than object.__str__, try __repr__
Sep 5, 2014
1627
}
1628
catch(err){
1629
console.log("pas de __str__ pour", arg)
1630
console.log('err ', err)
Sep 5, 2014
1631
try{ // try __repr__
1632
var f = getattr(arg,'__repr__')
1633
//return getattr(f,'__call__')()
Sep 5, 2014
1634
}catch(err){
1635
if($B.debug>1){console.log(err)}
1636
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1637
return arg.toString()
Sep 5, 2014
1638
}
1639
}
Sep 5, 2014
1641
}
str
Feb 10, 2018
1642
1643
str.__new__ = function(cls){
Sep 5, 2014
1644
if(cls===undefined){
1645
throw _b_.TypeError.$factory('str.__new__(): not enough arguments')
Sep 5, 2014
1646
}
1647
return {__class__:cls}
Sep 5, 2014
1648
}
1649
str
Feb 10, 2018
1650
$B.set_func_names(str, "builtins")
Sep 5, 2014
1652
// dictionary and factory for subclasses of string
str
Feb 10, 2018
1653
var StringSubclass = $B.StringSubclass = {
Feb 11, 2018
1654
__class__:_b_.type,
str
Feb 10, 2018
1655
__mro__: [object],
1656
__name__:'str',
1657
$is_class: true
Sep 5, 2014
1658
}
1659
str
Feb 10, 2018
1660
// the methods in subclass apply the methods in str to the
Sep 5, 2014
1661
// result of instance.valueOf(), which is a Javascript string
str
Feb 10, 2018
1662
for(var $attr in str){
1663
if(typeof str[$attr]=='function'){
1664
StringSubclass[$attr]=(function(attr){
Sep 5, 2014
1665
return function(){
1666
var args = [], pos=0
Sep 5, 2014
1667
if(arguments.length>0){
1668
var args = [arguments[0].valueOf()], pos=1
1669
for(var i=1, _len_i = arguments.length; i < _len_i;i++){
1670
args[pos++]=arguments[i]
Sep 5, 2014
1671
}
1672
}
str
Feb 10, 2018
1673
return str[attr].apply(null,args)
Sep 5, 2014
1674
}
1675
})($attr)
1676
}
1677
}
str
Feb 10, 2018
1678
StringSubclass.__new__ = function(cls){
Sep 5, 2014
1681
str
Feb 10, 2018
1682
$B.set_func_names(StringSubclass, "builtins")
Sep 5, 2014
1684
_b_.str = str
1685
1686
// Function to parse the 2nd argument of format()
1687
$B.parse_format_spec = function(spec){
1688
1689
if(spec==''){this.empty=true}
1690
else{
1691
var pos=0,
1692
aligns = '<>=^',
1693
digits = '0123456789',
1694
types = 'bcdeEfFgGnosxX%',
1695
align_pos = aligns.indexOf(spec.charAt(0))
1696
if(align_pos!=-1){
1697
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1698
// If the second char is also an alignment specifier, the
1699
// first char is the fill value
1700
this.fill = spec.charAt(0)
1701
this.align = spec.charAt(1)
1702
pos = 2
1703
}else{
1704
// The first character defines alignment : fill defaults to ' '
1705
this.align=aligns[align_pos];
1706
this.fill=' ';
1707
pos++
1708
}
1709
}else{
1710
align_pos = aligns.indexOf(spec.charAt(1))
1711
if(spec.charAt(1) && align_pos!=-1){
1712
// The second character defines alignment : fill is the first one
1713
this.align=aligns[align_pos]
1714
this.fill=spec.charAt(0)
1715
pos = 2
1716
}
1717
}
1718
var car = spec.charAt(pos)
1719
if(car=='+'||car=='-'||car==' '){
1720
this.sign=car;
1721
pos++;
1722
car=spec.charAt(pos);
1724
if(car=='#'){this.alternate=true;pos++;car=spec.charAt(pos)}
1725
if(car=='0'){
1726
// sign-aware : equivalent to fill=0 and align=='='
1727
this.fill='0'
1728
this.align = '='
1729
pos++;car=spec.charAt(pos)
1730
}
1731
while(car && digits.indexOf(car)>-1){
1732
if(this.width===undefined){this.width=car}
1733
else{this.width+=car}
1734
pos++;car=spec.charAt(pos)
1736
if(this.width!==undefined){this.width=parseInt(this.width)}
1737
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1738
if(car=='.'){
1739
if(digits.indexOf(spec.charAt(pos+1))==-1){
1740
throw _b_.ValueError.$factory("Missing precision in format spec")
1741
}
1742
this.precision = spec.charAt(pos+1)
1743
pos+=2;car=spec.charAt(pos)
1744
while(car && digits.indexOf(car)>-1){
1745
this.precision+=car;pos++;car=spec.charAt(pos)
1746
}
1747
this.precision = parseInt(this.precision)
1748
}
1749
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1750
if(pos!==spec.length){
Nov 11, 2015
1751
//console.log('error', spec, this, pos, spec.charAt(pos))
1752
throw _b_.ValueError.$factory("Invalid format specifier")
1755
this.toString = function(){
str
Feb 10, 2018
1756
return (this.fill===undefined ? '' : _b_.str.$factory(this.fill))+
1757
(this.align||'')+
1758
(this.sign||'')+
1759
(this.alternate ? '#' : '')+
1760
(this.sign_aware ? '0' : '')+
1761
(this.width || '')+
1762
(this.comma ? ',' : '')+
1763
(this.precision ? '.'+this.precision : '')+
1764
(this.type || '')
1765
}
1766
}
1767
1768
$B.format_width = function(s, fmt){
1769
if(fmt.width && s.length<fmt.width){
1770
var fill=fmt.fill || ' ', align = fmt.align || '<',
1771
missing = fmt.width-s.length
1772
switch(align){
1773
case '<':
1774
return s+fill.repeat(missing)
1775
case '>':
1776
return fill.repeat(missing)+s
1777
case '=':
1778
if('+-'.indexOf(s.charAt(0))>-1){
1779
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1780
}else{
1781
return fill.repeat(missing)+s
1782
}
1783
case '^':
1784
var left = parseInt(missing/2)
1785
return fill.repeat(left)+s+fill.repeat(missing-left)
1786
}
1787
}
1788
return s
1789
}
1790
1791
function fstring_expression(){
1792
this.type = 'expression'
1793
this.expression = ''
1794
this.conversion = null
1795
this.fmt = null
1796
}
1797
1798
$B.parse_fstring = function(string){
1799
// Parse a f-string
1800
var elts = [],
1801
pos = 0,
1802
current = '',
1803
ctype = null,
1804
nb_braces = 0,
1805
car
1806
1807
while(pos<string.length){
1808
if(ctype===null){
1809
car = string.charAt(pos)
1810
if(car=='{'){
1811
if(string.charAt(pos+1)=='{'){
1812
ctype = 'string'
1813
current = '{'
1814
pos += 2
1815
}else{
1816
ctype = 'expression'
1817
nb_braces = 1
1818
pos++
1819
}
1820
}else if(car=='}'){
1821
if(string.charAt(pos+1)==car){
1822
ctype = 'string'
1823
current = '}'
1824
pos += 2
1825
}else{
1826
throw Error(" f-string: single '}' is not allowed")
1827
}
1828
}else{
1829
ctype = 'string'
1830
current = car
1831
pos++
1832
}
1833
}else if(ctype=='string'){
1834
// end of string is the first single { or end of string
1835
var i=pos
1836
while(i<string.length){
1837
car = string.charAt(i)
1838
if(car=='{'){
1839
if(string.charAt(i+1)=='{'){
1840
current += '{'
1841
i+=2
1842
}else{
1843
elts.push(current)
1844
ctype = 'expression'
1845
pos = i+1
1846
break
1847
}
1848
}else if(car=='}'){
1849
if(string.charAt(i+1)==car){
1850
current += car
1851
i += 2
1852
}else{
1853
throw Error(" f-string: single '}' is not allowed")
1854
}
1855
}else{
1856
current += car
1857
i++
1858
}
1859
}
1860
pos = i+1
1861
}else{
1862
// End of expression is the } matching the opening {
1863
// There may be nested braces
1864
var i = pos,
1865
nb_braces = 1,
1866
nb_paren = 0,
1867
current = new fstring_expression()
1868
while(i<string.length){
1869
car = string.charAt(i)
1870
if(car=='{' && nb_paren==0){
1871
nb_braces++
1872
current.expression += car
1873
i++
1874
}else if(car=='}' && nb_paren==0){
1875
nb_braces -= 1
1876
if(nb_braces==0){
1877
// end of expression
1878
elts.push(current)
1879
ctype = null
1880
current = ''
1881
pos = i+1
1882
break
1884
current.expression += car
1885
i++
1886
}else if(car=='\\'){
1887
// backslash is not allowed in expressions
1888
throw Error("f-string expression part cannot include a" +
1889
" backslash")
1890
}else if(nb_paren == 0 && car=='!' && current.fmt===null &&
1891
':}'.indexOf(string.charAt(i + 2))>-1){
1892
if(current.expression.length==0){
1893
throw Error("f-string: empty expression not allowed")
1894
}
1895
if('ars'.indexOf(string.charAt(i+1)) == -1){
1896
throw Error("f-string: invalid conversion character:" +
1897
" expected 's', 'r', or 'a'")
1898
}else{
1899
current.conversion = string.charAt(i+1)
1900
i += 2
1901
}
1902
}else if(car=='('){
1903
nb_paren++
1904
current.expression += car
1905
i++
1906
}else if(car==')'){
1907
nb_paren--
1908
current.expression += car
1909
i++
1910
}else if(car=='"'){
1911
// triple string ?
1912
if(string.substr(i, 3)=='"""'){
1913
var end = string.indexOf('"""', i+3)
1914
if(end==-1){throw Error("f-string: unterminated string")}
1915
else{
1916
var trs = string.substring(i, end+3)
1917
trs = trs.replace('\n', '\\n\\')
1918
current.expression += trs
1919
i = end+3
1920
}
1921
}else{
1922
var end = string.indexOf('"', i+1)
1923
if(end==-1){throw Error("f-string: unterminated string")}
1924
else{
1925
current.expression += string.substring(i, end+1)
1926
i = end+1
1927
}
1928
}
1929
}else if(nb_paren == 0 && car==':'){
1930
current.fmt = true
1931
current.expression += car
1932
i++
1933
}else{
1934
current.expression += car
1935
i++
1936
}
1937
}
1938
if(nb_braces>0){
1939
throw Error("f-string: expected '}'")
1940
}
1941
}
1942
}
1943
if(current.length>0){elts.push(current)}
1944
return elts
1945
}
1946
Sep 5, 2014
1947
})(__BRYTHON__)