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