Permalink
Jan 14, 2015
Jan 14, 2015
Jan 1, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Dec 3, 2015
Dec 3, 2015
Jan 5, 2016
Jan 6, 2016
Jan 1, 2015
Jan 1, 2015
Jan 30, 2016
Newer
100644
1810 lines (1622 sloc)
58.1 KB
13
function normalize_start_end($){
14
if($.start===null||$.start===_b_.None){$.start = 0}
15
else if($.start<0){$.start += $.self.length; $.start=Math.max(0, $.start)}
16
if($.end===null||$.end===_b_.None){$.end = $.self.length}
17
else if($.end<0){$.end += $.self.length; $.end=Math.max(0, $.end)}
18
19
if(!isinstance($.start,_b_.int)||!isinstance($.end,_b_.int)){
20
throw _b_.TypeError(
21
"slice indices must be integers or None or have an __index__ method")}
22
23
}
24
25
function reverse(s){
26
// Reverse a string
27
return s.split('').reverse().join('')
28
}
29
30
function check_str(obj){
31
if(!_b_.isinstance(obj,str)){throw _b_.TypeError("can't convert '"+
32
$B.get_class(obj).__name__+"' object to str implicitely")}
35
$StringDict.__add__ = function(self,other){
36
if(!(typeof other==="string")){
37
try{return getattr(other,'__radd__')(self)}
38
catch(err){throw _b_.TypeError(
39
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
40
}
41
return self+other
42
}
43
44
$StringDict.__contains__ = function(self,item){
45
if(!(typeof item==="string")){throw _b_.TypeError(
46
"'in <string>' requires string as left operand, not "+item.__class__)}
47
var nbcar = item.length
48
if(nbcar==0) return true // a string contains the empty string
49
if(self.length==0) return nbcar==0
51
if(self.substr(i,nbcar)==item) return true
52
}
53
return false
54
}
55
56
$StringDict.__delitem__ = function(){
57
throw _b_.TypeError("'str' object doesn't support item deletion")
58
}
59
60
// __dir__must be assigned explicitely because attribute resolution for builtin
61
// classes doesn't use __mro__
62
$StringDict.__dir__ = $ObjectDict.__dir__
63
64
$StringDict.__eq__ = function(self,other){
65
if(other===undefined){ // compare object "self" to class "str"
66
return self===str
67
}
68
if (_b_.isinstance(other, _b_.str)) {
69
return other.valueOf() == self.valueOf()
70
}
74
function preformat(self, fmt){
75
if(fmt.empty){return _b_.str(self)}
76
if(fmt.type && fmt.type!='s'){
77
throw _b_.ValueError("Unknown format code '"+fmt.type+
78
"' for object of type 'str'")
79
}
80
return self
81
}
82
83
$StringDict.__format__ = function(self, format_spec) {
84
var fmt = new $B.parse_format_spec(format_spec)
85
// For strings, alignment default to left
86
fmt.align = fmt.align || '<'
87
return $B.format_width(preformat(self, fmt), fmt)
88
}
89
90
$StringDict.__getitem__ = function(self,arg){
91
if(isinstance(arg,_b_.int)){
92
var pos = arg
93
if(arg<0) pos+=self.length
94
if(pos>=0 && pos<self.length) return self.charAt(pos)
95
throw _b_.IndexError('string index out of range')
96
}
97
if(isinstance(arg,slice)) {
98
var s=_b_.slice.$dict.$conv_for_seq(arg, self.length),
99
start=s.start, stop=s.stop, step=s.step
100
var res = '',i=null
101
if(step>0){
102
if(stop<=start) return ''
103
for(var i=start;i<stop;i+=step) res += self.charAt(i)
104
} else {
105
if(stop>=start) return ''
107
}
108
return res
109
}
110
if(isinstance(arg,bool)) return self.__getitem__(_b_.int(arg))
115
if (self === undefined) {
116
return $StringDict.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
117
}
118
119
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
120
// this implementation for strings maybe good enough for us..
121
122
var hash=1;
124
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
125
}
126
127
return hash
128
}
129
130
$StringDict.__init__ = function(self,arg){
131
self.valueOf = function(){return arg}
132
self.toString = function(){return arg}
134
}
135
136
var $str_iterator = $B.$iterator_class('str_iterator')
137
$StringDict.__iter__ = function(self){
138
var items = self.split('') // list of all characters in string
139
return $B.$iterator(items,$str_iterator)
140
}
141
142
$StringDict.__len__ = function(self){return self.length}
143
146
var kwarg_key = new RegExp('([^\\)]*)\\)')
147
148
var NotANumber = function() {
149
this.name = 'NotANumber'
150
}
151
152
var number_check=function(s) {
153
if(!isinstance(s,[_b_.int,_b_.float])){
154
throw new NotANumber()
155
}
156
}
157
158
var get_char_array = function(size, char) {
159
if (size <= 0)
160
return ''
161
return new Array(size + 1).join(char)
162
}
163
164
var format_padding = function(s, flags, minus_one) {
165
var padding = flags.padding
166
if (!padding) { // undefined
167
return s
168
}
169
s = s.toString()
170
padding = parseInt(padding, 10)
171
if (minus_one) { // numeric formatting where sign goes in front of padding
172
padding -= 1
173
}
174
if (!flags.left) {
175
return get_char_array(padding - s.length, flags.pad_char) + s
176
} else {
177
// left adjusted
178
return s + get_char_array(padding - s.length, flags.pad_char)
179
}
180
}
181
182
var format_int_precision = function(val, flags) {
183
var precision = flags.precision
184
if (!precision) {
185
return val.toString()
186
}
187
precision = parseInt(precision, 10)
188
var s
189
if (val.__class__ === $B.LongInt.$dict) {
190
s=$B.LongInt.$dict.to_base(val, 10)
191
} else {
192
s=val.toString()
193
}
194
var sign = s[0]
195
if (s[0] === '-') {
196
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
197
}
198
return get_char_array(precision - s.length, '0') + s
199
}
200
201
var format_float_precision = function(val, upper, flags, modifier) {
202
var precision = flags.precision
203
// val is a float
204
if (isFinite(val)) {
205
val = modifier(val, precision, flags, upper)
206
return val
207
}
208
if (val === Infinity) {
209
val = 'inf'
210
} else if (val === -Infinity) {
211
val = '-inf'
212
} else {
213
val = 'nan'
214
}
215
if (upper) {
216
return val.toUpperCase()
217
}
218
return val
220
}
221
222
var format_sign = function(val, flags) {
223
if (flags.sign) {
224
if (val >= 0) {
225
return "+"
227
} else if (flags.space) {
228
if (val >= 0) {
229
return " "
230
}
231
}
232
return ""
233
}
235
var str_format = function(val, flags) {
236
// string format supports left and right padding
237
flags.pad_char = " " // even if 0 padding is defined, don't use it
238
return format_padding(str(val), flags)
239
}
243
if (val.__class__ === $B.LongInt.$dict) {
244
val = $B.LongInt.$dict.to_base(val, 10)
245
} else {
246
val = parseInt(val)
247
}
248
249
var s = format_int_precision(val, flags)
250
if (flags.pad_char === '0') {
251
if (val < 0) {
252
s = s.substring(1)
253
return '-' + format_padding(s, flags, true)
254
}
255
var sign = format_sign(val, flags)
256
if (sign !== '') {
257
return sign + format_padding(s, flags, true)
258
}
259
}
260
261
return format_padding(format_sign(val, flags) + s, flags)
262
}
264
var repr_format = function(val, flags) {
265
flags.pad_char = " " // even if 0 padding is defined, don't use it
266
return format_padding(repr(val), flags)
267
}
269
var ascii_format = function(val, flags) {
270
flags.pad_char = " " // even if 0 padding is defined, don't use it
271
return format_padding(ascii(val), flags)
272
}
274
// converts to val to float and sets precision if missing
275
var _float_helper = function(val, flags) {
276
number_check(val)
277
if (!flags.precision) {
278
if (!flags.decimal_point) {
279
flags.precision = 6
280
} else {
281
flags.precision = 0
282
}
283
} else {
284
flags.precision = parseInt(flags.precision, 10)
285
validate_precision(flags.precision)
286
}
287
return parseFloat(val)
288
}
290
// used to capture and remove trailing zeroes
291
var trailing_zeros = /(.*?)(0+)([eE].*)/
292
var leading_zeros = /\.(0*)/
293
var trailing_dot = /\.$/
295
var validate_precision = function(precision) {
296
// force precision to limits of javascript
298
}
299
300
// gG
301
var floating_point_format = function(val, upper, flags) {
302
val = _float_helper(val, flags)
303
var v = val.toString()
304
var v_len = v.length
305
var dot_idx = v.indexOf('.')
306
if (dot_idx < 0) {
307
dot_idx = v_len
308
}
309
if (val < 1 && val > -1) {
310
var zeros = leading_zeros.exec(v)
311
var numzeros
312
if (zeros) {
313
numzeros = zeros[1].length
314
} else {
315
numzeros = 0
316
}
317
if (numzeros >= 4) {
318
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
319
if (!flags.alternate) {
320
var trl = trailing_zeros.exec(val)
321
if (trl) {
322
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
328
}
329
return format_padding(val, flags)
330
}
331
flags.precision += numzeros
332
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
333
function(val, precision) {
334
val = val.toFixed(min(precision, v_len - dot_idx) + numzeros)
335
}), flags)
336
}
337
338
if (dot_idx > flags.precision) {
339
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
340
if (!flags.alternate) {
341
var trl = trailing_zeros.exec(val)
342
if (trl) {
343
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
344
}
345
} else {
346
if (flags.precision <= 1) {
347
val = val[0] + '.' + val.substring(1)
348
}
349
}
350
return format_padding(val, flags)
351
}
352
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
353
function(val, precision) {
354
if (!flags.decimal_point) {
355
precision = min(v_len - 1, 6)
356
} else if (precision > v_len) {
357
if (!flags.alternate) {
358
precision = v_len
360
}
361
if (precision < dot_idx) {
362
precision = dot_idx
363
}
364
return val.toFixed(precision - dot_idx)
365
}), flags)
366
}
368
var _floating_g_exp_helper = function(val, precision, flags, upper) {
369
if (precision) {
370
--precision
371
}
372
val = val.toExponential(precision)
373
// pad exponent to two digits
374
var e_idx = val.lastIndexOf('e')
375
if (e_idx > val.length - 4) {
376
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
377
}
378
if (upper) {
379
return val.toUpperCase()
380
}
381
return val
382
}
383
384
// fF
385
var floating_point_decimal_format = function(val, upper, flags) {
386
val = _float_helper(val, flags)
387
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
388
function(val, precision, flags) {
389
val = val.toFixed(precision)
390
if (precision === 0 && flags.alternate) {
391
val += '.'
392
}
393
return val
394
}), flags)
395
}
396
397
var _floating_exp_helper = function(val, precision, flags, upper) {
398
val = val.toExponential(precision)
399
// pad exponent to two digits
400
var e_idx = val.lastIndexOf('e')
401
if (e_idx > val.length - 4) {
402
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
403
}
404
if (upper) {
405
return val.toUpperCase()
406
}
407
return val
408
}
409
410
// eE
411
var floating_point_exponential_format = function(val, upper, flags) {
412
val = _float_helper(val, flags)
413
414
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
415
}
416
417
var signed_hex_format = function(val, upper, flags) {
420
421
if (val.__class__ === $B.LongInt.$dict) {
422
ret=$B.LongInt.$dict.to_base(val, 16)
423
} else {
424
ret = parseInt(val)
425
ret = ret.toString(16)
426
}
427
ret = format_int_precision(ret, flags)
428
if (upper) {
429
ret = ret.toUpperCase()
430
}
431
if (flags.pad_char === '0') {
432
if (val < 0) {
433
ret = ret.substring(1)
434
ret = '-' + format_padding(ret, flags, true)
435
}
436
var sign = format_sign(val, flags)
437
if (sign !== '') {
438
ret = sign + format_padding(ret, flags, true)
440
}
441
442
if (flags.alternate) {
443
if (ret.charAt(0) === '-') {
444
if (upper) {
445
ret = "-0X" + ret.slice(1)
446
} else {
447
ret = "-0x" + ret.slice(1)
448
}
449
} else {
450
if (upper) {
451
ret = "0X" + ret
452
} else {
453
ret = "0x" + ret
454
}
455
}
456
}
457
return format_padding(format_sign(val, flags) + ret, flags)
458
}
462
var ret
463
464
if (val.__class__ === $B.LongInt.$dict) {
465
ret = $B.LongInt.$dict.to_base(8)
466
} else {
467
ret = parseInt(val)
468
ret = ret.toString(8)
469
}
470
473
if (flags.pad_char === '0') {
474
if (val < 0) {
475
ret = ret.substring(1)
476
ret = '-' + format_padding(ret, flags, true)
477
}
478
var sign = format_sign(val, flags)
479
if (sign !== '') {
480
ret = sign + format_padding(ret, flags, true)
481
}
483
484
if (flags.alternate) {
485
if (ret.charAt(0) === '-') {
486
ret = "-0o" + ret.slice(1)
487
} else {
488
ret = "0o" + ret
489
}
491
return format_padding(ret, flags)
492
}
493
494
var single_char_format = function(val, flags) {
495
if(isinstance(val,str) && val.length==1) return val
496
try {
497
val = _b_.int(val) // yes, floats are valid (they are cast to int)
498
} catch (err) {
499
throw _b_.TypeError('%c requires int or char')
500
}
501
return format_padding(chr(val), flags)
502
}
503
504
var num_flag = function(c, flags) {
505
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
506
flags.pad_char = '0'
507
return
508
}
509
if (!flags.decimal_point) {
510
flags.padding = (flags.padding || "") + c
511
} else {
512
flags.precision = (flags.precision || "") + c
513
}
514
}
515
516
var decimal_point_flag = function(val, flags) {
517
if (flags.decimal_point) {
518
// can only have one decimal point
519
throw new UnsupportedChar()
520
}
521
flags.decimal_point = true
522
}
523
524
var neg_flag = function(val, flags) {
525
flags.pad_char = ' ' // overrides '0' flag
526
flags.left = true
527
}
528
529
var space_flag = function(val, flags) {
530
flags.space = true
531
}
532
533
var sign_flag = function(val, flags) {
534
flags.sign = true
535
}
536
537
var alternate_flag = function(val, flags) {
538
flags.alternate = true
539
}
540
542
's': str_format,
543
'd': num_format,
544
'i': num_format,
545
'u': num_format,
546
'o': octal_format,
547
'r': repr_format,
548
'a': ascii_format,
549
'g': function(val, flags) {return floating_point_format(val, false, flags)},
550
'G': function(val, flags) {return floating_point_format(val, true, flags)},
551
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
552
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
553
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
554
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
555
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
556
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
557
'c': single_char_format,
558
'0': function(val, flags) {return num_flag('0', flags)},
559
'1': function(val, flags) {return num_flag('1', flags)},
560
'2': function(val, flags) {return num_flag('2', flags)},
561
'3': function(val, flags) {return num_flag('3', flags)},
562
'4': function(val, flags) {return num_flag('4', flags)},
563
'5': function(val, flags) {return num_flag('5', flags)},
564
'6': function(val, flags) {return num_flag('6', flags)},
565
'7': function(val, flags) {return num_flag('7', flags)},
566
'8': function(val, flags) {return num_flag('8', flags)},
567
'9': function(val, flags) {return num_flag('9', flags)},
568
'-': neg_flag,
569
' ': space_flag,
570
'+': sign_flag,
571
'.': decimal_point_flag,
572
'#': alternate_flag
573
}
574
575
// exception thrown when an unsupported char is encountered in legacy format
576
var UnsupportedChar = function() {
577
this.name = "UnsupportedChar"
578
}
579
591
++pos
592
var rslt = kwarg_key.exec(s.substring(newpos))
593
if (!rslt) {
594
throw _b_.ValueError("incomplete format key")
595
}
596
var key = rslt[1]
597
newpos += rslt[0].length
598
try {
600
} catch(err) {
601
if (err.name === "KeyError") {
602
throw err
603
}
604
throw _b_.TypeError("format requires a mapping")
605
}
620
}
621
catch(err) {
622
if (err.name === "IndexError") {
623
throw _b_.TypeError("not enough arguments for format string")
624
} else {
625
throw err
626
}
632
// todo: get flags, type
633
// todo: string value based on flags, type, value
634
var flags = {'pad_char': ' '}
635
do {
642
if (ret !== undefined) {
643
return ret
644
}
645
++newpos
646
}
647
} catch (err) {
648
if (err.name === "UnsupportedChar") {
649
invalid_char = s[newpos]
650
if (invalid_char === undefined) {
651
throw _b_.ValueError("incomplete format")
652
}
653
throw _b_.ValueError("unsupported format character '" + invalid_char +
654
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
655
} else if (err.name === "NotANumber") {
656
var try_char = s[newpos]
663
}
664
} else {
665
cls = cls.__name__
666
}
667
throw _b_.TypeError("%" + try_char + " format: a number is required, not " + cls)
668
} else {
669
throw err
670
}
692
}
693
}
694
} else {
695
// % at end of string
696
throw _b_.ValueError("incomplete format")
697
}
698
pos = newpos + 1
699
} while (pos < length)
700
703
704
$StringDict.__mro__ = [$StringDict,$ObjectDict]
705
706
$StringDict.__mul__ = function(self,other){
707
var $=$B.args('__mul__',2,{self:null,other:null},['self','other'],
708
arguments,{},null,null)
709
if(!isinstance(other,_b_.int)){throw _b_.TypeError(
710
"Can't multiply sequence by non-int of type '"+
711
$B.get_class(other).__name__+"'")}
712
$res = ''
713
for(var i=0;i<other;i++){$res+=self.valueOf()}
714
return $res
715
}
716
717
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
718
719
$StringDict.__repr__ = function(self){
720
var res = self.replace(/\n/g,'\\\\n')
721
// escape the escape char
722
res = res.replace(/\\/g, '\\\\')
723
if(res.search('"')==-1 && res.search("'")==-1){
724
return "'"+res+"'"
733
$StringDict.__setattr__ = function(self,attr,value){return setattr(self,attr,value)}
734
735
$StringDict.__setitem__ = function(self,attr,value){
736
throw _b_.TypeError("'str' object does not support item assignment")
737
}
738
$StringDict.__str__ = function(self){
739
if(self===undefined) return "<class 'str'>"
740
return self.toString()
741
}
742
$StringDict.toString = function(){return 'string!'}
743
744
// generate comparison methods
745
var $comp_func = function(self,other){
746
if(typeof other !=="string"){throw _b_.TypeError(
747
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
748
return self > other
749
}
750
$comp_func += '' // source code
751
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
752
for(var $op in $comps){
753
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
754
}
755
756
// add "reflected" methods
757
$B.make_rmethods($StringDict)
758
759
// unsupported operations
760
var $notimplemented = function(self,other){
761
throw NotImplementedError("OPERATOR not implemented for class str")
762
}
763
764
$StringDict.capitalize = function(self){
765
if(self.length==0) return ''
766
return self.charAt(0).toUpperCase()+self.substr(1).toLowerCase()
767
}
768
769
$StringDict.casefold = function(self) {
770
throw _b_.NotImplementedError("function casefold not implemented yet");
771
}
772
773
$StringDict.center = function(self,width,fillchar){
774
var $=$B.args("center",3,
775
{self:null, width:null, fillchar:null},
776
['self', 'width', 'fillchar'],
777
arguments,{fillchar:' '},null,null)
778
779
if($.width<=self.length) return self
788
$StringDict.count = function(){
789
var $ = $B.args('count', 4, {self:null, sub:null, start:null, stop:null},
794
var substr = $.self
795
if($.start!==null){
796
var _slice
797
if($.stop!==null){_slice = _b_.slice($.start, $.stop)}
798
else{_slice = _b_.slice($.start,$.self.length)}
799
substr = $StringDict.__getitem__.apply(null, [$.self].concat(_slice))
800
}else{
801
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
802
}
803
if($.sub.length==0){
804
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
805
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
806
return substr.length+1
807
}
808
var n=0, pos=0
809
while(pos<substr.length){
810
pos=substr.indexOf($.sub,pos)
812
}
813
return n
814
}
815
816
$StringDict.encode = function(self, encoding) {
817
if (encoding === undefined) encoding='utf-8'
818
if(encoding=='rot13' || encoding=='rot_13'){
819
// Special case : returns a string
820
var res = ''
821
for(var i=0, _len = self.length; i<_len ; i++){
822
var char = self.charAt(i)
823
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
824
res += String.fromCharCode(String.charCodeAt(char)+13)
825
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
826
res += String.fromCharCode(String.charCodeAt(char)-13)
827
}else{res += char}
828
}
829
return res
830
}
835
// Return True if the string ends with the specified suffix, otherwise
836
// return False. suffix can also be a tuple of suffixes to look for.
837
// With optional start, test beginning at that position. With optional
838
// end, stop comparing at that position.
840
{self:null, suffix:null, start:null, end:null},
841
['self', 'suffix', 'start', 'end'],
842
arguments,{start:0, end:null},null,null)
843
844
normalize_start_end($)
845
846
var suffixes = $.suffix
852
if(!_b_.isinstance(suffix, str)){throw _b_.TypeError(
853
"endswith first arg must be str or a tuple of str, not int")}
854
if(suffix.length<=s.length &&
855
s.substr(s.length-suffix.length)==suffix) return true
856
}
857
return false
858
}
859
860
$StringDict.expandtabs = function(self, tabsize) {
861
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
862
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
863
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
864
if(s==1){return self.replace(/\t/g,' ')}
865
while(pos<self.length){
866
var car = self.charAt(pos)
867
switch(car){
868
case '\t':
869
while(col%s > 0){res += ' ';col++}
870
break
871
case '\r':
872
case '\n':
873
res += car
874
col = 0
875
break
876
default:
877
res += car
878
col++
879
break
880
}
881
pos++
882
}
883
884
return res
888
// Return the lowest index in the string where substring sub is found,
889
// such that sub is contained in the slice s[start:end]. Optional
890
// arguments start and end are interpreted as in slice notation.
891
// Return -1 if sub is not found.
900
throw _b_.TypeError(
901
"slice indices must be integers or None or have an __index__ method")}
902
var s = $.self.substring($.start,$.end)
903
904
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
905
if(s.length+$.sub.length==0){return -1}
906
907
var last_search = s.length-$.sub.length
908
for(var i=0;i<=last_search;i++){
909
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
918
// Parse a "format string", as described in the Python documentation
919
// Return a format object. For the format string
920
// a.x[z]!r:...
921
// the object has attributes :
922
// - name : "a"
923
// - name_ext : [".x", "[z]"]
924
// - conv : r
925
// - spec : rest of string after :
927
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
928
if(elts.length==1){
929
// No : in the string : it only contains a name
930
name = fmt_string
931
}else{
932
// name is before the first ":"
933
// spec (the format specification) is after
934
name = elts[0]
935
spec = elts.splice(1).join(':')
936
}
937
938
var elts = name.split('!')
939
if(elts.length>1){
940
name=elts[0]
941
conv=elts[1] // conversion flag
942
if(conv.length!==1 || 'ras'.search(conv)==-1){
943
throw _b_.ValueError('wrong conversion flag '+conv)
944
}
945
}
947
if(name!==undefined){
948
// "name' may be a subscription or attribute
949
// Put these "extensions" in the list "name_ext"
950
function name_repl(match){
951
name_ext.push(match)
952
return ''
953
}
954
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
955
name = name.replace(name_ext_re, name_repl)
956
}
965
arguments, {}, 'args', 'kw')
966
967
// Parse self to detect formatting instructions
968
// Create a list "parts" made of sections of the string :
969
// - elements of even rank are literal text
970
// - elements of odd rank are "format objects", built from the
971
// format strings in self (of the form {...})
972
var pos=0, _len=self.length, car, text='', parts=[], rank=0, defaults={}
973
974
while(pos<_len){
975
car = self.charAt(pos)
976
if(car=='{' && self.charAt(pos+1)=='{'){
977
// replace {{ by literal {
978
text += '{'
979
pos+=2
980
}else if(car=='}' && self.charAt(pos+1)=='}'){
981
// replace }} by literal }
982
text += '}'
983
pos+=2
984
}else if(car=='{'){
985
// Start of a format string
986
987
// Store current literal text
988
parts.push(text)
989
990
// Search the end of the format string, ie the } closing the
991
// opening {. Since the string can contain other pairs {} for
992
// nested formatting, an integer nb is incremented for each { and
993
// decremented for each } ; the end of the format string is
994
// reached when nb==0
995
var end = pos+1, nb=1
996
while(end<_len){
997
if(self.charAt(end)=='{'){nb++;end++}
998
else if(self.charAt(end)=='}'){
999
nb--;end++
1000
if(nb==0){
1001
// End of format string
1002
var fmt_string = self.substring(pos+1, end-1)
1003
1004
// Create a format object, by function parse_format
1005
var fmt_obj = parse_format(fmt_string)
1006
1007
// If no name is explicitely provided, use the rank
1008
if(!fmt_obj.name){
1009
fmt_obj.name=rank+''
1010
rank++
1011
}
1015
// In this case, evaluate them using the positional
1016
// or keyword arguments passed to format()
1018
if(/\d+/.exec(key)){
1019
// If key is numeric, search in positional
1020
// arguments
1021
return _b_.tuple.$dict.__getitem__($.args,
1022
parseInt(key))
1023
}else{
1024
// Else try in keyword arguments
1025
return _b_.dict.$dict.__getitem__($.kw, key)
1026
}
1027
}
1028
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1029
replace_nested)
1030
}
1031
1032
// Store format object in list "parts"
1033
parts.push(fmt_obj)
1034
text = ''
1035
break
1036
}
1037
}else{end++}
1039
if(nb>0){throw ValueError("wrong format "+self)}
1040
pos = end
1041
}else{text += car;pos++}
1045
// Apply formatting to the values passed to format()
1046
var res = '', fmt
1047
for(var i=0;i<parts.length;i++){
1048
// Literal text is added unchanged
1049
if(typeof parts[i]=='string'){res += parts[i];continue}
1050
1051
// Format objects
1052
fmt = parts[i]
1053
if(fmt.name.charAt(0).search(/\d/)>-1){
1054
// Numerical reference : use positional arguments
1055
var pos = parseInt(fmt.name),
1056
value = _b_.tuple.$dict.__getitem__($.args, pos)
1057
}else{
1058
// Use keyword arguments
1059
var value = _b_.dict.$dict.__getitem__($.kw, fmt.name)
1060
}
1061
// If name has extensions (attributes or subscriptions)
1062
for(var j=0;j<fmt.name_ext.length;j++){
1063
var ext = fmt.name_ext[j]
1064
if(ext.charAt(0)=='.'){
1065
// Attribute
1066
value = _b_.getattr(value, ext.substr(1))
1067
}else{
1068
// Subscription
1069
var key = ext.substr(1, ext.length-2)
1070
// An index made of digits is transformed into an integer
1071
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1072
value = _b_.getattr(value, '__getitem__')(key)
1073
}
1074
}
1075
// If the conversion flag is set, first call a function to convert
1076
// the value
1077
if(fmt.conv=='a'){value = _b_.ascii(value)}
1078
else if(fmt.conv=='r'){value = _b_.repr(value)}
1079
else if(fmt.conv=='s'){value = _b_.str(value)}
1080
1081
// Call attribute __format__ to perform the actual formatting
1082
res += _b_.getattr(value, '__format__')(fmt.spec)
1085
}
1086
1087
$StringDict.format_map = function(self) {
1088
throw NotImplementedError("function format_map not implemented yet");
1089
}
1090
1091
$StringDict.index = function(self){
1092
// Like find(), but raise ValueError when the substring is not found.
1094
if(res===-1) throw _b_.ValueError("substring not found")
1095
return res
1096
}
1097
1098
$StringDict.isalnum = function() {
1099
var $=$B.args('isalnum',1,{self:null},['self'],arguments,{},null,null)
1100
return /^[a-z0-9]+$/i.test($.self)
1101
}
1103
$StringDict.isalpha = function(self) {
1104
var $=$B.args('isalpha',1,{self:null},['self'],arguments,{},null,null)
1105
return /^[a-z]+$/i.test($.self)
1106
}
1108
$StringDict.isdecimal = function(){
1109
var $=$B.args('isdecimal',1,{self:null},['self'],arguments,{},null,null)
1111
return /^[0-9]+$/.test($.self)
1112
}
1113
1114
$StringDict.isdigit = function() {
1115
var $=$B.args('isdigit',1,{self:null},['self'],arguments,{},null,null)
1116
return /^[0-9]+$/.test($.self)
1117
}
1118
1119
$StringDict.isidentifier = function() {
1120
var $=$B.args('isidentifier',1,{self:null},['self'],arguments,{},null,null)
1122
if($.self.search(/\$/)>-1){return false}
1123
var last = $.self.charAt($.self.length-1)
1124
if(' \n;'.search(last)>-1){return false}
1125
var dummy = {}
1126
try{eval("dummy."+$.self); return true}
1127
catch(err){return false}
1128
}
1129
1130
$StringDict.islower = function() {
1131
var $=$B.args('islower',1,{self:null},['self'],arguments,{},null,null)
1132
// A string only made of whitespace is not lower for Python
1133
return $.self==$.self.toLowerCase() && $.self.search(/^\s*$/)==-1
1137
$StringDict.isnumeric = function() {
1138
var $=$B.args('isnumeric',1,{self:null},['self'],arguments,{},null,null)
1139
return /^[0-9]+$/.test($.self)
1140
}
1143
$StringDict.isprintable = function() {
1144
var $=$B.args('isprintable',1,{self:null},['self'],arguments,{},null,null)
1145
return !/[^ -~]/.test($.self)
1146
}
1148
$StringDict.isspace = function() {
1149
var $=$B.args('isspace',1,{self:null},['self'],arguments,{},null,null)
1150
return /^\s+$/i.test($.self)
1151
}
1153
$StringDict.istitle = function() {
1154
var $=$B.args('istitle',1,{self:null},['self'],arguments,{},null,null)
1155
if($.self.search(/^\s*$/)>-1){return false}
1156
1157
function get_case(char){
1158
if(char.toLowerCase()==char.toUpperCase()){return false}
1159
else if(char==char.toLowerCase()){return 'lower'}
1160
else{return 'upper'}
1161
}
1162
var pos=0,char,previous=false
1163
while(pos<$.self.length){
1164
char = $.self.charAt(pos)
1165
if(previous===undefined){previous=get_case(char)}
1166
else{
1167
_case = get_case(char)
1168
if(_case=='upper' && previous){return false}
1169
else if(_case=='lower' && !previous){return false}
1170
previous=_case
1171
}
1172
pos++
1173
}
1174
return true
1175
}
1177
$StringDict.isupper = function() {
1178
var $=$B.args('isupper',1,{self:null},['self'],arguments,{},null,null)
1179
return $.self==$.self.toUpperCase() && $.self.search(/^\s*$/)==-1
1180
}
1182
$StringDict.join = function(){
1183
var $=$B.args('join',2,{self:null,iterable:null},
1184
['self', 'iterable'], arguments, {}, null, null)
1185
1186
var iterable=_b_.iter($.iterable)
1187
var res = [],count=0
1191
if(!isinstance(obj2,str)){throw _b_.TypeError(
1192
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1202
$StringDict.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)
1210
$StringDict.lower = function(){
1211
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1212
return $.self.toLowerCase()
1213
}
1216
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1217
arguments,{chars:_b_.None},null,null)
1218
if($.chars===_b_.None){return $.self.replace(/^\s+/,'')}
1219
return $.self.replace(new RegExp("^["+$.chars+"]*"),"")
1223
$StringDict.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)
1226
1227
var _t=_b_.dict()
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('maketrans only argument must be a dict')
1238
}
1239
var items = _b_.list(_b_.dict.$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("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("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("maketrans arguments must be strings")
1260
}else if($.x.length!==$.y.length){
1261
throw _b_.TypeError("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('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
}
1273
}
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
}
1285
$StringDict.partition = function() {
1286
var $=$B.args('partition',2,{self:null,sep:null},['self','sep'],
1287
arguments,{},null,null)
1288
if($.sep==''){throw _b_.ValueError('empty separator')}
1289
check_str($.sep)
1290
var i=$.self.indexOf($.sep)
1291
if (i== -1) return _b_.tuple([$.self, '', ''])
1292
return _b_.tuple([$.self.substring(0,i), $.sep,
1293
$.self.substring(i+$.sep.length)])
1300
var re = new RegExp('\\'+specials.charAt(i),'g')
1301
str = str.replace(re, "\\"+specials.charAt(i))
1302
}
1303
return str
1304
}
1305
1306
$StringDict.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
1316
// Validate instance type of 'count'
1317
if (!isinstance(count,[_b_.int,_b_.float])) {
1318
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1319
"' object cannot be interpreted as an integer");
1320
} else if (isinstance(count, _b_.float)) {
1321
throw _b_.TypeError("integer argument expected, got float");
1322
}
1323
if(count==0){return self}
1324
if(count.__class__==$B.LongInt.$dict){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{
1334
var elts = $StringDict.split(self,old,count)
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
}
1345
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;
1356
}
1357
1358
$StringDict.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
1361
// start and end are interpreted as in slice notation. Return -1 on failure.
1371
if($.sub.length==0){
1372
if($.start>$.self.length){return -1}
1373
else{return $.self.length}
1374
}
1375
var sublen = $.sub.length
1376
1377
for(var i=$.end-sublen;i>=$.start;i--){
1378
if($.self.substr(i, sublen)==$.sub){return i}
1379
}
1380
return -1
1381
}
1382
1383
$StringDict.rindex = function(){
1384
// Like rfind() but raises ValueError when the substring sub is not found
1386
if(res==-1){throw _b_.ValueError("substring not found")}
1387
return res
1388
}
1389
1390
$StringDict.rjust = function(self) {
1392
{self:null, width:null, fillchar:null},
1393
['self', 'width', 'fillchar'],
1394
arguments,{fillchar:' '},null,null)
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)
1407
var items = $StringDict.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
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),
1418
sep=$.sep,maxsplit=$.maxsplit,self=$.self
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),
1425
// Reverse the list, then each string inside the list
1426
rev_res.reverse()
1427
for(var i=0;i<rev_res.length;i++){
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.replace(/\s+$/,'')}
1437
return $.self.replace(new RegExp("["+$.chars+"]*$"),"")
1442
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1443
['self','sep','maxsplit'],arguments,
1444
{sep:_b_.None, maxsplit:-1},null,null)
1445
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1446
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1449
var res = []
1450
var pos = 0
1451
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1453
var name = ''
1454
while(1){
1455
if(self.charAt(pos).search(/\s/)===-1){
1456
if(name===''){name=self.charAt(pos)}
1457
else{name+=self.charAt(pos)}
1458
}else{
1459
if(name!==''){
1460
res.push(name)
1461
if(maxsplit!==-1&&res.length===maxsplit+1){
1462
res.pop()
1463
res.push(name+self.substr(pos))
1464
return res
1465
}
1466
name=''
1467
}
1468
}
1469
pos++
1470
if(pos>self.length-1){
1471
if(name){res.push(name)}
1472
break
1473
}
1474
}
1475
return res
1476
}else{
1477
var res = [],s='',pos=0,seplen=sep.length
1478
if(maxsplit==0){return [self]}
1479
while(pos<self.length){
1480
if(self.substr(pos,seplen)==sep){
1481
res.push(s)
1482
pos += seplen
1483
if(maxsplit>-1 && res.length>=maxsplit){
1484
res.push(self.substr(pos))
1485
return res
1486
}
1487
s= ''
1488
}else{
1489
s += self.charAt(pos)
1490
pos++
1498
$StringDict.splitlines = function(self){
1499
var $=$B.args('splitlines',2,{self:null,keepends:null},
1500
['self','keepends'],arguments,{keepends:false},null,null)
1501
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1502
throw _b_.TypeError('integer argument expected, got '+
1503
$B.get_class($.keepends).__name)
1504
}
1505
var keepends = _b_.int($.keepends)
1506
// Remove trailing line breaks
1507
if(keepends){
1508
var res = [],start=pos,pos=0,x,self=$.self
1509
while(pos<self.length){
1510
if(self.substr(pos,2)=='\r\n'){
1511
res.push(self.substring(start,pos+2))
1512
start = pos+2
1513
pos = start
1514
}else if(self.charAt(pos)=='\r' || self.charAt(pos)=='\n'){
1515
res.push(self.substring(start,pos+1))
1516
start = pos+1
1517
pos = start
1518
}else{pos++}
1519
}
1520
var rest = self.substr(start)
1521
if(rest){res.push(rest)}
1522
return res
1523
}else{
1524
var self = $.self.replace(/[\r\n]$/,'')
1525
return self.split(/\n|\r\n|\r/)
1526
}
1527
}
1530
// Return True if string starts with the prefix, otherwise return False.
1531
// prefix can also be a tuple of prefixes to look for. With optional
1532
// start, test string beginning at that position. With optional end,
1533
// stop comparing string at that position.
1535
{self:null, prefix:null, start:null, end:null},
1536
['self', 'prefix', 'start', 'end'],
1539
normalize_start_end($)
1540
1541
var prefixes = $.prefix
1542
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1543
1544
var s = $.self.substring($.start,$.end)
1545
for(var i=0, _len_i = prefixes.length; i < _len_i;i++){
1546
prefix = prefixes[i]
1547
if(!_b_.isinstance(prefix, str)){throw _b_.TypeError(
1548
"endswith first arg must be str or a tuple of str, not int")}
1549
if(s.substr(0,prefix.length)==prefix) return true
1555
$StringDict.strip = function(){
1556
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1557
arguments,{chars:_b_.None},null,null)
1558
return $StringDict.rstrip($StringDict.lstrip($.self,$.chars),$.chars)
1564
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1566
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1567
})
1568
}
1569
1570
$StringDict.title = function(self) {
1571
var $=$B.args('title',1,{self:null},['self'],arguments,{},null,null)
1572
1573
// Transform letters after a non-cased character to uppercase
1574
var res = '',previous=false
1575
1576
function is_cased(c){
1577
return c.toLowerCase() != c.toUpperCase()
1578
}
1579
1580
for(var i=0;i<$.self.length;i++){
1581
var char = $.self.charAt(i), cased = is_cased(char)
1582
if(!previous && cased){
1583
res += char.toUpperCase()
1584
}else if(previous){res+=char.toLowerCase()}
1585
else{res+=char}
1586
previous = cased
1587
}
1588
return res
1603
$StringDict.upper = function(){
1604
var $=$B.args('lower',1,{self:null},['self'],arguments,{},null,null)
1605
return $.self.toUpperCase()
1606
}
1609
var $=$B.args('zfill',2,{self:null,width:null},
1610
['self','width'],arguments,{},null,null)
1611
if ($.width <= self.length) {return self}
1612
switch(self.charAt(0)){
1613
case '+':
1614
case '-':
1615
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1616
default:
1617
return '0'.repeat(width - self.length)+self
1618
}
1624
case 'string':
1625
return arg
1626
case 'number':
1627
if(isFinite(arg)){return arg.toString()}
1634
// class or its subclasses, but the attribute __str__ of the
1635
// class metaclass (usually "type") or its subclasses (usually
1636
// "object")
1637
// The metaclass is the attribute __class__ of the class dictionary
1638
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1643
var f = getattr(arg,'__str__')
1644
// XXX fix : if not better than object.__str__, try __repr__
1645
return f()
1646
}
1647
catch(err){
1653
if($B.debug>1){console.log(err)}
1654
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1656
}
1657
}
1658
}
1659
str.__class__ = $B.$factory
1660
str.$dict = $StringDict
1661
$StringDict.$factory = str
1662
$StringDict.__new__ = function(cls){
1663
if(cls===undefined){
1664
throw _b_.TypeError('str.__new__(): not enough arguments')
1665
}
1666
return {__class__:cls.$dict}
1667
}
1668
1671
// dictionary and factory for subclasses of string
1672
var $StringSubclassDict = {
1673
__class__:$B.$type,
1674
__name__:'str'
1675
}
1676
1677
// the methods in subclass apply the methods in $StringDict to the
1678
// result of instance.valueOf(), which is a Javascript string
1679
for(var $attr in $StringDict){
1680
if(typeof $StringDict[$attr]=='function'){
1681
$StringSubclassDict[$attr]=(function(attr){
1682
return function(){
1688
}
1689
}
1690
return $StringDict[attr].apply(null,args)
1691
}
1692
})($attr)
1693
}
1694
}
1695
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1696
1697
// factory for str subclasses
1698
$B.$StringSubclassFactory = {
1699
__class__:$B.$factory,
1700
$dict:$StringSubclassDict
1701
}
1702
1703
_b_.str = str
1704
1705
// Function to parse the 2nd argument of format()
1706
$B.parse_format_spec = function(spec){
1716
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1717
// If the second char is also an alignment specifier, the
1718
// first char is the fill value
1719
this.fill = spec.charAt(0)
1720
this.align = spec.charAt(1)
1721
pos = 2
1722
}else{
1723
// The first character defines alignment : fill defaults to ' '
1724
this.align=aligns[align_pos];
1725
this.fill=' ';
1726
pos++
1727
}
1728
}else{
1729
align_pos = aligns.indexOf(spec.charAt(1))
1730
if(spec.charAt(1) && align_pos!=-1){
1731
// The second character defines alignment : fill is the first one
1732
this.align=aligns[align_pos]
1733
this.fill=spec.charAt(0)
1734
pos = 2
1735
}
1736
}
1737
var car = spec.charAt(pos)
1738
if(car=='+'||car=='-'||car==' '){
1739
this.sign=car;
1740
pos++;
1741
car=spec.charAt(pos);
1744
if(car=='0'){
1745
// sign-aware : equivalent to fill=0 and align=='='
1746
this.fill='0'
1747
this.align = '='
1748
pos++;car=spec.charAt(pos)
1749
}
1751
if(this.width===undefined){this.width=car}
1752
else{this.width+=car}
1753
pos++;car=spec.charAt(pos)
1755
if(this.width!==undefined){this.width=parseInt(this.width)}
1756
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1757
if(car=='.'){
1758
if(digits.indexOf(spec.charAt(pos+1))==-1){
1759
throw _b_.ValueError("Missing precision in format spec")
1760
}
1761
this.precision = spec.charAt(pos+1)
1762
pos+=2;car=spec.charAt(pos)
1763
while(car && digits.indexOf(car)>-1){
1764
this.precision+=car;pos++;car=spec.charAt(pos)
1765
}
1766
this.precision = parseInt(this.precision)
1767
}
1768
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1769
if(pos!==spec.length){
1771
throw _b_.ValueError("Invalid format specifier")
1772
}
1773
}
1774
this.toString = function(){
1775
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1776
(this.align||'')+
1777
(this.sign||'')+
1778
(this.alternate ? '#' : '')+
1779
(this.sign_aware ? '0' : '')+
1780
(this.width || '')+
1781
(this.comma ? ',' : '')+
1782
(this.precision ? '.'+this.precision : '')+
1783
(this.type || '')
1784
}
1785
}
1786
1787
$B.format_width = function(s, fmt){
1788
if(fmt.width && s.length<fmt.width){
1789
var fill=fmt.fill || ' ', align = fmt.align || '<',
1790
missing = fmt.width-s.length
1791
switch(align){
1792
case '<':
1793
return s+fill.repeat(missing)
1794
case '>':
1795
return fill.repeat(missing)+s
1796
case '=':
1797
if('+-'.indexOf(s.charAt(0))>-1){
1798
return s.charAt(0)+fill.repeat(missing)+s.substr(1)
1799
}else{
1800
return fill.repeat(missing)+s
1801
}
1802
case '^':
1803
left = parseInt(missing/2)