Permalink
Jan 14, 2015
Jan 14, 2015
Jan 1, 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 1, 2015
Jan 1, 2015
Jan 1, 2015
Jan 1, 2015
Newer
100644
1771 lines (1542 sloc)
53.7 KB
9
__name__:'str',
10
$native:true
11
}
12
13
$StringDict.__add__ = function(self,other){
14
if(!(typeof other==="string")){
15
try{return getattr(other,'__radd__')(self)}
16
catch(err){throw _b_.TypeError(
17
"Can't convert "+$B.get_class(other).__name__+" to str implicitely")}
18
}
19
return self+other
20
}
21
22
$StringDict.__contains__ = function(self,item){
23
if(!(typeof item==="string")){throw _b_.TypeError(
24
"'in <string>' requires string as left operand, not "+item.__class__)}
25
var nbcar = item.length
26
if(nbcar==0) return true // a string contains the empty string
27
if(self.length==0) return nbcar==0
29
if(self.substr(i,nbcar)==item) return true
30
}
31
return false
32
}
33
34
$StringDict.__delitem__ = function(){
35
throw _b_.TypeError("'str' object doesn't support item deletion")
36
}
37
38
// __dir__must be assigned explicitely because attribute resolution for builtin
39
// classes doesn't use __mro__
40
$StringDict.__dir__ = $ObjectDict.__dir__
41
42
$StringDict.__eq__ = function(self,other){
43
if(other===undefined){ // compare object "self" to class "str"
44
return self===str
45
}
46
if (_b_.isinstance(other, _b_.str)) {
47
return other.valueOf() == self.valueOf()
48
}
49
return other===self.valueOf()
50
}
51
52
$StringDict.__format__ = function(self,arg){
53
var _fs = $FormattableString(self.valueOf())
54
var args=[]
55
// we don't need the first item (ie, self)
56
for (var i = 1, _len_i = arguments.length; i < _len_i; i++) { args.push(arguments[i])}
57
return _fs.strformat(arg)
58
}
59
60
$StringDict.__getitem__ = function(self,arg){
61
if(isinstance(arg,_b_.int)){
62
var pos = arg
63
if(arg<0) pos+=self.length
64
if(pos>=0 && pos<self.length) return self.charAt(pos)
65
throw _b_.IndexError('string index out of range')
66
}
67
if(isinstance(arg,slice)) {
68
var step = arg.step===None ? 1 : arg.step
69
if(step>0){
70
var start = arg.start===None ? 0 : arg.start
71
var stop = arg.stop===None ? getattr(self,'__len__')() : arg.stop
72
}else{
73
var start = arg.start===None ? getattr(self,'__len__')()-1 : arg.start
74
var stop = arg.stop===None ? 0 : arg.stop
75
}
76
if(start<0) start+=self.length
77
if(stop<0) stop+=self.length
78
var res = '',i=null
79
if(step>0){
80
if(stop<=start) return ''
81
for(var i=start;i<stop;i+=step) res += self.charAt(i)
82
} else {
83
if(stop>=start) return ''
84
for(var i=start;i>=stop;i+=step) res += self.charAt(i)
85
}
86
return res
87
}
88
if(isinstance(arg,bool)) return self.__getitem__(_b_.int(arg))
89
}
90
91
// special method to speed up "for" loops
92
$StringDict.__getitems__ = function(self){return self.split('')}
93
94
$StringDict.__hash__ = function(self) {
95
if (self === undefined) {
96
return $StringDict.__hashvalue__ || $B.$py_next_hash-- // for hash of string type (not instance of string)
97
}
98
99
//http://stackoverflow.com/questions/2909106/python-whats-a-correct-and-good-way-to-implement-hash
100
// this implementation for strings maybe good enough for us..
101
102
var hash=1;
104
hash=(101*hash + self.charCodeAt(i)) & 0xFFFFFFFF
105
}
106
107
return hash
108
}
109
110
$StringDict.__init__ = function(self,arg){
111
self.valueOf = function(){return arg}
112
self.toString = function(){return arg}
113
}
114
115
var $str_iterator = $B.$iterator_class('str_iterator')
116
$StringDict.__iter__ = function(self){
117
var items = self.split('') // list of all characters in string
118
return $B.$iterator(items,$str_iterator)
119
}
120
121
$StringDict.__len__ = function(self){return self.length}
122
123
var kwarg_key = new RegExp('([^\\)]*)\\)')
124
125
var NotANumber = function() {
126
this.name = 'NotANumber'
127
}
128
129
var number_check=function(s) {
130
if(!isinstance(s,[_b_.int,_b_.float])){
131
throw new NotANumber()
132
}
133
}
134
135
var get_char_array = function(size, char) {
136
if (size <= 0)
137
return ''
138
return new Array(size + 1).join(char)
139
}
140
141
var format_padding = function(s, flags, minus_one) {
142
var padding = flags.padding
143
if (!padding) { // undefined
144
return s
145
}
146
s = s.toString()
147
padding = parseInt(padding, 10)
148
if (minus_one) { // numeric formatting where sign goes in front of padding
149
padding -= 1
150
}
151
if (!flags.left) {
152
return get_char_array(padding - s.length, flags.pad_char) + s
153
} else {
154
// left adjusted
155
return s + get_char_array(padding - s.length, flags.pad_char)
156
}
157
}
158
159
var format_int_precision = function(val, flags) {
160
var precision = flags.precision
161
if (!precision) {
162
return val.toString()
163
}
164
precision = parseInt(precision, 10)
165
var s = val.toString()
166
var sign = s[0]
167
if (s[0] === '-') {
168
return '-' + get_char_array(precision - s.length + 1, '0') + s.slice(1)
169
}
170
return get_char_array(precision - s.length, '0') + s
171
}
172
173
var format_float_precision = function(val, upper, flags, modifier) {
174
var precision = flags.precision
175
// val is a float
176
if (isFinite(val)) {
177
val = modifier(val, precision, flags, upper)
178
return val
179
}
180
if (val === Infinity) {
181
val = 'inf'
182
} else if (val === -Infinity) {
183
val = '-inf'
184
} else {
185
val = 'nan'
186
}
187
if (upper) {
188
return val.toUpperCase()
189
}
190
return val
192
}
193
194
var format_sign = function(val, flags) {
195
if (flags.sign) {
196
if (val >= 0) {
197
return "+"
199
} else if (flags.space) {
200
if (val >= 0) {
201
return " "
202
}
203
}
204
return ""
205
}
207
var str_format = function(val, flags) {
208
// string format supports left and right padding
209
flags.pad_char = " " // even if 0 padding is defined, don't use it
210
return format_padding(str(val), flags)
211
}
213
var num_format = function(val, flags) {
214
number_check(val)
215
val = parseInt(val)
216
var s = format_int_precision(val, flags)
217
if (flags.pad_char === '0') {
218
if (val < 0) {
219
s = s.substring(1)
220
return '-' + format_padding(s, flags, true)
221
}
222
var sign = format_sign(val, flags)
223
if (sign !== '') {
224
return sign + format_padding(s, flags, true)
225
}
226
}
227
228
return format_padding(format_sign(val, flags) + s, flags)
229
}
231
var repr_format = function(val, flags) {
232
flags.pad_char = " " // even if 0 padding is defined, don't use it
233
return format_padding(repr(val), flags)
234
}
236
var ascii_format = function(val, flags) {
237
flags.pad_char = " " // even if 0 padding is defined, don't use it
238
return format_padding(ascii(val), flags)
239
}
241
// converts to val to float and sets precision if missing
242
var _float_helper = function(val, flags) {
243
number_check(val)
244
if (!flags.precision) {
245
if (!flags.decimal_point) {
246
flags.precision = 6
247
} else {
248
flags.precision = 0
249
}
250
} else {
251
flags.precision = parseInt(flags.precision, 10)
252
validate_precision(flags.precision)
253
}
254
return parseFloat(val)
255
}
257
// used to capture and remove trailing zeroes
258
var trailing_zeros = /(.*?)(0+)([eE].*)/
259
var leading_zeros = /\.(0*)/
260
var trailing_dot = /\.$/
262
var validate_precision = function(precision) {
263
// force precision to limits of javascript
264
if (precision > 20) {
265
throw _b_.ValueError("precision too big")
266
}
267
}
268
269
// gG
270
var floating_point_format = function(val, upper, flags) {
271
val = _float_helper(val, flags)
272
var v = val.toString()
273
var v_len = v.length
274
var dot_idx = v.indexOf('.')
275
if (dot_idx < 0) {
276
dot_idx = v_len
277
}
278
if (val < 1 && val > -1) {
279
var zeros = leading_zeros.exec(v)
280
var numzeros
281
if (zeros) {
282
numzeros = zeros[1].length
283
} else {
284
numzeros = 0
285
}
286
if (numzeros >= 4) {
287
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
288
if (!flags.alternate) {
289
var trl = trailing_zeros.exec(val)
290
if (trl) {
291
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
297
}
298
return format_padding(val, flags)
299
}
300
flags.precision += numzeros
301
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
302
function(val, precision) {
303
val = val.toFixed(min(precision, v_len - dot_idx) + numzeros)
304
}), flags)
305
}
306
307
if (dot_idx > flags.precision) {
308
val = format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_g_exp_helper)
309
if (!flags.alternate) {
310
var trl = trailing_zeros.exec(val)
311
if (trl) {
312
val = trl[1].replace(trailing_dot, '') + trl[3] // remove trailing
313
}
314
} else {
315
if (flags.precision <= 1) {
316
val = val[0] + '.' + val.substring(1)
317
}
318
}
319
return format_padding(val, flags)
320
}
321
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
322
function(val, precision) {
323
if (!flags.decimal_point) {
324
precision = min(v_len - 1, 6)
325
} else if (precision > v_len) {
326
if (!flags.alternate) {
327
precision = v_len
329
}
330
if (precision < dot_idx) {
331
precision = dot_idx
332
}
333
return val.toFixed(precision - dot_idx)
334
}), flags)
335
}
337
var _floating_g_exp_helper = function(val, precision, flags, upper) {
338
if (precision) {
339
--precision
340
}
341
val = val.toExponential(precision)
342
// pad exponent to two digits
343
var e_idx = val.lastIndexOf('e')
344
if (e_idx > val.length - 4) {
345
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
346
}
347
if (upper) {
348
return val.toUpperCase()
349
}
350
return val
351
}
352
353
// fF
354
var floating_point_decimal_format = function(val, upper, flags) {
355
val = _float_helper(val, flags)
356
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags,
357
function(val, precision, flags) {
358
val = val.toFixed(precision)
359
if (precision === 0 && flags.alternate) {
360
val += '.'
361
}
362
return val
363
}), flags)
364
}
365
366
var _floating_exp_helper = function(val, precision, flags, upper) {
367
val = val.toExponential(precision)
368
// pad exponent to two digits
369
var e_idx = val.lastIndexOf('e')
370
if (e_idx > val.length - 4) {
371
val = val.substring(0, e_idx + 2) + '0' + val.substring(e_idx + 2)
372
}
373
if (upper) {
374
return val.toUpperCase()
375
}
376
return val
377
}
378
379
// eE
380
var floating_point_exponential_format = function(val, upper, flags) {
381
val = _float_helper(val, flags)
382
383
return format_padding(format_sign(val, flags) + format_float_precision(val, upper, flags, _floating_exp_helper), flags)
384
}
385
386
var signed_hex_format = function(val, upper, flags) {
387
number_check(val)
388
var ret = parseInt(val)
389
ret = ret.toString(16)
390
ret = format_int_precision(ret, flags)
391
if (upper) {
392
ret = ret.toUpperCase()
393
}
394
if (flags.pad_char === '0') {
395
if (val < 0) {
396
ret = ret.substring(1)
397
ret = '-' + format_padding(ret, flags, true)
398
}
399
var sign = format_sign(val, flags)
400
if (sign !== '') {
401
ret = sign + format_padding(ret, flags, true)
403
}
404
405
if (flags.alternate) {
406
if (ret.charAt(0) === '-') {
407
if (upper) {
408
ret = "-0X" + ret.slice(1)
409
} else {
410
ret = "-0x" + ret.slice(1)
411
}
412
} else {
413
if (upper) {
414
ret = "0X" + ret
415
} else {
416
ret = "0x" + ret
417
}
418
}
419
}
420
return format_padding(format_sign(val, flags) + ret, flags)
421
}
423
var octal_format = function(val, flags) {
424
number_check(val)
425
var ret = parseInt(val)
426
ret = ret.toString(8)
427
ret = format_int_precision(ret, flags)
429
if (flags.pad_char === '0') {
430
if (val < 0) {
431
ret = ret.substring(1)
432
ret = '-' + format_padding(ret, flags, true)
433
}
434
var sign = format_sign(val, flags)
435
if (sign !== '') {
436
ret = sign + format_padding(ret, flags, true)
437
}
439
440
if (flags.alternate) {
441
if (ret.charAt(0) === '-') {
442
ret = "-0o" + ret.slice(1)
443
} else {
444
ret = "0o" + ret
445
}
447
return format_padding(ret, flags)
448
}
449
450
var single_char_format = function(val, flags) {
451
if(isinstance(val,str) && val.length==1) return val
452
try {
453
val = _b_.int(val) // yes, floats are valid (they are cast to int)
454
} catch (err) {
455
throw _b_.TypeError('%c requires int or char')
456
}
457
return format_padding(chr(val), flags)
458
}
459
460
var num_flag = function(c, flags) {
461
if (c === '0' && !flags.padding && !flags.decimal_point && !flags.left) {
462
flags.pad_char = '0'
463
return
464
}
465
if (!flags.decimal_point) {
466
flags.padding = (flags.padding || "") + c
467
} else {
468
flags.precision = (flags.precision || "") + c
469
}
470
}
471
472
var decimal_point_flag = function(val, flags) {
473
if (flags.decimal_point) {
474
// can only have one decimal point
475
throw new UnsupportedChar()
476
}
477
flags.decimal_point = true
478
}
479
480
var neg_flag = function(val, flags) {
481
flags.pad_char = ' ' // overrides '0' flag
482
flags.left = true
483
}
484
485
var space_flag = function(val, flags) {
486
flags.space = true
487
}
488
489
var sign_flag = function(val, flags) {
490
flags.sign = true
491
}
492
493
var alternate_flag = function(val, flags) {
494
flags.alternate = true
495
}
496
497
var char_to_func_mapping = {
498
's': str_format,
499
'd': num_format,
500
'i': num_format,
501
'u': num_format,
502
'o': octal_format,
503
'r': repr_format,
504
'a': ascii_format,
505
'g': function(val, flags) {return floating_point_format(val, false, flags)},
506
'G': function(val, flags) {return floating_point_format(val, true, flags)},
507
'f': function(val, flags) {return floating_point_decimal_format(val, false, flags)},
508
'F': function(val, flags) {return floating_point_decimal_format(val, true, flags)},
509
'e': function(val, flags) {return floating_point_exponential_format(val, false, flags)},
510
'E': function(val, flags) {return floating_point_exponential_format(val, true, flags)},
511
'x': function(val, flags) {return signed_hex_format(val, false, flags)},
512
'X': function(val, flags) {return signed_hex_format(val, true, flags)},
513
'c': single_char_format,
514
'0': function(val, flags) {return num_flag('0', flags)},
515
'1': function(val, flags) {return num_flag('1', flags)},
516
'2': function(val, flags) {return num_flag('2', flags)},
517
'3': function(val, flags) {return num_flag('3', flags)},
518
'4': function(val, flags) {return num_flag('4', flags)},
519
'5': function(val, flags) {return num_flag('5', flags)},
520
'6': function(val, flags) {return num_flag('6', flags)},
521
'7': function(val, flags) {return num_flag('7', flags)},
522
'8': function(val, flags) {return num_flag('8', flags)},
523
'9': function(val, flags) {return num_flag('9', flags)},
524
'-': neg_flag,
525
' ': space_flag,
526
'+': sign_flag,
527
'.': decimal_point_flag,
528
'#': alternate_flag
529
}
530
531
// exception thrown when an unsupported char is encountered in legacy format
532
var UnsupportedChar = function() {
533
this.name = "UnsupportedChar"
534
}
535
536
$StringDict.__mod__ = function(val, args) {
537
return $legacy_format(val, args, char_to_func_mapping)
538
}
539
540
var $legacy_format = function(val, args, char_mapping) {
541
var length = val.length
542
var pos = 0 |0
543
var argpos = null
544
if (args && args.__class__ === _b_.tuple.$dict) {
545
argpos = 0 |0
546
}
547
var ret = ''
548
var $get_kwarg_string = function(s) {
549
// returns [val, newpos]
550
++pos
551
var rslt = kwarg_key.exec(s.substring(newpos))
552
if (!rslt) {
553
throw _b_.ValueError("incomplete format key")
554
}
555
var key = rslt[1]
556
newpos += rslt[0].length
557
try {
558
var val = args.__class__.__getitem__(args, key)
559
} catch(err) {
560
if (err.name === "KeyError") {
561
throw err
562
}
563
throw _b_.TypeError("format requires a mapping")
564
}
565
return get_string_value(s, val)
566
}
567
568
var $get_arg_string = function(s) {
569
// returns [val, newpos]
570
var val
571
572
// non-tuple args
573
if (argpos === null) {
574
// args is the value
575
val = args
576
} else {
577
try {
578
val = args[argpos++]
579
}
580
catch(err) {
581
if (err.name === "IndexError") {
582
throw _b_.TypeError("not enough arguments for format string")
583
} else {
584
throw err
585
}
588
return get_string_value(s, val)
589
}
590
var get_string_value = function(s, val) {
591
// todo: get flags, type
592
// todo: string value based on flags, type, value
593
var flags = {'pad_char': ' '}
594
do {
596
try {
597
if (func === undefined) {
598
throw new UnsupportedChar()
599
} else {
600
var ret = func(val, flags)
601
if (ret !== undefined) {
602
return ret
603
}
604
++newpos
605
}
606
} catch (err) {
607
if (err.name === "UnsupportedChar") {
608
invalid_char = s[newpos]
609
if (invalid_char === undefined) {
610
throw _b_.ValueError("incomplete format")
611
}
612
throw _b_.ValueError("unsupported format character '" + invalid_char +
613
"' (0x" + invalid_char.charCodeAt(0).toString(16) + ") at index " + newpos)
614
} else if (err.name === "NotANumber") {
615
var try_char = s[newpos]
616
var cls = val.__class__
617
if (!cls) {
618
if (typeof(val) === 'string') {
619
cls = 'str'
620
} else {
621
cls = typeof(val)
622
}
623
} else {
624
cls = cls.__name__
625
}
626
throw _b_.TypeError("%" + try_char + " format: a number is required, not " + cls)
627
} else {
628
throw err
629
}
635
if (newpos < 0) {
636
ret += val.substring(pos)
637
break
638
}
639
ret += val.substring(pos, newpos)
640
++newpos
641
if (newpos < length) {
642
if (val[newpos] === '%') {
643
ret += '%'
644
++newpos
645
} else {
646
var tmp
647
if (val[newpos] === '(') {
648
++newpos
649
ret += $get_kwarg_string(val)
650
} else {
651
ret += $get_arg_string(val)
652
}
653
}
654
} else {
655
// % at end of string
656
throw _b_.ValueError("incomplete format")
657
}
658
pos = newpos + 1
659
} while (pos < length)
660
return ret
661
}
662
663
var char_to_new_format_mapping = {
664
'b': function(val, flags) {
665
number_check(val)
666
val = val.toString(2)
667
if (flags.alternate) {
668
val = "0b" + val
669
}
670
return val
671
},
672
'n': function(val, flags) {return floating_point_format(val, false, flags)},
673
'N': function(val, flags) {return floating_point_format(val, true, flags)}
674
}
676
for (k in char_to_func_mapping) {
677
char_to_new_format_mapping[k] = char_to_func_mapping[k]
678
}
679
680
$format_to_legacy = function(val, args) {
681
return $legacy_format(val, args, char_to_new_format_mapping)
682
}
683
684
$StringDict.__mro__ = [$StringDict,$ObjectDict]
685
686
$StringDict.__mul__ = function(self,other){
687
if(!isinstance(other,_b_.int)){throw _b_.TypeError(
688
"Can't multiply sequence by non-int of type '"+
689
$B.get_class(other).__name__+"'")}
690
$res = ''
691
for(var i=0;i<other;i++){$res+=self.valueOf()}
692
return $res
693
}
694
695
$StringDict.__ne__ = function(self,other){return other!==self.valueOf()}
696
697
$StringDict.__repr__ = function(self){
698
if(self===undefined){return "<class 'str'>"}
699
var qesc = new RegExp("'","g") // to escape single quote
700
var res = self.replace(/\n/g,'\\\\n')
701
res = "'"+res.replace(qesc,"\\'")+"'"
702
return res
703
}
704
705
$StringDict.__setattr__ = function(self,attr,value){setattr(self,attr,value)}
706
707
$StringDict.__setitem__ = function(self,attr,value){
708
throw _b_.TypeError("'str' object does not support item assignment")
709
}
710
$StringDict.__str__ = function(self){
711
if(self===undefined) return "<class 'str'>"
712
return self.toString()
713
}
714
$StringDict.toString = function(){return 'string!'}
715
716
// generate comparison methods
717
var $comp_func = function(self,other){
718
if(typeof other !=="string"){throw _b_.TypeError(
719
"unorderable types: 'str' > "+$B.get_class(other).__name__+"()")}
720
return self > other
721
}
722
$comp_func += '' // source code
723
var $comps = {'>':'gt','>=':'ge','<':'lt','<=':'le'}
724
for(var $op in $comps){
725
eval("$StringDict.__"+$comps[$op]+'__ = '+$comp_func.replace(/>/gm,$op))
726
}
727
728
// add "reflected" methods
729
$B.make_rmethods($StringDict)
730
731
// unsupported operations
732
var $notimplemented = function(self,other){
733
throw NotImplementedError("OPERATOR not implemented for class str")
734
}
735
736
$StringDict.capitalize = function(self){
737
if(self.length==0) return ''
738
return self.charAt(0).toUpperCase()+self.substr(1).toLowerCase()
739
}
740
741
$StringDict.casefold = function(self) {
742
throw _b_.NotImplementedError("function casefold not implemented yet");
743
}
744
745
$StringDict.center = function(self,width,fillchar){
746
if(fillchar===undefined){fillchar=' '}else{fillchar=fillchar}
747
if(width<=self.length) return self
748
749
var pad = parseInt((width-self.length)/2)
750
var res = Array(pad+1).join(fillchar) // is this statement faster than the for loop below?
751
res += self + res
752
if(res.length<width){res += fillchar}
753
return res
754
}
755
756
$StringDict.count = function(self,elt){
757
if(!(typeof elt==="string")){throw _b_.TypeError(
758
"Can't convert '"+elt.__class__.__name__+"' object to str implicitly")}
759
//needs to be non overlapping occurrences of substring in string.
760
var n=0, pos=0
761
while(1){
762
pos=self.indexOf(elt,pos)
763
if(pos>=0){ n++; pos+=elt.length} else break;
764
}
765
return n
766
}
767
768
$StringDict.encode = function(self, encoding) {
769
if (encoding === undefined) encoding='utf-8'
770
return bytes(self, encoding)
771
}
772
773
$StringDict.endswith = function(self){
774
// Return True if the string ends with the specified suffix, otherwise
775
// return False. suffix can also be a tuple of suffixes to look for.
776
// With optional start, test beginning at that position. With optional
777
// end, stop comparing at that position.
778
var args = []
780
var start=null,end=null
781
var $ns=$B.$MakeArgs("$StringDict.endswith",args,['suffix'],
782
['start','end'],null,null)
783
var suffixes = $ns['suffix']
784
if(!isinstance(suffixes,_b_.tuple)){suffixes=[suffixes]}
785
start = $ns['start'] || start
786
end = $ns['end'] || self.length-1
787
var s = self.substr(start,end+1)
789
suffix = suffixes[i]
790
if(suffix.length<=s.length &&
791
s.substr(s.length-suffix.length)==suffix) return true
792
}
793
return false
794
}
795
796
$StringDict.expandtabs = function(self, tabsize) {
797
tabsize=tabsize || 8
798
var _str=''
799
for (var i=0; i < tabsize; i++) _str+=' '
800
return self.valueOf().replace(/\t/g, _str)
801
}
802
803
$StringDict.find = function(self){
804
// Return the lowest index in the string where substring sub is found,
805
// such that sub is contained in the slice s[start:end]. Optional
806
// arguments start and end are interpreted as in slice notation.
807
// Return -1 if sub is not found.
808
var start=0,end=self.length
809
var $ns=$B.$MakeArgs("$StringDict.find",arguments,['self','sub'],
810
['start','end'],null,null)
811
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
812
if(!isinstance(sub,str)){throw _b_.TypeError(
813
"Can't convert '"+sub.__class__.__name__+"' object to str implicitly")}
814
if(!isinstance(start,_b_.int)||!isinstance(end,_b_.int)){
815
throw _b_.TypeError(
816
"slice indices must be integers or None or have an __index__ method")}
817
var s = self.substring(start,end)
818
var esc_sub = ''
820
switch(sub.charAt(i)) {
821
case '[':
822
case '.':
823
case '*':
824
case '+':
825
case '?':
826
case '|':
827
case '(':
828
case ')':
829
case '$':
830
case '^':
831
esc_sub += '\\'
832
}
833
esc_sub += sub.charAt(i)
834
}
835
var res = s.search(esc_sub)
836
if(res==-1) return -1
837
return start+res
838
}
839
840
var $FormattableString=function(format_string) {
841
// inspired from
842
// https://raw.github.com/florentx/stringformat/master/stringformat.py
843
this.format_string=format_string
844
845
this._prepare = function() {
846
//console.log('prepare')
847
var match = arguments[0]
848
//console.log('match1', match)
849
850
var p1 = '' + arguments[2]
851
852
if (match == '%') return '%%'
853
if (match.substring(0,1) == match.substring(match.length-1)) {
854
// '{{' or '}}'
855
return match.substring(0, Math.floor(match.length/2))
856
}
857
858
if (p1.charAt(0) == '{' && p1.charAt(match.length-1) == '}') {
859
p1=match.substring(1, p1.length-1)
860
}
861
862
var _repl
863
if (match.length >= 2) {
864
_repl=''
865
} else {
866
_repl = match.substring(1)
867
}
868
869
var _i = p1.indexOf(':')
870
var _out
871
if (_i > -1) {
872
_out = [p1.slice(0,_i), p1.slice(_i+1)]
873
} else { _out=[p1]}
874
875
var _field=_out[0] || ''
876
var _format_spec=_out[1] || ''
877
878
_out= _field.split('!')
879
var _literal=_out[0] || ''
880
var _sep=_field.indexOf('!') > -1?'!': undefined // _out[1]
881
var _conv=_out[1] //conversion
882
883
if (_sep && _conv === undefined) {
884
throw _b_.ValueError("end of format while looking for conversion specifier")
885
}
886
887
if (_conv !== undefined && _conv.length > 1) {
888
throw _b_.ValueError("expected ':' after format specifier")
889
}
890
891
if (_conv !== undefined && 'rsa'.indexOf(_conv) == -1) {
892
throw _b_.ValueError("Unknown conversion specifier " + _conv)
893
}
894
895
_name_parts=this.field_part.apply(null, [_literal])
896
897
var _start=_literal.charAt(0)
898
var _name=''
899
if (_start=='' || _start=='.' || _start == '[') {
900
// auto-numbering
901
if (this._index === undefined) {
902
throw _b_.ValueError("cannot switch from manual field specification to automatic field numbering")
903
}
904
905
_name = self._index.toString()
906
this._index+=1
907
908
if (! _literal ) {
909
_name_parts.shift()
910
}
911
} else {
912
_name = _name_parts.shift()[1]
914
// manual specification
915
if (this._index) {
916
throw _b_.ValueError("cannot switch from automatic field " +
917
"numbering to manual field specification")
918
this._index=undefined
919
}
920
}
921
}
922
923
var _empty_attribute=false
924
925
var _k
927
_k = _name_parts[i][0]
928
var _v = _name_parts[i][1]
929
var _tail = _name_parts[i][2]
930
if (_v === '') {_empty_attribute = true}
931
if (_tail !== '') {
932
throw _b_.ValueError("Only '.' or '[' may follow ']' " +
933
"in format field specifier")
934
}
935
}
936
937
if (_name_parts && _k == '[' && !
938
_literal.charAt(_literal.length) == ']') {
939
throw _b_.ValueError("Missing ']' in format string")
940
}
941
942
if (_empty_attribute) {
943
throw _b_.ValueError("Empty attribute in format string")
944
}
945
946
var _rv=''
947
if (_format_spec.indexOf('{') != -1) {
948
_format_spec = _format_spec.replace(this.format_sub_re, this._prepare)
949
_rv = [_name_parts, _conv, _format_spec]
950
if (this._nested[_name] === undefined) {
951
this._nested[_name]=[]
952
this._nested_array.push(_name)
953
}
954
this._nested[_name].push(_rv)
955
} else {
956
_rv = [_name_parts, _conv, _format_spec]
957
if (this._kwords[_name] === undefined) {
958
this._kwords[_name]=[]
959
this._kwords_array.push(_name)
960
}
961
this._kwords[_name].push(_rv)
962
}
963
964
return '%(' + id(_rv) + ')s'
965
} // this._prepare
966
967
this.format=function() {
968
// same as str.format() and unicode.format in Python 2.6+
969
970
var $ns=$B.$MakeArgs('format',arguments,[],[],'args','kwargs')
971
var args=$ns['args']
972
var kwargs=$ns['kwargs']
973
974
if (args.length>0) {
976
//kwargs[str(i)]=args.$dict[i]
977
getattr(kwargs, '__setitem__')(str(i), args[i])
978
}
979
}
980
981
//encode arguments to ASCII, if format string is bytes
982
var _want_bytes = isinstance(this._string, str)
983
var _params=_b_.dict()
984
986
var _name = this._kwords_array[i]
987
var _items = this._kwords[_name]
988
var _var = getattr(kwargs, '__getitem__')(_name)
989
var _value;
990
if (hasattr(_var, 'value')) {
991
_value = getattr(_var, 'value')
992
} else {
993
_value=_var
994
}
995
997
var _parts = _items[j][0]
998
var _conv = _items[j][1]
999
var _spec = _items[j][2]
1000
1001
var _f=this.format_field.apply(null, [_value, _parts,_conv,_spec,_want_bytes])
1002
getattr(_params,'__setitem__')(id(_items[j]).toString(), _f)
1003
}
1004
}
1005
1007
var _name = this._nested_array[i]
1008
var _items = this._nested[i]
1009
1010
var _var = getattr(kwargs, '__getitem__')(_name)
1011
var _value;
1012
if (hasattr(_var, 'value')) {
1013
_value = getattr(getattr(kwargs, '__getitem__')(_name), 'value')
1014
} else {
1015
_value=_var
1016
}
1017
1019
var _parts = _items[j][0]
1020
var _conv = _items[j][1]
1021
var _spec = _items[j][2]
1022
1024
1025
var _f=this.format_field.apply(null, [_value, _parts,_conv,_spec,_want_bytes])
1026
getattr(_params,'__setitem__')(id(_items[j]).toString(), _f)
1027
}
1028
}
1030
} // this.format
1031
1032
this.format_field=function(value,parts,conv,spec,want_bytes) {
1033
1034
if (want_bytes === undefined) want_bytes = false
1035
1037
var _k = parts[i][0]
1038
var _part = parts[i][1]
1039
1040
if (_k) {
1041
if (!isNaN(_part)) {
1042
value = value[parseInt(_part)]
1043
} else {
1044
value = getattr(value, _part)
1045
}
1046
} else {
1047
value = value[_part]
1048
}
1049
}
1050
1051
if (conv) {
1052
// fix me
1059
1060
return value
1061
}
1062
1063
this.strformat=function(value, format_spec) {
1064
if (format_spec === undefined) format_spec = ''
1065
if (!isinstance(value,[str,_b_.int]) && hasattr(value, '__format__')) {
1066
return getattr(value, '__format__')(format_spec)
1067
}
1068
var _m = this.format_spec_re.test(format_spec)
1069
1070
if (!_m) throw _b_.ValueError('Invalid conversion specification')
1071
1072
var _match=this.format_spec_re.exec(format_spec)
1073
var _align=_match[1]
1074
var _sign=_match[2]
1075
var _prefix=_match[3]
1076
var _width=_match[4]
1077
var _comma=_match[5]
1078
var _precision=_match[6]
1079
var _conversion=_match[7]
1080
1084
1085
if (_prefix != '' && ! _is_numeric) {
1086
if (_is_numeric) {
1087
throw _b_.ValueError('Alternate form (#) not allowed in float format specifier')
1088
} else {
1089
throw _b_.ValueError('Alternate form (#) not allowed in string format specification')
1090
}
1091
}
1092
1093
if (_is_numeric && _conversion == 'n') {
1094
_conversion = _is_integer && 'd' || 'g'
1095
} else {
1096
if (_sign) {
1097
if (! _is_numeric) {
1098
throw _b_.ValueError('Sign not allowed in string format specification');
1099
}
1100
if (_conversion == 'c') {
1101
throw("Sign not allowed with integer format specifier 'c'")
1102
}
1103
}
1104
}
1105
1106
if (_comma !== '') {
1107
value += ''
1108
var x = value.split('.')
1109
var x1 = x[0];
1110
var x2 = x.length > 1 ? '.' + x[1] : '';
1111
var rgx = /(\d+)(\d{3})/;
1112
1113
while (rgx.test(x1)) {
1114
x1 = x1.replace(rgx, '$1' + ',' + '$2');
1115
}
1116
value=x1+x2
1117
}
1118
1119
var _rv
1120
if (_conversion != '' && ((_is_numeric && _conversion == 's') ||
1121
(! _is_integer && 'coxX'.indexOf(_conversion) != -1))) {
1122
console.log(_conversion)
1123
throw _b_.ValueError('Fix me')
1124
}
1125
1126
if (_conversion == 'c') _conversion = 's'
1127
1128
// fix me
1129
_rv='%' + _prefix + _precision + (_conversion || 's')
1130
1132
1133
if (_sign != '-' && value >= 0) _rv = _sign + _rv
1134
1135
var _zero = false
1136
if (_width) {
1137
_zero = _width.charAt(0) == '0'
1138
_width = parseInt(_width)
1139
} else {
1140
_width = 0
1141
}
1142
1143
// Fastpath when alignment is not required
1144
1145
if (_width <= _rv.length) {
1147
throw _b_.ValueError("'=' alignment not allowed in string format specifier")
1148
}
1149
return _rv
1150
}
1151
1152
_fill = _align.substr(0,_align.length-1)
1153
_align= _align.substr(_align.length-1)
1154
1155
if (! _fill) {_fill = _zero && '0' || ' '}
1156
1157
if (_align == '^') {
1158
_rv = getattr(_rv, 'center')(_width, _fill)
1159
} else if (_align == '=' || (_zero && ! _align)) {
1160
if (! _is_numeric) {
1161
throw _b_.ValueError("'=' alignment not allowed in string format specifier")
1162
}
1163
if (_value < 0 || _sign != '-') {
1164
_rv = _rv.substring(0,1) + getattr(_rv.substring(1),'rjust')(_width - 1, _fill)
1165
} else {
1166
_rv = getattr(_rv, 'rjust')(_width, _fill)
1167
}
1168
} else if ((_align == '>' || _align == '=') || (_is_numeric && ! _aligned)) {
1169
_rv = getattr(_rv, 'rjust')(_width, _fill)
1170
} else if (_align == '<') {
1171
_rv = getattr(_rv, 'ljust')(_width, _fill)
1172
} else {
1173
throw _b_.ValueError("'" + _align + "' alignment not valid")
1174
}
1175
1176
return _rv
1177
}
1178
1179
this.field_part=function(literal) {
1180
if (literal.length == 0) return [['','','']]
1181
1182
var _matches=[]
1183
var _pos=0
1184
1185
var _start='', _middle='', _end=''
1186
var arg_name=''
1187
1188
// arg_name
1189
if (literal === undefined) console.log(literal)
1190
var _lit=literal.charAt(_pos)
1191
while (_pos < literal.length &&
1192
_lit !== '[' && _lit !== '.') {
1193
arg_name += _lit
1194
_pos++
1195
_lit=literal.charAt(_pos)
1196
}
1197
1198
// todo.. need to work on code below, but this takes cares of most
1199
// common cases.
1200
if (arg_name != '') _matches.push(['', arg_name, ''])
1201
1202
//return _matches
1203
1204
var attribute_name=''
1205
var element_index=''
1206
1207
//look for attribute_name and element_index
1208
while (_pos < literal.length) {
1209
var car = literal.charAt(_pos)
1210
1211
if (car == '[') { // element_index
1212
_start=_middle=_end=''
1213
_pos++
1214
1215
car = literal.charAt(_pos)
1216
while (_pos < literal.length && car !== ']') {
1217
_middle += car
1218
_pos++
1219
car = literal.charAt(_pos)
1220
}
1221
1222
_pos++
1223
if (car == ']') {
1224
while (_pos < literal.length) {
1225
_end+=literal.charAt(_pos)
1226
_pos++
1227
}
1228
}
1229
1230
_matches.push([_start, _middle, _end])
1231
1232
} else if (car == '.') { // attribute_name
1233
_middle=''
1234
_pos++
1235
car = literal.charAt(_pos)
1236
while (_pos < literal.length &&
1237
car !== '[' &&
1238
car !== '.') {
1239
//console.log(car)
1240
_middle += car
1241
_pos++
1242
car = literal.charAt(_pos)
1243
}
1244
1245
_matches.push(['.', _middle, ''])
1246
}
1247
}
1248
return _matches
1249
}
1250
1251
this.format_str_re = new RegExp(
1252
'(%)' +
1253
'|((?!{)(?:{{)+' +
1254
'|(?:}})+(?!})' +
1256
)
1257
1258
this.format_sub_re = new RegExp('({[^{}]*})') // nested replacement field
1259
1260
this.format_spec_re = new RegExp(
1261
'((?:[^{}]?[<>=^])?)' + // alignment
1262
'([\\-\\+ ]?)' + // sign
1263
'(#?)' + '(\\d*)' + '(,?)' + // base prefix, minimal width, thousands sep
1264
'((?:\.\\d+)?)' + // precision
1265
'(.?)$' // type
1266
)
1267
1268
this._index = 0
1269
this._kwords = {}
1270
this._kwords_array=[]
1271
this._nested = {}
1272
this._nested_array=[]
1273
1274
this._string=format_string.replace(this.format_str_re, this._prepare)
1275
1276
return this
1277
}
1278
1279
1280
$StringDict.format = function(self) {
1281
1282
var _fs = $FormattableString(self.valueOf())
1283
var args=[]
1284
// we don't need the first item (ie, self)
1285
for (var i = 1, _len_i = arguments.length; i < _len_i; i++) { args.push(arguments[i])}
1286
return _fs.format.apply(null, args)
1287
}
1288
1289
$StringDict.format_map = function(self) {
1290
throw NotImplementedError("function format_map not implemented yet");
1291
}
1292
1293
$StringDict.index = function(self){
1294
// Like find(), but raise ValueError when the substring is not found.
1295
var res = $StringDict.find.apply(self,arguments)
1296
if(res===-1) throw _b_.ValueError("substring not found")
1297
return res
1298
}
1299
1300
$StringDict.isalnum = function(self) {return /^[a-z0-9]+$/i.test(self)}
1301
1302
$StringDict.isalpha = function(self) {return /^[a-z]+$/i.test(self)}
1303
1304
$StringDict.isdecimal = function(self) {
1305
// this is not 100% correct
1306
return /^[0-9]+$/.test(self)
1307
}
1308
1309
$StringDict.isdigit = function(self) { return /^[0-9]+$/.test(self)}
1310
1311
$StringDict.isidentifier = function(self) {
1312
1313
switch(self) {
1314
case 'False':
1315
case 'None':
1316
case 'True':
1317
case 'and':
1318
case 'as':
1319
case 'assert':
1320
case 'break':
1321
case 'class':
1322
case 'continue':
1323
case 'def':
1324
case 'del':
1325
case 'elif':
1326
case 'else':
1327
case 'except':
1328
case 'finally':
1329
case 'for':
1330
case 'from':
1331
case 'global':
1332
case 'if':
1333
case 'import':
1334
case 'in':
1335
case 'is':
1336
case 'lambda':
1337
case 'nonlocal':
1338
case 'not':
1339
case 'or':
1340
case 'pass':
1341
case 'raise':
1342
case 'return':
1343
case 'try':
1344
case 'while':
1345
case 'with':
1346
case 'yield':
1347
return true
1348
}
1349
1350
// fixme.. this isn't complete but should be a good start
1351
return /^[a-z][0-9a-z_]+$/i.test(self)
1352
}
1353
1354
$StringDict.islower = function(self) {return /^[a-z]+$/.test(self)}
1355
1356
// not sure how to handle unicode variables
1357
$StringDict.isnumeric = function(self) {return /^[0-9]+$/.test(self)}
1358
1359
// inspired by http://www.codingforums.com/archive/index.php/t-17925.html
1360
$StringDict.isprintable = function(self) {return !/[^ -~]/.test(self)}
1361
1362
$StringDict.isspace = function(self) {return /^\s+$/i.test(self)}
1363
1364
$StringDict.istitle = function(self) {return /^([A-Z][a-z]+)(\s[A-Z][a-z]+)$/i.test(self)}
1365
1366
$StringDict.isupper = function(self) {return /^[A-Z]+$/.test(self)}
1367
1368
$StringDict.join = function(self,obj){
1369
var iterable=iter(obj)
1370
var res = '',count=0
1371
while(1){
1372
try{
1373
var obj2 = next(iterable)
1374
if(!isinstance(obj2,str)){throw _b_.TypeError(
1375
"sequence item "+count+": expected str instance, "+$B.get_class(obj2).__name__+" found")}
1376
res += obj2+self
1377
count++
1378
}catch(err){
1379
if(err.__name__==='StopIteration'){$B.$pop_exc();break}
1380
else{throw err}
1381
}
1382
}
1383
if(count==0) return ''
1384
return res.substr(0,res.length-self.length)
1385
}
1386
1387
$StringDict.ljust = function(self, width, fillchar) {
1388
if (width <= self.length) return self
1389
if (fillchar === undefined) fillchar=' '
1390
return self + Array(width - self.length + 1).join(fillchar)
1391
}
1392
1393
$StringDict.lower = function(self){return self.toLowerCase()}
1394
1395
$StringDict.lstrip = function(self,x){
1396
var pattern = null
1397
if(x==undefined){pattern="\\s*"}
1398
else{pattern = "["+x+"]*"}
1399
var sp = new RegExp("^"+pattern)
1400
return self.replace(sp,"")
1401
}
1402
1403
// note, maketrans should be a static function.
1404
$StringDict.maketrans = function(from, to) {
1405
var _t=[]
1406
// make 'default' translate table
1407
for(var i=0; i < 256; i++) _t[i]=String.fromCharCode(i)
1408
1409
// make substitution in the translation table
1411
var _ndx=from.source[i].charCodeAt(0) //retrieve ascii code of char
1412
_t[_ndx]=to.source[i]
1413
}
1414
1415
// create a data structure that string.translate understands
1419
}
1420
return _d
1421
}
1422
1423
$StringDict.partition = function(self,sep) {
1424
if (sep === undefined) {
1425
throw Error("sep argument is required");
1426
return
1427
}
1428
var i=self.indexOf(sep)
1429
if (i== -1) return _b_.tuple([self, '', ''])
1430
return _b_.tuple([self.substring(0,i), sep, self.substring(i+sep.length)])
1431
}
1432
1433
function $re_escape(str)
1434
{
1435
var specials = "[.*+?|()$^"
1437
var re = new RegExp('\\'+specials.charAt(i),'g')
1438
str = str.replace(re, "\\"+specials.charAt(i))
1439
}
1440
return str
1441
}
1442
1443
$StringDict.replace = function(self, old, _new, count) {
1444
// Replaces occurrences of 'old' by '_new'. Count references
1445
// the number of times to replace. In CPython, negative or undefined
1446
// values of count means replace all.
1447
if (count === undefined) {
1448
count = -1;
1449
} else {
1450
// Validate instance type of 'count'
1451
if (!isinstance(count,[_b_.int,_b_.float])) {
1452
throw _b_.TypeError("'" + str(count.__class__) + "' object cannot be interpreted as an integer");
1453
} else if (isinstance(count, _b_.float)) {
1454
throw _b_.TypeError("integer argument expected, got float");
1457
1458
var res = self.valueOf();
1459
var pos = -1;
1460
if (count < 0) count = res.length;
1461
while (count > 0) {
1462
pos = res.indexOf(old, pos);
1463
if (pos < 0)
1464
break;
1465
res = res.substr(0, pos) + _new + res.substr(pos + old.length);
1466
pos = pos + _new.length;
1467
count--;
1468
}
1469
return res;
1470
}
1471
1472
$StringDict.rfind = function(self){
1473
// Return the highest index in the string where substring sub is found,
1474
// such that sub is contained within s[start:end]. Optional arguments
1475
// start and end are interpreted as in slice notation. Return -1 on failure.
1476
var start=0,end=self.length
1477
var $ns=$B.$MakeArgs("$StringDict.find",arguments,['self','sub'],
1478
['start','end'],null,null)
1479
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1480
if(!isinstance(sub,str)){throw _b_.TypeError(
1481
"Can't convert '"+sub.__class__.__name__+"' object to str implicitly")}
1482
if(!isinstance(start,_b_.int)||!isinstance(end,_b_.int)){throw _b_.TypeError(
1483
"slice indices must be integers or None or have an __index__ method")}
1484
1485
var s = self.substring(start,end)
1486
var reversed = '',rsub=''
1487
for(var i=s.length-1;i>=0;i--){reversed += s.charAt(i)}
1488
for(var i=sub.length-1;i>=0;i--){rsub += sub.charAt(i)}
1489
var res = reversed.search($re_escape(rsub))
1490
if(res==-1) return -1
1491
return start+s.length-1-res-sub.length+1
1492
}
1493
1494
$StringDict.rindex = function(){
1495
// Like rfind() but raises ValueError when the substring sub is not found
1496
var res = $StringDict.rfind.apply(this,arguments)
1497
if(res==-1){throw _b_.ValueError("substring not found")}
1498
return res
1499
}
1500
1501
$StringDict.rjust = function(self) {
1502
var fillchar = ' '
1503
var $ns=$B.$MakeArgs("$StringDict.rjust",arguments,['self','width'],
1504
['fillchar'],null,null)
1505
for(var attr in $ns){eval('var '+attr+'=$ns[attr]')}
1506
1507
if (width <= self.length) return self
1508
1509
return Array(width - self.length + 1).join(fillchar) + self
1510
}
1511
1512
$StringDict.rpartition = function(self,sep) {
1513
if (sep === undefined) {
1514
throw Error("sep argument is required");
1515
return
1516
}
1517
var pos=self.length-sep.length
1518
while(1){
1519
if(self.substr(pos,sep.length)==sep){
1520
return _b_.tuple([self.substr(0,pos),sep,self.substr(pos+sep.length)])
1521
}else{
1522
pos--
1523
if(pos<0){return _b_.tuple(['','',self])}
1524
}
1525
}
1526
}
1527
1528
$StringDict.rsplit = function(self) {
1529
var args = []
1531
var $ns=$B.$MakeArgs("$StringDict.rsplit",args,[],[],'args','kw')
1532
var sep=None,maxsplit=-1
1533
if($ns['args'].length>=1){sep=$ns['args'][0]}
1534
if($ns['args'].length==2){maxsplit=$ns['args'][1]}
1541
if (array.length <= maxsplit || maxsplit == -1) return array
1542
1543
var s=[]
1544
1545
s = array.splice(array.length - maxsplit, array.length)
1546
s.splice(0, 0, array.join(sep))
1547
1548
return s
1549
}
1550
1551
$StringDict.rstrip = function(self,x){
1552
if(x==undefined){var pattern="\\s*"}
1553
else{var pattern = "["+x+"]*"}
1554
sp = new RegExp(pattern+'$')
1555
return str(self.replace(sp,""))
1556
}
1557
1558
$StringDict.split = function(self){
1559
var args = []
1561
var $ns=$B.$MakeArgs("$StringDict.split",args,[],[],'args','kw')
1562
var sep=None,maxsplit=-1
1563
if($ns['args'].length>=1){sep=$ns['args'][0]}
1564
if($ns['args'].length==2){maxsplit=$ns['args'][1]}
1565
maxsplit = _b_.dict.$dict.get($ns['kw'],'maxsplit',maxsplit)
1567
if(sep===None){
1568
var res = []
1569
var pos = 0
1570
while(pos<self.length&&self.charAt(pos).search(/\s/)>-1){pos++}
1571
if(pos===self.length-1){return []}
1572
var name = ''
1573
while(1){
1574
if(self.charAt(pos).search(/\s/)===-1){
1575
if(name===''){name=self.charAt(pos)}
1576
else{name+=self.charAt(pos)}
1577
}else{
1578
if(name!==''){
1579
res.push(name)
1580
if(maxsplit!==-1&&res.length===maxsplit+1){
1581
res.pop()
1582
res.push(name+self.substr(pos))
1583
return res
1584
}
1585
name=''
1586
}
1587
}
1588
pos++
1589
if(pos>self.length-1){
1590
if(name){res.push(name)}
1591
break
1592
}
1593
}
1594
return res
1595
}else{
1596
var esc_sep = ''
1601
case '.':
1602
case '[':
1603
case ']':
1604
case '(':
1605
case ')':
1606
case '|':
1607
case '$':
1608
case '^':
1609
esc_sep += '\\'
1610
}
1611
esc_sep += sep.charAt(i)
1612
}
1613
var re = new RegExp(esc_sep)
1614
if (maxsplit==-1){
1615
// use native Javascript split on self
1616
return self.valueOf().split(re,maxsplit)
1617
}
1618
1619
// javascript split behavior is different from python when
1620
// a maxsplit argument is supplied. (see javascript string split
1621
// function docs for details)
1622
var l=self.valueOf().split(re,-1)
1625
if (b.length > 0) a.push(b.join(sep))
1626
1627
return a
1628
}
1629
}
1630
1631
$StringDict.splitlines = function(self){return $StringDict.split(self,'\n')}
1632
1633
$StringDict.startswith = function(self){
1634
// Return True if string starts with the prefix, otherwise return False.
1635
// prefix can also be a tuple of prefixes to look for. With optional
1636
// start, test string beginning at that position. With optional end,
1637
// stop comparing string at that position.
1638
var $ns=$B.$MakeArgs("$StringDict.startswith",arguments,['self','prefix'],
1639
['start','end'],null,null)
1640
var prefixes = $ns['prefix']
1641
if(!isinstance(prefixes,_b_.tuple)){prefixes=[prefixes]}
1642
var start = $ns['start'] || 0
1643
var end = $ns['end'] || self.length-1
1644
var s = self.substr(start,end+1)
1645
1647
if (s.indexOf(prefixes[i]) == 0) return true
1648
}
1649
return false
1650
}
1651
1652
$StringDict.strip = function(self,x){
1653
if(x==undefined){x = "\\s"}
1654
return $StringDict.rstrip($StringDict.lstrip(self,x),x)
1655
}
1656
1657
$StringDict.swapcase = function(self) {
1658
//inspired by http://www.geekpedia.com/code69_Swap-string-case-using-JavaScript.html
1659
return self.replace(/([a-z])|([A-Z])/g, function($0,$1,$2)
1660
{ return ($1) ? $0.toUpperCase() : $0.toLowerCase()
1661
})
1662
}
1663
1664
$StringDict.title = function(self) {
1665
//inspired from http://stackoverflow.com/questions/196972/convert-string-to-title-case-with-javascript
1666
return self.replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
1667
}
1668
1669
$StringDict.translate = function(self,table) {
1670
var res = ''
1671
if (isinstance(table, _b_.dict)) {
1673
var repl = _b_.dict.$dict.get(table,self.charCodeAt(i),-1)
1674
if(repl==-1){res += self.charAt(i)}
1675
else if(repl!==None){res += repl}
1676
}
1677
}
1678
return res
1679
}
1680
1681
$StringDict.upper = function(self){return self.toUpperCase()}
1682
1683
$StringDict.zfill = function(self, width) {
1684
if (width === undefined || width <= self.length || !self.isnumeric()) {
1685
return self
1686
}
1687
1688
return Array(width - self.length +1).join('0');
1689
}
1690
1691
function str(arg){
1692
if(arg===undefined) return ''
1693
else if(typeof arg=='number'){return arg.toString()}
1694
else if(typeof arg=='string'){return arg}
1700
// class or its subclasses, but the attribute __str__ of the
1701
// class metaclass (usually "type") or its subclasses (usually
1702
// "object")
1703
// The metaclass is the attribute __class__ of the class dictionary
1704
var func = $B.$type.__getattribute__(arg.$dict.__class__,'__str__')
1709
var f = getattr(arg,'__str__')
1710
// XXX fix : if not better than object.__str__, try __repr__
1711
return f()
1712
}
1713
catch(err){
1719
}catch(err){
1720
$B.$pop_exc()
1721
console.log(err+'\ndefault to toString '+arg);return arg.toString()
1722
}
1723
}
1724
}
1725
str.__class__ = $B.$factory
1726
str.$dict = $StringDict
1727
$StringDict.$factory = str
1728
$StringDict.__new__ = function(cls){
1729
if(cls===undefined){
1730
throw _b_.TypeError('str.__new__(): not enough arguments')
1731
}
1732
return {__class__:cls.$dict}
1733
}
1734
1737
// dictionary and factory for subclasses of string
1738
var $StringSubclassDict = {
1739
__class__:$B.$type,
1740
__name__:'str'
1741
}
1742
1743
// the methods in subclass apply the methods in $StringDict to the
1744
// result of instance.valueOf(), which is a Javascript string
1745
for(var $attr in $StringDict){
1746
if(typeof $StringDict[$attr]=='function'){
1747
$StringSubclassDict[$attr]=(function(attr){
1748
return function(){
1749
var args = []
1750
if(arguments.length>0){
1751
var args = [arguments[0].valueOf()]
1753
args.push(arguments[i])
1754
}
1755
}
1756
return $StringDict[attr].apply(null,args)
1757
}
1758
})($attr)
1759
}
1760
}
1761
$StringSubclassDict.__mro__ = [$StringSubclassDict,$ObjectDict]
1762
1763
// factory for str subclasses
1764
$B.$StringSubclassFactory = {
1765
__class__:$B.$factory,
1766
$dict:$StringSubclassDict
1767
}
1768
1769
_b_.str = str
1770
1771
})(__BRYTHON__)