Skip to content
This repository was archived by the owner on Mar 23, 2023. It is now read-only.

Commit d8cb498

Browse files
corona10trotterdylan
authored andcommitted
[Runtime] Implementation of str.isspace(), isupper(), islower(), istitle() (#245)
1 parent d223a81 commit d8cb498

2 files changed

Lines changed: 137 additions & 7 deletions

File tree

runtime/str.go

Lines changed: 114 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,92 @@ func strIsDigit(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
383383
return True.ToObject(), nil
384384
}
385385

386+
func strIsLower(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
387+
if raised := checkMethodArgs(f, "islower", args, StrType); raised != nil {
388+
return nil, raised
389+
}
390+
s := toStrUnsafe(args[0]).Value()
391+
if len(s) == 0 {
392+
return False.ToObject(), nil
393+
}
394+
for i := range s {
395+
if !isLower(s[i]) {
396+
return False.ToObject(), nil
397+
}
398+
}
399+
return True.ToObject(), nil
400+
}
401+
402+
func strIsSpace(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
403+
if raised := checkMethodArgs(f, "isspace", args, StrType); raised != nil {
404+
return nil, raised
405+
}
406+
s := toStrUnsafe(args[0]).Value()
407+
if len(s) == 0 {
408+
return False.ToObject(), nil
409+
}
410+
for i := range s {
411+
if !isSpace(s[i]) {
412+
return False.ToObject(), nil
413+
}
414+
}
415+
return True.ToObject(), nil
416+
}
417+
418+
func strIsTitle(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
419+
if raised := checkMethodArgs(f, "istitle", args, StrType); raised != nil {
420+
return nil, raised
421+
}
422+
423+
s := toStrUnsafe(args[0]).Value()
424+
if len(s) == 0 {
425+
return False.ToObject(), nil
426+
}
427+
428+
if len(s) == 1 {
429+
return GetBool(isUpper(s[0])).ToObject(), nil
430+
}
431+
432+
cased := false
433+
previousIsCased := false
434+
435+
for i := range s {
436+
if isUpper(s[i]) {
437+
if previousIsCased {
438+
return False.ToObject(), nil
439+
}
440+
previousIsCased = true
441+
cased = true
442+
} else if isLower(s[i]) {
443+
if !previousIsCased {
444+
return False.ToObject(), nil
445+
}
446+
previousIsCased = true
447+
cased = true
448+
} else {
449+
previousIsCased = false
450+
}
451+
}
452+
453+
return GetBool(cased).ToObject(), nil
454+
}
455+
456+
func strIsUpper(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
457+
if raised := checkMethodArgs(f, "isupper", args, StrType); raised != nil {
458+
return nil, raised
459+
}
460+
s := toStrUnsafe(args[0]).Value()
461+
if len(s) == 0 {
462+
return False.ToObject(), nil
463+
}
464+
for i := range s {
465+
if !isUpper(s[i]) {
466+
return False.ToObject(), nil
467+
}
468+
}
469+
return True.ToObject(), nil
470+
}
471+
386472
func strJoin(f *Frame, args Args, _ KWArgs) (*Object, *BaseException) {
387473
if raised := checkMethodArgs(f, "join", args, StrType, ObjectType); raised != nil {
388474
return nil, raised
@@ -807,9 +893,9 @@ func strSwapCase(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
807893
}
808894
b := make([]byte, numBytes)
809895
for i := 0; i < numBytes; i++ {
810-
if s[i] >= 'a' && s[i] <= 'z' {
896+
if isLower(s[i]) {
811897
b[i] = toUpper(s[i])
812-
} else if s[i] >= 'A' && s[i] <= 'Z' {
898+
} else if isUpper(s[i]) {
813899
b[i] = toLower(s[i])
814900
} else {
815901
b[i] = s[i]
@@ -828,6 +914,10 @@ func initStrType(dict map[string]*Object) {
828914
dict["isalnum"] = newBuiltinFunction("isalnum", strIsAlNum).ToObject()
829915
dict["isalpha"] = newBuiltinFunction("isalpha", strIsAlpha).ToObject()
830916
dict["isdigit"] = newBuiltinFunction("isdigit", strIsDigit).ToObject()
917+
dict["islower"] = newBuiltinFunction("islower", strIsLower).ToObject()
918+
dict["isspace"] = newBuiltinFunction("isspace", strIsSpace).ToObject()
919+
dict["istitle"] = newBuiltinFunction("istitle", strIsTitle).ToObject()
920+
dict["isupper"] = newBuiltinFunction("isupper", strIsUpper).ToObject()
831921
dict["join"] = newBuiltinFunction("join", strJoin).ToObject()
832922
dict["lower"] = newBuiltinFunction("lower", strLower).ToObject()
833923
dict["lstrip"] = newBuiltinFunction("lstrip", strLStrip).ToObject()
@@ -1119,12 +1209,12 @@ func strTitle(f *Frame, args Args, kwargs KWArgs) (*Object, *BaseException) {
11191209
for i := 0; i < numBytes; i++ {
11201210
c := s[i]
11211211
switch {
1122-
case s[i] >= 'a' && s[i] <= 'z':
1212+
case isLower(c):
11231213
if !previousIsCased {
11241214
c = toUpper(c)
11251215
}
11261216
previousIsCased = true
1127-
case s[i] >= 'A' && s[i] <= 'Z':
1217+
case isUpper(c):
11281218
if previousIsCased {
11291219
c = toLower(c)
11301220
}
@@ -1174,14 +1264,14 @@ func init() {
11741264
}
11751265

11761266
func toLower(b byte) byte {
1177-
if b >= 'A' && b <= 'Z' {
1267+
if isUpper(b) {
11781268
return b + caseOffset
11791269
}
11801270
return b
11811271
}
11821272

11831273
func toUpper(b byte) byte {
1184-
if b >= 'a' && b <= 'z' {
1274+
if isLower(b) {
11851275
return b - caseOffset
11861276
}
11871277
return b
@@ -1192,13 +1282,30 @@ func isAlNum(c byte) bool {
11921282
}
11931283

11941284
func isAlpha(c byte) bool {
1195-
return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
1285+
return isUpper(c) || isLower(c)
11961286
}
11971287

11981288
func isDigit(c byte) bool {
11991289
return '0' <= c && c <= '9'
12001290
}
12011291

1292+
func isLower(c byte) bool {
1293+
return 'a' <= c && c <= 'z'
1294+
}
1295+
1296+
func isSpace(c byte) bool {
1297+
switch c {
1298+
case ' ', '\n', '\t', '\v', '\f', '\r':
1299+
return true
1300+
default:
1301+
return false
1302+
}
1303+
}
1304+
1305+
func isUpper(c byte) bool {
1306+
return 'A' <= c && c <= 'Z'
1307+
}
1308+
12021309
// strLeftPad returns s padded with fillchar so that its length is at least width.
12031310
// Fillchar must be a single character. When fillchar is "0", s starting with a
12041311
// sign are handled correctly.

runtime/str_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,29 @@ func TestStrMethods(t *testing.T) {
371371
{"isdigit", wrapArgs(""), False.ToObject(), nil},
372372
{"isdigit", wrapArgs("abc#123"), False.ToObject(), nil},
373373
{"isdigit", wrapArgs("123", "456"), nil, mustCreateException(TypeErrorType, "'isdigit' of 'str' requires 1 arguments")},
374+
{"islower", wrapArgs("abc"), True.ToObject(), nil},
375+
{"islower", wrapArgs("ABC"), False.ToObject(), nil},
376+
{"islower", wrapArgs(""), False.ToObject(), nil},
377+
{"islower", wrapArgs("abc#123"), False.ToObject(), nil},
378+
{"islower", wrapArgs("123", "456"), nil, mustCreateException(TypeErrorType, "'islower' of 'str' requires 1 arguments")},
379+
{"isupper", wrapArgs("abc"), False.ToObject(), nil},
380+
{"isupper", wrapArgs("ABC"), True.ToObject(), nil},
381+
{"isupper", wrapArgs(""), False.ToObject(), nil},
382+
{"isupper", wrapArgs("abc#123"), False.ToObject(), nil},
383+
{"isupper", wrapArgs("123", "456"), nil, mustCreateException(TypeErrorType, "'isupper' of 'str' requires 1 arguments")},
384+
{"isspace", wrapArgs(""), False.ToObject(), nil},
385+
{"isspace", wrapArgs(" "), True.ToObject(), nil},
386+
{"isspace", wrapArgs("\n\t\v\f\r "), True.ToObject(), nil},
387+
{"isspace", wrapArgs(""), False.ToObject(), nil},
388+
{"isspace", wrapArgs("asdad"), False.ToObject(), nil},
389+
{"isspace", wrapArgs(" "), True.ToObject(), nil},
390+
{"isspace", wrapArgs(" ", "456"), nil, mustCreateException(TypeErrorType, "'isspace' of 'str' requires 1 arguments")},
391+
{"istitle", wrapArgs("abc"), False.ToObject(), nil},
392+
{"istitle", wrapArgs("Abc&D"), True.ToObject(), nil},
393+
{"istitle", wrapArgs("ABc&D"), False.ToObject(), nil},
394+
{"istitle", wrapArgs(""), False.ToObject(), nil},
395+
{"istitle", wrapArgs("abc#123"), False.ToObject(), nil},
396+
{"istitle", wrapArgs("ABc&D", "456"), nil, mustCreateException(TypeErrorType, "'istitle' of 'str' requires 1 arguments")},
374397
{"join", wrapArgs(",", newTestList("foo", "bar")), NewStr("foo,bar").ToObject(), nil},
375398
{"join", wrapArgs(":", newTestList("foo", "bar", NewUnicode("baz"))), NewUnicode("foo:bar:baz").ToObject(), nil},
376399
{"join", wrapArgs("nope", NewTuple()), NewStr("").ToObject(), nil},

0 commit comments

Comments
 (0)