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
Feb 9, 2016
Jan 14, 2015
Jan 14, 2015
Feb 9, 2016
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Jan 14, 2015
Feb 9, 2016
Oct 8, 2016
Dec 3, 2015
Dec 3, 2015
Jan 6, 2016
Jan 1, 2015
Jan 1, 2015
Jan 30, 2016
Oct 12, 2016
Newer
100644
1780 lines (1613 sloc)
58.2 KB
5
if (!String.prototype.trim) {
6
// Polyfill for older browsers
7
// The code does not use a regex to make it a bit faster.
8
// Implementation taken from a comment by Timo on the blog:
9
// http://blog.stevenlevithan.com/archives/faster-trim-javascript
10
String.prototype.trim = function () {
11
var c;
12
for (var i = 0; i < this.length; i++) {
13
c = this.charCodeAt(i);
14
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
15
continue; else break;
16
}
17
for (var j = this.length - 1; j >= i; j--) {
18
c = this.charCodeAt(j);
19
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
20
continue; else break;
21
}
22
return this.substring(i, j + 1);
23
}
24
}
25
if (!String.prototype.trimLeft) {
26
// Convenience method for browsers which do not have a native trimLeft
27
// (which is a nonstandard extension in Firefox and Chrome)
28
String.prototype.trimLeft = function () {
29
var c;
30
for (var i = 0; i < this.length; i++) {
31
c = this.charCodeAt(i);
32
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
33
continue; else break;
34
}
35
return this.substring(i);
36
};
37
}
38
if (!String.prototype.trimRight) {
39
String.prototype.trimRight = function () {
40
// Convenience method for browsers which do not have a native trimRight
41
// (which is a nonstandard extension in Firefox and Chrome)
42
var c;
43
for (var j = this.length - 1; j >= 0; j--) {
44
c = this.charCodeAt(j);
45
if (c == 32 || c == 10 || c == 13 || c == 9 || c == 12 || c == 11 || c == 160 || c == 5760 || c == 6158 || c == 8192 || c == 8193 || c == 8194 || c == 8195 || c == 8196 || c == 8197 || c == 8198 || c == 8199 || c == 8200 || c == 8201 || c == 8202 || c == 8232 || c == 8233 || c == 8239 || c == 8287 || c == 12288 || c == 65279)
46
continue; else break;
47
}
48
return this.substring(0, j + 1);
49
};
50
}
51
60
function normalize_start_end($){
61
if($.start===null||$.start===_b_.None){$.start = 0}
62
else if($.start<0){$.start += $.self.length; $.start=Math.max(0, $.start)}
63
if($.end===null||$.end===_b_.None){$.end = $.self.length}
64
else if($.end<0){$.end += $.self.length; $.end=Math.max(0, $.end)}
65
66
if(!isinstance($.start,_b_.int)||!isinstance($.end,_b_.int)){
67
throw _b_.TypeError(
68
"slice indices must be integers or None or have an __index__ method")}
69
70
}
71
72
function reverse(s){
73
// Reverse a string
74
return s.split('').reverse().join('')
75
}
76
77
function check_str(obj){
78
if(!_b_.isinstance(obj,str)){throw _b_.TypeError("can't convert '"+
79
$B.get_class(obj).__name__+"' object to str implicitely")}
82
$StringDict.__add__ = function(self,other){
83
if(!(typeof other==="string")){
84
try{return getattr(other,'__radd__')(self)}
85
catch(err){throw _b_.TypeError(
86
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
87
}
88
return self+other
89
}
90
91
$StringDict.__contains__ = function(self,item){
92
if(!(typeof item==="string")){throw _b_.TypeError(
93
"'in <string>' requires string as left operand, not "+item.__class__)}
94
var nbcar = item.length
95
if(nbcar==0) return true // a string contains the empty string
96
if(self.length==0) return nbcar==0
98
if(self.substr(i,nbcar)==item) return true
99
}
100
return false
101
}
102
103
$StringDict.__delitem__ = function(){
104
throw _b_.TypeError("'str' object doesn't support item deletion")
105
}
106
107
// __dir__must be assigned explicitely because attribute resolution for builtin
108
// classes doesn't use __mro__
109
$StringDict.__dir__ = $ObjectDict.__dir__
110
111
$StringDict.__eq__ = function(self,other){
112
if(other===undefined){ // compare object "self" to class "str"
113
return self===str
114
}
115
if (_b_.isinstance(other, _b_.str)) {
116
return other.valueOf() == self.valueOf()
117
}
121
function preformat(self, fmt){
122
if(fmt.empty){return _b_.str(self)}
123
if(fmt.type && fmt.type!='s'){
124
throw _b_.ValueError("Unknown format code '"+fmt.type+
125
"' for object of type 'str'")
126
}
127
return self
128
}
129
130
$StringDict.__format__ = function(self, format_spec) {
131
var fmt = new $B.parse_format_spec(format_spec)
132
// For strings, alignment default to left
133
fmt.align = fmt.align || '<'
134
return $B.format_width(preformat(self, fmt), fmt)
135
}
136
137
$StringDict.__getitem__ = function(self,arg){
138
if(isinstance(arg,_b_.int)){
139
var pos = arg
140
if(arg<0) pos+=self.length
141
if(pos>=0 && pos<self.length) return self.charAt(pos)
142
throw _b_.IndexError('string index out of range')
143
}
144
if(isinstance(arg,slice)) {
145
var s=_b_.slice.$dict.$conv_for_seq(arg, self.length),
146
start=s.start, stop=s.stop, step=s.step
147
var res = '',i=null
148
if(step>0){
149
if(stop<=start) return ''
150
for(var i=start;i<stop;i+=step) res += self.charAt(i)
151
} else {
152
if(stop>=start) return ''
154
}
155
return res
156
}
157
if(isinstance(arg,bool)) return self.__getitem__(_b_.int(arg))
162
if (self === undefined) {
163
return $StringDict.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
164
}
165
166
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
167
// this implementation for strings maybe good enough for us..
168
169
var hash=1;
171
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
172
}
173
174
return hash
175
}
176
177
$StringDict.__init__ = function(self,arg){
178
self.valueOf = function(){return arg}
179
self.toString = function(){return arg}
181
}
182
183
var $str_iterator = $B.$iterator_class('str_iterator')
184
$StringDict.__iter__ = function(self){
185
var items = self.split('') // list of all characters in string
186
return $B.$iterator(items,$str_iterator)
187
}
188
189
$StringDict.__len__ = function(self){return self.length}
190
193
var kwarg_key = new RegExp('([^\\)]*)\\)')
194
195
var NotANumber = function() {
196
this.name = 'NotANumber'
197
}
198
199
var number_check=function(s) {
200
if(!isinstance(s,[_b_.int,_b_.float])){
201
throw new NotANumber()
202
}
203
}
204
205
var get_char_array = function(size, char) {
206
if (size <= 0)
207
return ''
208
return new Array(size + 1).join(char)
209
}
210
211
var format_padding = function(s, flags, minus_one) {
212
var padding = flags.padding
213
if (!padding) { // undefined
214
return s
215
}
216
s = s.toString()
217
padding = parseInt(padding, 10)
218
if (minus_one) { // numeric formatting where sign goes in front of padding
219
padding -= 1
220
}
221
if (!flags.left) {
222
return get_char_array(padding - s.length, flags.pad_char) + s
223
} else {
224
// left adjusted
225
return s + get_char_array(padding - s.length, flags.pad_char)
226
}
227
}
228
229
var format_int_precision = function(val, flags) {
230
var precision = flags.precision
231
if (!precision) {
232
return val.toString()
233
}
234
precision = parseInt(precision, 10)
235
var s
236
if (val.__class__ === $B.LongInt.$dict) {
237
s=$B.LongInt.$dict.to_base(val, 10)
238
} else {
239
s=val.toString()
240
}
241
if (s[0] === '-') {
242
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
243
}
244
return get_char_array(precision - s.length, '0') + s
245
}
246
247
var format_float_precision = function(val, upper, flags, modifier) {
248
var precision = flags.precision
249
// val is a float
250
if (isFinite(val)) {
251
val = modifier(val, precision, flags, upper)
252
return val
253
}
254
if (val === Infinity) {
255
val = 'inf'
256
} else if (val === -Infinity) {
257
val = '-inf'
258
} else {
259
val = 'nan'
260
}
261
if (upper) {
262
return val.toUpperCase()
263
}
264
return val
266
}
267
268
var format_sign = function(val, flags) {
269
if (flags.sign) {
270
if (val >= 0) {
271
return "+"
273
} else if (flags.space) {
274
if (val >= 0) {
275
return " "
276
}
277
}
278
return ""
279
}
281
var str_format = function(val, flags) {
282
// string format supports left and right padding
283
flags.pad_char = " " // even if 0 padding is defined, don't use it
284
return format_padding(str(val), flags)
285
}
289
if (val.__class__ === $B.LongInt.$dict) {
290
val = $B.LongInt.$dict.to_base(val, 10)
291
} else {
292
val = parseInt(val)
293
}
294
295
var s = format_int_precision(val, flags)
296
if (flags.pad_char === '0') {
297
if (val < 0) {
298
s = s.substring(1)
299
return '-' + format_padding(s, flags, true)
300
}
301
var sign = format_sign(val, flags)
302
if (sign !== '') {
303
return sign + format_padding(s, flags, true)
304
}
305
}
306
307
return format_padding(format_sign(val, flags) + s, flags)
308
}
310
var repr_format = function(val, flags) {
311
flags.pad_char = " " // even if 0 padding is defined, don't use it
312
return format_padding(repr(val), flags)
313
}
315
var ascii_format = function(val, flags) {
316
flags.pad_char = " " // even if 0 padding is defined, don't use it
317
return format_padding(ascii(val), flags)
318
}
320
// converts to val to float and sets precision if missing
321
var _float_helper = function(val, flags) {
322
number_check(val)
323
if (!flags.precision) {
324
if (!flags.decimal_point) {
325
flags.precision = 6
326
} else {
327
flags.precision = 0
328
}
329
} else {
330
flags.precision = parseInt(flags.precision, 10)
331
validate_precision(flags.precision)
332
}
333
return parseFloat(val)
334
}
336
// used to capture and remove trailing zeroes
337
var trailing_zeros = /(.*?)(0+)([eE].*)/
338
var leading_zeros = /\.(0*)/
339
var trailing_dot = /\.$/
341
var validate_precision = function(precision) {
342
// force precision to limits of javascript
344
}
345
346
// gG
347
var floating_point_format = function(val, upper, flags) {
348
val = _float_helper(val, flags)
349
var v = val.toString()
350
var v_len = v.length
351
var dot_idx = v.indexOf('.')
352
if (dot_idx < 0) {
353
dot_idx = v_len
354
}
355
if (val < 1 && val > -1) {
356
var zeros = leading_zeros.exec(v)
357
var numzeros
358
if (zeros) {
359
numzeros = zeros[1].length
360
} else {
361
numzeros = 0
362
}
363
if (numzeros >= 4) {
364
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
365
if (!flags.alternate) {
366
var trl = trailing_zeros.exec(val)
367
if (trl) {
368
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
374
}
375
return format_padding(val, flags)
376
}
377
flags.precision += numzeros
378
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
379
function(val, precision) {
380
val = val.toFixed(min(precision, v_len - dot_idx) + numzeros)
381
}), flags)
382
}
383
384
if (dot_idx > flags.precision) {
385
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
386
if (!flags.alternate) {
387
var trl = trailing_zeros.exec(val)
388
if (trl) {
389
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
390
}
391
} else {
392
if (flags.precision <= 1) {
393
val = val[0] + '.' + val.substring(1)
394
}
395
}
396
return format_padding(val, flags)
397
}
398
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
399
function(val, precision) {
400
if (!flags.decimal_point) {
401
precision = min(v_len - 1, 6)
402
} else if (precision > v_len) {
403
if (!flags.alternate) {
404
precision = v_len
406
}
407
if (precision < dot_idx) {
408
precision = dot_idx
409
}
410
return val.toFixed(precision - dot_idx)
411
}), flags)
412
}
414
var _floating_g_exp_helper = function(val, precision, flags, upper) {
415
if (precision) {
416
--precision
417
}
418
val = val.toExponential(precision)
419
// pad exponent to two digits
420
var e_idx = val.lastIndexOf('e')
421
if (e_idx > val.length - 4) {
422
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
423
}
424
if (upper) {
425
return val.toUpperCase()
426
}
427
return val
428
}
429
430
// fF
431
var floating_point_decimal_format = function(val, upper, flags) {
432
val = _float_helper(val, flags)
433
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
434
function(val, precision, flags) {
435
val = val.toFixed(precision)
436
if (precision === 0 && flags.alternate) {
437
val += '.'
438
}
439
return val
440
}), flags)
441
}
442
443
var _floating_exp_helper = function(val, precision, flags, upper) {
444
val = val.toExponential(precision)
445
// pad exponent to two digits
446
var e_idx = val.lastIndexOf('e')
447
if (e_idx > val.length - 4) {
448
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
449
}
450
if (upper) {
451
return val.toUpperCase()
452
}
453
return val
454
}
455
456
// eE
457
var floating_point_exponential_format = function(val, upper, flags) {
458
val = _float_helper(val, flags)
459
460
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
461
}
462
463
var signed_hex_format = function(val, upper, flags) {
466
467
if (val.__class__ === $B.LongInt.$dict) {
468
ret=$B.LongInt.$dict.to_base(val, 16)
469
} else {
470
ret = parseInt(val)
471
ret = ret.toString(16)
472
}
473
ret = format_int_precision(ret, flags)
474
if (upper) {
475
ret = ret.toUpperCase()
476
}
477
if (flags.pad_char === '0') {
478
if (val < 0) {
479
ret = ret.substring(1)
480
ret = '-' + format_padding(ret, flags, true)
481
}
482
var sign = format_sign(val, flags)
483
if (sign !== '') {
484
ret = sign + format_padding(ret, flags, true)
486
}
487
488
if (flags.alternate) {
489
if (ret.charAt(0) === '-') {
490
if (upper) {
491
ret = "-0X" + ret.slice(1)
492
} else {
493
ret = "-0x" + ret.slice(1)
494
}
495
} else {
496
if (upper) {
497
ret = "0X" + ret
498
} else {
499
ret = "0x" + ret
500
}
501
}
502
}
503
return format_padding(format_sign(val, flags) + ret, flags)
504
}
508
var ret
509
510
if (val.__class__ === $B.LongInt.$dict) {
511
ret = $B.LongInt.$dict.to_base(8)
512
} else {
513
ret = parseInt(val)
514
ret = ret.toString(8)
515
}
516
519
if (flags.pad_char === '0') {
520
if (val < 0) {
521
ret = ret.substring(1)
522
ret = '-' + format_padding(ret, flags, true)
523
}
524
var sign = format_sign(val, flags)
525
if (sign !== '') {
526
ret = sign + format_padding(ret, flags, true)
527
}
529
530
if (flags.alternate) {
531
if (ret.charAt(0) === '-') {
532
ret = "-0o" + ret.slice(1)
533
} else {
534
ret = "0o" + ret
535
}
537
return format_padding(ret, flags)
538
}
539
540
var single_char_format = function(val, flags) {
541
if(isinstance(val,str) && val.length==1) return val
542
try {
543
val = _b_.int(val) // yes, floats are valid (they are cast to int)
544
} catch (err) {
545
throw _b_.TypeError('%c requires int or char')
546
}
547
return format_padding(chr(val), flags)
548
}
549
550
var num_flag = function(c, flags) {
551
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
552
flags.pad_char = '0'
553
return
554
}
555
if (!flags.decimal_point) {
556
flags.padding = (flags.padding || "") + c
557
} else {
558
flags.precision = (flags.precision || "") + c
559
}
560
}
561
562
var decimal_point_flag = function(val, flags) {
563
if (flags.decimal_point) {
564
// can only have one decimal point
565
throw new UnsupportedChar()
566
}
567
flags.decimal_point = true
568
}
569
570
var neg_flag = function(val, flags) {
571
flags.pad_char = ' ' // overrides '0' flag
572
flags.left = true
573
}
574
575
var space_flag = function(val, flags) {
576
flags.space = true
577
}
578
579
var sign_flag = function(val, flags) {
580
flags.sign = true
581
}
582
583
var alternate_flag = function(val, flags) {
584
flags.alternate = true
585
}
586
588
's': str_format,
589
'd': num_format,
590
'i': num_format,
591
'u': num_format,
592
'o': octal_format,
593
'r': repr_format,
594
'a': ascii_format,
595
'g': function(val, flags) {return floating_point_format(val, false, flags)},
596
'G': function(val, flags) {return floating_point_format(val, true, flags)},
597
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
598
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
599
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
600
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
601
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
602
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
603
'c': single_char_format,
604
'0': function(val, flags) {return num_flag('0', flags)},
605
'1': function(val, flags) {return num_flag('1', flags)},
606
'2': function(val, flags) {return num_flag('2', flags)},
607
'3': function(val, flags) {return num_flag('3', flags)},
608
'4': function(val, flags) {return num_flag('4', flags)},
609
'5': function(val, flags) {return num_flag('5', flags)},
610
'6': function(val, flags) {return num_flag('6', flags)},
611
'7': function(val, flags) {return num_flag('7', flags)},
612
'8': function(val, flags) {return num_flag('8', flags)},
613
'9': function(val, flags) {return num_flag('9', flags)},
614
'-': neg_flag,
615
' ': space_flag,
616
'+': sign_flag,
617
'.': decimal_point_flag,
618
'#': alternate_flag
619
}
620
621
// exception thrown when an unsupported char is encountered in legacy format
622
var UnsupportedChar = function() {
623
this.name = "UnsupportedChar"
624
}
625
628
var length = self.length,
629
pos = 0 |0,
630
argpos = null,
631
getitem
632
if (_b_.isinstance(args, _b_.tuple)) {
640
++pos
641
var rslt = kwarg_key.exec(s.substring(newpos))
642
if (!rslt) {
643
throw _b_.ValueError("incomplete format key")
644
}
645
var key = rslt[1]
646
newpos += rslt[0].length
647
try {
649
} catch(err) {
650
if (err.name === "KeyError") {
651
throw err
652
}
653
throw _b_.TypeError("format requires a mapping")
654
}
667
self = args[argpos++]
668
if(self===undefined){
669
throw _b_.TypeError("not enough arguments for format string")
675
// todo: get flags, type
676
// todo: string value based on flags, type, value
677
var flags = {'pad_char': ' '}
678
do {
685
if (ret !== undefined) {
686
return ret
687
}
688
++newpos
689
}
690
} catch (err) {
691
if (err.name === "UnsupportedChar") {
692
invalid_char = s[newpos]
693
if (invalid_char === undefined) {
694
throw _b_.ValueError("incomplete format")
695
}
696
throw _b_.ValueError("unsupported format character '" + invalid_char +
697
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
698
} else if (err.name === "NotANumber") {
699
var try_char = s[newpos]
706
}
707
} else {
708
cls = cls.__name__
709
}
710
throw _b_.TypeError("%" + try_char + " format: a number is required, not " + cls)
711
} else {
712
throw err
713
}
736
}
737
}
738
} else {
739
// % at end of string
740
throw _b_.ValueError("incomplete format")
741
}
742
pos = newpos + 1
743
} while (pos < length)
744
745
if(argpos!==null){
746
if(args.length>argpos){
747
throw _b_.TypeError('not enough arguments for format string')
748
}else if(args.length<argpos){
749
throw _b_.TypeError('not all arguments converted during string formatting')
750
}
751
}else if(nbph==0){
752
throw _b_.TypeError('not all arguments converted during string formatting')
753
}
760
var $=$B.args('__mul__',2,{self:null,other:null},['self','other'],
761
arguments,{},null,null)
767
return $res
768
}
769
770
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
771
772
$StringDict.__repr__ = function(self){
773
var res = self.replace(/\n/g,'\\\\n')
774
// escape the escape char
775
res = res.replace(/\\/g, '\\\\')
776
if(res.search('"')==-1 && res.search("'")==-1){
777
return "'"+res+"'"
783
return res
784
}
785
786
$StringDict.__setitem__ = function(self,attr,value){
787
throw _b_.TypeError("'str' object does not support item assignment")
788
}
789
$StringDict.__str__ = function(self){
790
if(self===undefined) return "<class 'str'>"
791
return self.toString()
792
}
793
$StringDict.toString = function(){return 'string!'}
794
795
// generate comparison methods
796
var $comp_func = function(self,other){
797
if(typeof other !=="string"){throw _b_.TypeError(
798
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
799
return self > other
800
}
801
$comp_func += '' // source code
802
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
803
for(var $op in $comps){
804
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
805
}
806
807
// add "reflected" methods
808
$B.make_rmethods($StringDict)
809
810
// unsupported operations
811
var $notimplemented = function(self,other){
812
throw NotImplementedError("OPERATOR not implemented for class str")
813
}
814
815
$StringDict.title = unicode.title;
816
$StringDict.capitalize = unicode.capitalize;
817
$StringDict.casefold = unicode.casefold;
818
$StringDict.islower = unicode.islower;
819
$StringDict.isupper = unicode.isupper;
820
$StringDict.istitle = unicode.istitle;
821
$StringDict.isspace = unicode.isspace;
822
$StringDict.isalpha = unicode.isalpha;
823
$StringDict.isalnum = unicode.isalnum;
824
$StringDict.isdecimal = unicode.isdecimal;
825
$StringDict.isdigit = unicode.isdigit;
826
$StringDict.isnumeric = unicode.isnumeric;
827
$StringDict.isidentifier = unicode.isidentifier;
828
$StringDict.isprintable = unicode.isprintable;
829
$StringDict.lower = unicode.lower;
830
$StringDict.swapcase = unicode.swapcase;
831
$StringDict.upper = unicode.upper;
834
var $=$B.args("center",3,
835
{self:null, width:null, fillchar:null},
836
['self', 'width', 'fillchar'],
837
arguments,{fillchar:' '},null,null)
838
839
if($.width<=self.length) return self
848
$StringDict.count = function(){
849
var $ = $B.args('count', 4, {self:null, sub:null, start:null, stop:null},
854
var substr = $.self
855
if($.start!==null){
856
var _slice
857
if($.stop!==null){_slice = _b_.slice($.start, $.stop)}
858
else{_slice = _b_.slice($.start,$.self.length)}
859
substr = $StringDict.__getitem__.apply(null, [$.self].concat(_slice))
860
}else{
861
if($.self.length+$.sub.length==0){return 1} // ''.count('') = 1
862
}
863
if($.sub.length==0){
864
if($.start==$.self.length){return 1} // 'aaa'.count('',3) = 1
865
else if(substr.length==0){return 0} // 'aaa'.count('',4) = 0
866
return substr.length+1
867
}
868
var n=0, pos=0
869
while(pos<substr.length){
870
pos=substr.indexOf($.sub,pos)
872
}
873
return n
874
}
875
876
$StringDict.encode = function(self, encoding) {
877
if (encoding === undefined) encoding='utf-8'
878
if(encoding=='rot13' || encoding=='rot_13'){
879
// Special case : returns a string
880
var res = ''
881
for(var i=0, _len = self.length; i<_len ; i++){
882
var char = self.charAt(i)
883
if(('a'<=char && char<='m') || ('A'<=char && char<='M')){
884
res += String.fromCharCode(String.charCodeAt(char)+13)
885
}else if(('m'<char && char<='z') || ('M'<char && char<='Z')){
886
res += String.fromCharCode(String.charCodeAt(char)-13)
887
}else{res += char}
888
}
889
return res
890
}
895
// Return True if the string ends with the specified suffix, otherwise
896
// return False. suffix can also be a tuple of suffixes to look for.
897
// With optional start, test beginning at that position. With optional
898
// end, stop comparing at that position.
900
{self:null, suffix:null, start:null, end:null},
901
['self', 'suffix', 'start', 'end'],
902
arguments,{start:0, end:null},null,null)
903
904
normalize_start_end($)
905
906
var suffixes = $.suffix
912
if(!_b_.isinstance(suffix, str)){throw _b_.TypeError(
913
"endswith first arg must be str or a tuple of str, not int")}
914
if(suffix.length<=s.length &&
915
s.substr(s.length-suffix.length)==suffix) return true
916
}
917
return false
918
}
919
920
$StringDict.expandtabs = function(self, tabsize) {
921
var $ = $B.args('expandtabs', 2, {self:null, tabsize:null},
922
['self', 'tabsize'], arguments, {tabsize:8}, null, null)
923
var s=$B.$GetInt($.tabsize), col=0,pos=0,res=''
924
if(s==1){return self.replace(/\t/g,' ')}
925
while(pos<self.length){
926
var car = self.charAt(pos)
927
switch(car){
928
case '\t':
929
while(col%s > 0){res += ' ';col++}
930
break
931
case '\r':
932
case '\n':
933
res += car
934
col = 0
935
break
936
default:
937
res += car
938
col++
939
break
940
}
941
pos++
942
}
943
944
return res
948
// Return the lowest index in the string where substring sub is found,
949
// such that sub is contained in the slice s[start:end]. Optional
950
// arguments start and end are interpreted as in slice notation.
951
// Return -1 if sub is not found.
960
throw _b_.TypeError(
961
"slice indices must be integers or None or have an __index__ method")}
962
var s = $.self.substring($.start,$.end)
963
964
if($.sub.length==0 && $.start==$.self.length){return $.self.length}
965
if(s.length+$.sub.length==0){return -1}
966
967
var last_search = s.length-$.sub.length
968
for(var i=0;i<=last_search;i++){
969
if(s.substr(i, $.sub.length)==$.sub){return $.start+i}
978
// Parse a "format string", as described in the Python documentation
979
// Return a format object. For the format string
980
// a.x[z]!r:...
981
// the object has attributes :
982
// - name : "a"
983
// - name_ext : [".x", "[z]"]
984
// - conv : r
985
// - spec : rest of string after :
987
var elts = fmt_string.split(':'), name, conv, spec, name_ext=[]
988
if(elts.length==1){
989
// No : in the string : it only contains a name
990
name = fmt_string
991
}else{
992
// name is before the first ":"
993
// spec (the format specification) is after
994
name = elts[0]
995
spec = elts.splice(1).join(':')
996
}
997
998
var elts = name.split('!')
999
if(elts.length>1){
1000
name=elts[0]
1001
conv=elts[1] // conversion flag
1002
if(conv.length!==1 || 'ras'.search(conv)==-1){
1003
throw _b_.ValueError('wrong conversion flag '+conv)
1004
}
1005
}
1007
if(name!==undefined){
1008
// "name' may be a subscription or attribute
1009
// Put these "extensions" in the list "name_ext"
1010
function name_repl(match){
1011
name_ext.push(match)
1012
return ''
1013
}
1014
var name_ext_re = /\.[_a-zA-Z][_a-zA-Z0-9]*|\[[_a-zA-Z][_a-zA-Z0-9]*\]|\[[0-9]+\]/g
1015
name = name.replace(name_ext_re, name_repl)
1016
}
1025
arguments, {}, 'args', 'kw')
1026
1027
// Parse self to detect formatting instructions
1028
// Create a list "parts" made of sections of the string :
1029
// - elements of even rank are literal text
1030
// - elements of odd rank are "format objects", built from the
1031
// format strings in self (of the form {...})
1032
var pos=0,
1033
_len=self.length,
1034
car,
1035
text='',
1036
parts=[],
1037
rank=0
1038
1039
while(pos<_len){
1040
car = self.charAt(pos)
1041
if(car=='{' && self.charAt(pos+1)=='{'){
1042
// replace {{ by literal {
1043
text += '{'
1044
pos+=2
1045
}else if(car=='}' && self.charAt(pos+1)=='}'){
1046
// replace }} by literal }
1047
text += '}'
1048
pos+=2
1049
}else if(car=='{'){
1050
// Start of a format string
1051
1052
// Store current literal text
1053
parts.push(text)
1054
1055
// Search the end of the format string, ie the } closing the
1056
// opening {. Since the string can contain other pairs {} for
1057
// nested formatting, an integer nb is incremented for each { and
1058
// decremented for each } ; the end of the format string is
1059
// reached when nb==0
1060
var end = pos+1, nb=1
1061
while(end<_len){
1062
if(self.charAt(end)=='{'){nb++;end++}
1063
else if(self.charAt(end)=='}'){
1064
nb--;end++
1065
if(nb==0){
1066
// End of format string
1067
var fmt_string = self.substring(pos+1, end-1)
1068
1069
// Create a format object, by function parse_format
1070
var fmt_obj = parse_format(fmt_string)
1071
1072
// If no name is explicitely provided, use the rank
1073
if(!fmt_obj.name){
1074
fmt_obj.name=rank+''
1075
rank++
1076
}
1080
// In this case, evaluate them using the positional
1081
// or keyword arguments passed to format()
1083
if(/\d+/.exec(key)){
1084
// If key is numeric, search in positional
1085
// arguments
1086
return _b_.tuple.$dict.__getitem__($.args,
1087
parseInt(key))
1088
}else{
1089
// Else try in keyword arguments
1090
return _b_.dict.$dict.__getitem__($.kw, key)
1091
}
1092
}
1093
fmt_obj.spec = fmt_obj.spec.replace(/\{(.+?)\}/g,
1094
replace_nested)
1095
}
1096
1097
// Store format object in list "parts"
1098
parts.push(fmt_obj)
1099
text = ''
1100
break
1101
}
1102
}else{end++}
1104
if(nb>0){throw ValueError("wrong format "+self)}
1105
pos = end
1106
}else{text += car;pos++}
1110
// Apply formatting to the values passed to format()
1111
var res = '', fmt
1112
for(var i=0;i<parts.length;i++){
1113
// Literal text is added unchanged
1114
if(typeof parts[i]=='string'){res += parts[i];continue}
1115
1116
// Format objects
1117
fmt = parts[i]
1118
if(fmt.name.charAt(0).search(/\d/)>-1){
1119
// Numerical reference : use positional arguments
1120
var pos = parseInt(fmt.name),
1121
value = _b_.tuple.$dict.__getitem__($.args, pos)
1122
}else{
1123
// Use keyword arguments
1124
var value = _b_.dict.$dict.__getitem__($.kw, fmt.name)
1125
}
1126
// If name has extensions (attributes or subscriptions)
1127
for(var j=0;j<fmt.name_ext.length;j++){
1128
var ext = fmt.name_ext[j]
1129
if(ext.charAt(0)=='.'){
1130
// Attribute
1131
value = _b_.getattr(value, ext.substr(1))
1132
}else{
1133
// Subscription
1134
var key = ext.substr(1, ext.length-2)
1135
// An index made of digits is transformed into an integer
1136
if(key.charAt(0).search(/\d/)>-1){key = parseInt(key)}
1137
value = _b_.getattr(value, '__getitem__')(key)
1138
}
1139
}
1140
// If the conversion flag is set, first call a function to convert
1141
// the value
1142
if(fmt.conv=='a'){value = _b_.ascii(value)}
1143
else if(fmt.conv=='r'){value = _b_.repr(value)}
1144
else if(fmt.conv=='s'){value = _b_.str(value)}
1145
1146
// Call attribute __format__ to perform the actual formatting
1147
res += _b_.getattr(value, '__format__')(fmt.spec)
1150
}
1151
1152
$StringDict.format_map = function(self) {
1153
throw NotImplementedError("function format_map not implemented yet");
1154
}
1155
1156
$StringDict.index = function(self){
1157
// Like find(), but raise ValueError when the substring is not found.
1159
if(res===-1) throw _b_.ValueError("substring not found")
1160
return res
1161
}
1162
1163
$StringDict.join = function(){
1164
var $=$B.args('join',2,{self:null,iterable:null},
1165
['self', 'iterable'], arguments, {}, null, null)
1166
1167
var iterable=_b_.iter($.iterable)
1168
var res = [],count=0
1172
if(!isinstance(obj2,str)){throw _b_.TypeError(
1173
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1183
$StringDict.ljust = function(self) {
1184
var $=$B.args('ljust',3,{self:null,width:null,fillchar:null},
1185
['self','width','fillchar'],arguments,{fillchar:' '},null,null)
1186
1187
if ($.width <= self.length) return self
1188
return self + $.fillchar.repeat($.width - self.length)
1192
var $=$B.args('lstrip',2,{self:null,chars:null},['self','chars'],
1193
arguments,{chars:_b_.None},null,null)
1194
if($.chars===_b_.None){return $.self.trimLeft()}
1195
for (var i = 0; i < $.self.length; i++) {
1196
if ($.chars.indexOf($.self.charAt(i)) === -1) {
1197
return $.self.substring(i);
1198
}
1199
}
1200
return '';
1204
$StringDict.maketrans = function() {
1205
var $ = $B.args('maketrans', 3, {x:null,y:null,z:null},['x','y','z'],
1206
arguments, {y:null, z:null}, null, null)
1207
1208
var _t=_b_.dict()
1209
// make 'default' translate table
1210
for(var i=0; i < 256; i++) _t.$numeric_dict[i]=i
1211
1212
if($.y===null && $.z===null){
1213
// If there is only one argument, it must be a dictionary mapping
1214
// Unicode ordinals (integers) or characters (strings of length 1) to
1215
// Unicode ordinals, strings (of arbitrary lengths) or None. Character
1216
// keys will then be converted to ordinals.
1217
if(!_b_.isinstance($.x, _b_.dict)){
1218
throw _b_.TypeError('maketrans only argument must be a dict')
1219
}
1220
var items = _b_.list(_b_.dict.$dict.items($.x))
1221
for(var i=0, len=items.length;i<len;i++){
1222
var k = items[i][0], v=items[i][1]
1223
if(!_b_.isinstance(k, _b_.int)){
1224
if(_b_.isinstance(k, _b_.str) && k.length==1){k = _b_.ord(k)}
1225
else{throw _b_.TypeError("dictionary key "+k+
1226
" is not int or 1-char string")}
1227
}
1228
if(v!==_b_.None && !_b_.isinstance(v, [_b_.int, _b_.str])){
1229
throw _b_.TypeError("dictionary value "+v+
1230
" is not None, integer or string")
1231
}
1232
_t.$numeric_dict[k] = v
1233
}
1234
return _t
1235
}else{
1236
// If there are two arguments, they must be strings of equal length,
1237
// and in the resulting dictionary, each character in x will be mapped
1238
// to the character at the same position in y
1239
if(!(_b_.isinstance($.x, _b_.str) && _b_.isinstance($.y, _b_.str))){
1240
throw _b_.TypeError("maketrans arguments must be strings")
1241
}else if($.x.length!==$.y.length){
1242
throw _b_.TypeError("maketrans arguments must be strings or same length")
1243
}else{
1244
var toNone = {}
1245
if($.z!==null){
1246
// If there is a third argument, it must be a string, whose
1247
// characters will be mapped to None in the result
1248
if(!_b_.isinstance($.z, _b_.str)){
1249
throw _b_.TypeError('maketrans third argument must be a string')
1250
}
1251
for(var i=0,len=$.z.length;i<len;i++){
1252
toNone[_b_.ord($.z.charAt(i))] = true
1253
}
1254
}
1255
for(var i=0,len=$.x.length;i<len;i++){
1256
_t.$numeric_dict[_b_.ord($.x.charAt(i))] = _b_.ord($.y.charAt(i))
1257
}
1258
for(var k in toNone){
1259
_t.$numeric_dict[k] = _b_.None
1260
}
1261
return _t
1262
}
1263
}
1266
$StringDict.partition = function() {
1267
var $=$B.args('partition',2,{self:null,sep:null},['self','sep'],
1268
arguments,{},null,null)
1269
if($.sep==''){throw _b_.ValueError('empty separator')}
1270
check_str($.sep)
1271
var i=$.self.indexOf($.sep)
1272
if (i== -1) return _b_.tuple([$.self, '', ''])
1273
return _b_.tuple([$.self.substring(0,i), $.sep,
1274
$.self.substring(i+$.sep.length)])
1281
var re = new RegExp('\\'+specials.charAt(i),'g')
1282
str = str.replace(re, "\\"+specials.charAt(i))
1283
}
1284
return str
1285
}
1286
1287
$StringDict.replace = function(self, old, _new, count) {
1288
// Replaces occurrences of 'old' by '_new'. Count references
1289
// the number of times to replace. In CPython, negative or undefined
1290
// values of count means replace all.
1291
var $ = $B.args('replace', 4, {self:null,old:null,$$new:null,count:null},
1292
['self','old','$$new','count'], arguments, {count:-1},null,null),
1293
count=$.count,self=$.self,old=$.old,_new=$.$$new
1297
// Validate instance type of 'count'
1298
if (!isinstance(count,[_b_.int,_b_.float])) {
1299
throw _b_.TypeError("'" + $B.get_class(count).__name__ +
1300
"' object cannot be interpreted as an integer");
1301
} else if (isinstance(count, _b_.float)) {
1302
throw _b_.TypeError("integer argument expected, got float");
1303
}
1304
if(count==0){return self}
1305
if(count.__class__==$B.LongInt.$dict){count=parseInt(count.value)}
1306
if(old==''){
1307
if(_new==''){return self}
1308
if(self==''){return _new}
1309
var elts=self.split('')
1310
if(count>-1 && elts.length>=count){
1311
var rest = elts.slice(count).join('')
1312
return _new+elts.slice(0, count).join(_new)+rest
1313
}else{return _new+elts.join(_new)+_new}
1314
}else{
1315
var elts = $StringDict.split(self,old,count)
1318
var res = self, pos = -1
1319
if(old.length==0){
1320
var res = _new
1321
for(var i=0;i<elts.length;i++){
1322
res += elts[i]+_new
1323
}
1324
return res+rest
1325
}
1326
1327
if (count < 0) count = res.length;
1328
while (count > 0) {
1329
pos = res.indexOf(old, pos);
1330
if (pos < 0)
1331
break;
1332
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1333
pos = pos + _new.length;
1334
count--;
1335
}
1336
return res;
1337
}
1338
1339
$StringDict.rfind = function(self){
1340
// Return the highest index in the string where substring sub is found,
1341
// such that sub is contained within s[start:end]. Optional arguments
1342
// start and end are interpreted as in slice notation. Return -1 on failure.
1352
if($.sub.length==0){
1353
if($.start>$.self.length){return -1}
1354
else{return $.self.length}
1355
}
1356
var sublen = $.sub.length
1357
1358
for(var i=$.end-sublen;i>=$.start;i--){
1359
if($.self.substr(i, sublen)==$.sub){return i}
1360
}
1361
return -1
1362
}
1363
1364
$StringDict.rindex = function(){
1365
// Like rfind() but raises ValueError when the substring sub is not found
1367
if(res==-1){throw _b_.ValueError("substring not found")}
1368
return res
1369
}
1370
1371
$StringDict.rjust = function(self) {
1373
{self:null, width:null, fillchar:null},
1374
['self', 'width', 'fillchar'],
1375
arguments,{fillchar:' '},null,null)
1383
var $=$B.args('rpartition',2,{self:null,sep:null},['self','sep'],
1384
arguments,{},null,null)
1385
check_str($.sep)
1386
var self = reverse($.self),
1387
sep = reverse($.sep)
1388
var items = $StringDict.partition(self,sep).reverse()
1389
for(var i=0;i<items.length;i++){
1390
items[i]=items[i].split('').reverse().join('')
1391
}
1392
return items
1396
var $=$B.args("rsplit",3,{self:null,sep:null,maxsplit:null},
1397
['self','sep','maxsplit'],arguments,
1398
{sep:_b_.None, maxsplit:-1},null,null),
1402
var rev_str = reverse($.self),
1403
rev_sep = sep === _b_.None ? sep : reverse($.sep),
1406
// Reverse the list, then each string inside the list
1407
rev_res.reverse()
1408
for(var i=0;i<rev_res.length;i++){
1415
var $=$B.args('rstrip',2,{self:null,chars:null},['self','chars'],
1416
arguments,{chars:_b_.None},null,null)
1417
if($.chars===_b_.None){return $.self.trimRight()}
1418
for (var j = $.self.length-1; j >= 0; j--) {
1419
if ($.chars.indexOf($.self.charAt(j)) === -1) {
1420
return $.self.substring(0,j+1);
1421
}
1422
}
1423
return '';
1428
var $=$B.args("split",3,{self:null,sep:null,maxsplit:null},
1429
['self','sep','maxsplit'],arguments,
1430
{sep:_b_.None, maxsplit:-1},null,null)
1431
var sep=$.sep,maxsplit=$.maxsplit,self=$.self
1432
if(maxsplit.__class__===$B.LongInt.$dict){maxsplit=parseInt(maxsplit.value)}
1438
var name = ''
1439
while(1){
1440
if(self.charAt(pos).search(/\s/)===-1){
1441
if(name===''){name=self.charAt(pos)}
1442
else{name+=self.charAt(pos)}
1443
}else{
1444
if(name!==''){
1445
res.push(name)
1446
if(maxsplit!==-1&&res.length===maxsplit+1){
1447
res.pop()
1448
res.push(name+self.substr(pos))
1449
return res
1450
}
1451
name=''
1452
}
1453
}
1454
pos++
1455
if(pos>self.length-1){
1456
if(name){res.push(name)}
1457
break
1458
}
1459
}
1460
return res
1461
}else{
1463
if(maxsplit==0){return [self]}
1464
while(pos<self.length){
1465
if(self.substr(pos,seplen)==sep){
1466
res.push(s)
1467
pos += seplen
1468
if(maxsplit>-1 && res.length>=maxsplit){
1469
res.push(self.substr(pos))
1470
return res
1471
}
1472
s= ''
1473
}else{
1474
s += self.charAt(pos)
1475
pos++
1483
$StringDict.splitlines = function(self){
1484
var $=$B.args('splitlines',2,{self:null,keepends:null},
1485
['self','keepends'],arguments,{keepends:false},null,null)
1486
if(!_b_.isinstance($.keepends,[_b_.bool, _b_.int])){
1487
throw _b_.TypeError('integer argument expected, got '+
1488
$B.get_class($.keepends).__name)
1489
}
1490
var keepends = _b_.int($.keepends)
1491
// Remove trailing line breaks
1492
if(keepends){
1497
while(pos<self.length){
1498
if(self.substr(pos,2)=='\r\n'){
1499
res.push(self.substring(start,pos+2))
1500
start = pos+2
1501
pos = start
1502
}else if(self.charAt(pos)=='\r' || self.charAt(pos)=='\n'){
1503
res.push(self.substring(start,pos+1))
1504
start = pos+1
1505
pos = start
1506
}else{pos++}
1507
}
1508
var rest = self.substr(start)
1509
if(rest){res.push(rest)}
1510
return res
1511
}else{
1512
var self = $.self.replace(/[\r\n]$/,'')
1513
return self.split(/\n|\r\n|\r/)
1514
}
1515
}
1518
// Return True if string starts with the prefix, otherwise return False.
1519
// prefix can also be a tuple of prefixes to look for. With optional
1520
// start, test string beginning at that position. With optional end,
1521
// stop comparing string at that position.
1523
{self:null, prefix:null, start:null, end:null},
1524
['self', 'prefix', 'start', 'end'],
1527
normalize_start_end($)
1528
1529
var prefixes = $.prefix
1530
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1531
1532
var s = $.self.substring($.start,$.end)
1533
for(var i=0, _len_i = prefixes.length; i < _len_i;i++){
1534
prefix = prefixes[i]
1535
if(!_b_.isinstance(prefix, str)){throw _b_.TypeError(
1536
"endswith first arg must be str or a tuple of str, not int")}
1537
if(s.substr(0,prefix.length)==prefix) return true
1543
$StringDict.strip = function(){
1544
var $=$B.args('strip',2,{self:null,chars:null},['self','chars'],
1545
arguments,{chars:_b_.None},null,null)
1546
if($.chars===_b_.None){return $.self.trim()}
1547
for (var i = 0; i < $.self.length; i++) {
1548
if ($.chars.indexOf($.self.charAt(i)) === -1) {
1549
break;
1550
}
1551
}
1552
for (var j = $.self.length-1; j >= i; j--) {
1553
if ($.chars.indexOf($.self.charAt(j)) === -1) {
1554
break;
1555
}
1556
}
1557
return $.self.substring(i,j+1);
1573
var $=$B.args('zfill',2,{self:null,width:null},
1574
['self','width'],arguments,{},null,null)
1575
if ($.width <= self.length) {return self}
1576
switch(self.charAt(0)){
1577
case '+':
1578
case '-':
1579
return self.charAt(0)+'0'.repeat($.width-self.length)+self.substr(1)
1580
default:
1581
return '0'.repeat(width - self.length)+self
1582
}
1588
case 'string':
1589
return arg
1590
case 'number':
1591
if(isFinite(arg)){return arg.toString()}
1598
// class or its subclasses, but the attribute __str__ of the
1599
// class metaclass (usually "type") or its subclasses (usually
1600
// "object")
1601
// The metaclass is the attribute __class__ of the class dictionary
1602
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1605
}else if(arg.__class__===$B.$type){ // experimental
1606
var func = $B.$type.__getattribute__(arg.__class__,'__str__')
1607
if(func.__func__===_b_.object.$dict.__str__){
1608
return func(arg)
1609
}
1610
return func()
1613
var f = getattr(arg,'__str__')
1614
// XXX fix : if not better than object.__str__, try __repr__
1615
return f()
1616
}
1617
catch(err){
1623
if($B.debug>1){console.log(err)}
1624
console.log('Warning - no method __str__ or __repr__, default to toString', arg)
1626
}
1627
}
1628
}
1629
str.__class__ = $B.$factory
1630
str.$dict = $StringDict
1631
$StringDict.$factory = str
1632
$StringDict.__new__ = function(cls){
1633
if(cls===undefined){
1634
throw _b_.TypeError('str.__new__(): not enough arguments')
1635
}
1636
return {__class__:cls.$dict}
1637
}
1638
1641
// dictionary and factory for subclasses of string
1642
var $StringSubclassDict = {
1643
__class__:$B.$type,
1644
__name__:'str'
1645
}
1646
1647
// the methods in subclass apply the methods in $StringDict to the
1648
// result of instance.valueOf(), which is a Javascript string
1649
for(var $attr in $StringDict){
1650
if(typeof $StringDict[$attr]=='function'){
1651
$StringSubclassDict[$attr]=(function(attr){
1652
return function(){
1658
}
1659
}
1660
return $StringDict[attr].apply(null,args)
1661
}
1662
})($attr)
1663
}
1664
}
1666
1667
// factory for str subclasses
1668
$B.$StringSubclassFactory = {
1669
__class__:$B.$factory,
1670
$dict:$StringSubclassDict
1671
}
1672
1673
_b_.str = str
1674
1675
// Function to parse the 2nd argument of format()
1676
$B.parse_format_spec = function(spec){
1686
if(spec.charAt(1) && aligns.indexOf(spec.charAt(1))!=-1){
1687
// If the second char is also an alignment specifier, the
1688
// first char is the fill value
1689
this.fill = spec.charAt(0)
1690
this.align = spec.charAt(1)
1691
pos = 2
1692
}else{
1693
// The first character defines alignment : fill defaults to ' '
1694
this.align=aligns[align_pos];
1695
this.fill=' ';
1696
pos++
1697
}
1698
}else{
1699
align_pos = aligns.indexOf(spec.charAt(1))
1700
if(spec.charAt(1) && align_pos!=-1){
1701
// The second character defines alignment : fill is the first one
1702
this.align=aligns[align_pos]
1703
this.fill=spec.charAt(0)
1704
pos = 2
1705
}
1706
}
1707
var car = spec.charAt(pos)
1708
if(car=='+'||car=='-'||car==' '){
1709
this.sign=car;
1710
pos++;
1711
car=spec.charAt(pos);
1714
if(car=='0'){
1715
// sign-aware : equivalent to fill=0 and align=='='
1716
this.fill='0'
1717
this.align = '='
1718
pos++;car=spec.charAt(pos)
1719
}
1721
if(this.width===undefined){this.width=car}
1722
else{this.width+=car}
1723
pos++;car=spec.charAt(pos)
1725
if(this.width!==undefined){this.width=parseInt(this.width)}
1726
if(car==','){this.comma=true;pos++;car=spec.charAt(pos)}
1727
if(car=='.'){
1728
if(digits.indexOf(spec.charAt(pos+1))==-1){
1729
throw _b_.ValueError("Missing precision in format spec")
1730
}
1731
this.precision = spec.charAt(pos+1)
1732
pos+=2;car=spec.charAt(pos)
1733
while(car && digits.indexOf(car)>-1){
1734
this.precision+=car;pos++;car=spec.charAt(pos)
1735
}
1736
this.precision = parseInt(this.precision)
1737
}
1738
if(car && types.indexOf(car)>-1){this.type=car;pos++;car=spec.charAt(pos)}
1739
if(pos!==spec.length){
1741
throw _b_.ValueError("Invalid format specifier")
1742
}
1743
}
1744
this.toString = function(){
1745
return (this.fill===undefined ? '' : _b_.str(this.fill))+
1746
(this.align||'')+
1747
(this.sign||'')+
1748
(this.alternate ? '#' : '')+
1749
(this.sign_aware ? '0' : '')+
1750
(this.width || '')+
1751
(this.comma ? ',' : '')+
1752
(this.precision ? '.'+this.precision : '')+
1753
(this.type || '')
1754
}
1755
}
1756
1757
$B.format_width = function(s, fmt){
1758
if(fmt.width && s.length<fmt.width){
1759
var fill=fmt.fill || ' ', align = fmt.align || '<',
1760
missing = fmt.width-s.length
1761
switch(align){
1762
case '<':
1763
return s+fill.repeat(missing)
1764
case '>':
1765
return fill.repeat(missing)+s
1766
case '=':
1767
if('+-'.indexOf(s.charAt(0))>-1){
1768
return s.charAt(0)+fill.repeat(missing)+s.substr(1)