diff --git a/src/stringobj.c b/src/stringobj.c index c59e3e1879..613ec399ae 100644 --- a/src/stringobj.c +++ b/src/stringobj.c @@ -198,17 +198,17 @@ void LoadChar( Obj c ) /**************************************************************************** ** -*F FuncEmptyString( , ) . . . . . . . empty string with space -* -* Returns an empty string, but with space for len characters preallocated. -* +*F FuncEmptyString( , ) . . . . . . . . empty string with space +** +** Returns an empty string, but with space for len characters preallocated. +** */ Obj FuncEmptyString( Obj self, Obj len ) { Obj new; - while ( ! IS_INTOBJ(len) ) { + while ( ! IS_NONNEG_INTOBJ(len) ) { len = ErrorReturnObj( - " must be an integer (not a %s)", + " must be an non-negative integer (not a %s)", (Int)TNAM_OBJ(len), 0L, "you can replace via 'return ;'" ); } @@ -220,11 +220,11 @@ Obj FuncEmptyString( Obj self, Obj len ) /**************************************************************************** ** -*F FuncShrinkAllocationString( , ) . . give back unneeded memory -* -* Shrinks the bag of to minimal possible size (possibly converts to -* compact representation). -* +*F FuncShrinkAllocationString( , ) . . give back unneeded memory +** +** Shrinks the bag of to minimal possible size (possibly converts to +** compact representation). +** */ Obj FuncShrinkAllocationString( Obj self, Obj str ) { @@ -406,19 +406,22 @@ Obj FuncSTRING_SINTLIST ( * integers ? */ /* general code */ - if (! IS_RANGE(val) ) { - if (! IS_PLIST(val)) { + while (!IS_RANGE(val) && !IS_PLIST(val)) { +again: val = ErrorReturnObj( - " must be a plain list or range, not a %s)", + " must be a plain list of small integers or a range, not a %s", (Int)TNAM_OBJ(val), 0L, "you can replace via 'return ;'" ); - } - + } + if (! IS_RANGE(val) ) { l=LEN_PLIST(val); n=NEW_STRING(l); p=CHARS_STRING(n); for (i=1;i<=l;i++) { - *p++=CHAR_SINT(INT_INTOBJ(ELM_PLIST(val,i))); + Obj x = ELM_PLIST(val,i); + if (!IS_INTOBJ(x)) + goto again; + *p++=CHAR_SINT(INT_INTOBJ(x)); } } else { @@ -434,7 +437,6 @@ Obj FuncSTRING_SINTLIST ( } - CHANGED_BAG(n); return n; } @@ -464,12 +466,10 @@ Obj FuncREVNEG_STRING ( q=CHARS_STRING(n); j=l-1; for (i=1;i<=l;i++) { - /* *q++=CHAR_SINT(-SINT_CHAR(p[j])); */ *q++=-p[j]; j--; } - CHANGED_BAG(n); return n; } @@ -1084,8 +1084,6 @@ void AssString ( /* now perform the assignment and return the assigned value */ SET_ELM_STRING( list, pos, val ); - /* CHARS_STRING(list)[pos-1] = CHAR_VALUE(val); */ - CHANGED_BAG( list ); } } @@ -1377,7 +1375,6 @@ void ConvString ( ResizeBag( string, SIZEBAG_STRINGLEN(lenString) ); /* copy data area from tmp */ memcpy(ADDR_OBJ(string), CONST_ADDR_OBJ(tmp), SIZE_OBJ(tmp)); - CHANGED_BAG(string); } @@ -1431,17 +1428,6 @@ Obj MakeString2(const Char *cstr1, const Char *cstr2) return result; } -Obj MakeString3(const Char *cstr1, const Char *cstr2, const Char *cstr3) -{ - Obj result; - size_t len1 = strlen(cstr1), len2 = strlen(cstr2), len3 = strlen(cstr3); - result = NEW_STRING(len1 + len2 + len3); - memcpy(CSTR_STRING(result), cstr1, len1); - memcpy(CSTR_STRING(result)+len1, cstr2, len2); - memcpy(CSTR_STRING(result)+len1+len2, cstr3, len3); - return result; -} - Obj MakeImmString2(const Char *cstr1, const Char *cstr2) { Obj result = MakeString2(cstr1, cstr2); @@ -1449,13 +1435,6 @@ Obj MakeImmString2(const Char *cstr1, const Char *cstr2) return result; } -Obj MakeImmString3(const Char *cstr1, const Char *cstr2, const Char *cstr3) -{ - Obj result = MakeString3(cstr1, cstr2, cstr3); - MakeImmutableString(result); - return result; -} - Obj ConvImmString(Obj str) { Obj result; @@ -1511,12 +1490,11 @@ Obj FuncCONV_STRING ( Obj string ) { /* check whether is a string */ - if ( ! IS_STRING( string ) ) { + while ( ! IS_STRING( string ) ) { string = ErrorReturnObj( "ConvString: must be a string (not a %s)", (Int)TNAM_OBJ(string), 0L, "you can replace via 'return ;'" ); - return FuncCONV_STRING( self, string ); } /* convert to the string representation */ @@ -1549,12 +1527,11 @@ Obj FuncCOPY_TO_STRING_REP ( Obj obj ) { /* check whether is a string */ - if (!IS_STRING(obj)) { + while (!IS_STRING(obj)) { obj = ErrorReturnObj( - "ConvString: must be a string (not a %s)", + "CopyToStringRep: must be a string (not a %s)", (Int)TNAM_OBJ(obj), 0L, "you can replace via 'return ;'" ); - return FuncCOPY_TO_STRING_REP( self, obj ); } return CopyToStringRep(obj); } @@ -1645,12 +1622,11 @@ Obj FuncNormalizeWhitespace ( Int i, j, len, white; /* check whether is a string */ - if ( ! IsStringConv( string ) ) { + while ( ! IsStringConv( string ) ) { string = ErrorReturnObj( "NormalizeWhitespace: must be a string (not a %s)", (Int)TNAM_OBJ(string), 0L, "you can replace via 'return ;'" ); - return FuncNormalizeWhitespace( self, string ); } len = GET_LEN_STRING(string); @@ -1701,21 +1677,19 @@ Obj FuncREMOVE_CHARACTERS ( UInt1 REMCHARLIST[256] = {0}; /* check whether is a string */ - if ( ! IsStringConv( string ) ) { + while ( ! IsStringConv( string ) ) { string = ErrorReturnObj( "RemoveCharacters: first argument must be a string (not a %s)", (Int)TNAM_OBJ(string), 0L, "you can replace via 'return ;'" ); - return FuncREMOVE_CHARACTERS( self, string, rem ); } /* check whether is a string */ - if ( ! IsStringConv( rem ) ) { + while ( ! IsStringConv( rem ) ) { rem = ErrorReturnObj( "RemoveCharacters: second argument must be a string (not a %s)", (Int)TNAM_OBJ(rem), 0L, "you can replace via 'return ;'" ); - return FuncREMOVE_CHARACTERS( self, string, rem ); } /* set REMCHARLIST by setting positions of characters in rem to 1 */ @@ -1757,32 +1731,28 @@ Obj FuncTranslateString ( Int j, len; /* check whether is a string */ - if ( ! IsStringConv( string ) ) { + while ( ! IsStringConv( string ) ) { string = ErrorReturnObj( - "RemoveCharacters: first argument must be a string (not a %s)", + "TranslateString: first argument must be a string (not a %s)", (Int)TNAM_OBJ(string), 0L, "you can replace via 'return ;'" ); - return FuncTranslateString( self, string, trans ); } - /* check whether is a string */ - if ( ! IsStringConv( trans ) ) { - trans = ErrorReturnObj( - "RemoveCharacters: second argument must be a string (not a %s)", - (Int)TNAM_OBJ(trans), 0L, - "you can replace via 'return ;'" ); - return FuncTranslateString( self, string, trans ); - } - - /* check if string has length at least 256 */ - if ( GET_LEN_STRING( trans ) < 256 ) { - trans = ErrorReturnObj( - "RemoveCharacters: second argument must have length >= 256", - 0L, 0L, - "you can replace via 'return ;'" ); - return FuncTranslateString( self, string, trans ); + // check whether is a string of length at least 256 + while ( ! IsStringConv( trans ) || GET_LEN_STRING( trans ) < 256 ) { + if ( ! IsStringConv( trans ) ) { + trans = ErrorReturnObj( + "TranslateString: second argument must be a string (not a %s)", + (Int)TNAM_OBJ(trans), 0L, + "you can replace via 'return ;'" ); + } else if ( GET_LEN_STRING( trans ) < 256 ) { + trans = ErrorReturnObj( + "TranslateString: second argument must have length >= 256", + 0L, 0L, + "you can replace via 'return ;'" ); + } } - + /* now change string in place */ len = GET_LEN_STRING(string); s = CHARS_STRING(string); @@ -1816,30 +1786,27 @@ Obj FuncSplitStringInternal ( UInt1 SPLITSTRINGWSPACE[256] = { 0 }; /* check whether is a string */ - if ( ! IsStringConv( string ) ) { + while ( ! IsStringConv( string ) ) { string = ErrorReturnObj( "SplitString: first argument must be a string (not a %s)", (Int)TNAM_OBJ(string), 0L, "you can replace via 'return ;'" ); - return FuncSplitStringInternal( self, string, seps, wspace ); } /* check whether is a string */ - if ( ! IsStringConv( seps ) ) { + while ( ! IsStringConv( seps ) ) { seps = ErrorReturnObj( "SplitString: second argument must be a string (not a %s)", (Int)TNAM_OBJ(seps), 0L, "you can replace via 'return ;'" ); - return FuncSplitStringInternal( self, string, seps, wspace ); } /* check whether is a string */ - if ( ! IsStringConv( wspace ) ) { + while ( ! IsStringConv( wspace ) ) { wspace = ErrorReturnObj( "SplitString: third argument must be a string (not a %s)", (Int)TNAM_OBJ(wspace), 0L, "you can replace via 'return ;'" ); - return FuncSplitStringInternal( self, string, seps, wspace ); } /* set SPLITSTRINGSEPS by setting positions of characters in rem to 1 */ diff --git a/src/stringobj.h b/src/stringobj.h index b511226fc4..4a04ee8462 100644 --- a/src/stringobj.h +++ b/src/stringobj.h @@ -367,10 +367,8 @@ static inline Obj MakeImmString(const Char * cstr) Obj MakeString2(const Char *cstr1, const Char *cstr2); -Obj MakeString3(const Char *cstr1, const Char *cstr2, const Char *cstr3); Obj MakeImmString2(const Char *cstr1, const Char *cstr2); -Obj MakeImmString3(const Char *cstr1, const Char *cstr2, const Char *cstr3); Obj ConvImmString(Obj str); diff --git a/tst/testinstall/kernel/streams.tst b/tst/testinstall/kernel/streams.tst index 5d634e398e..baa322d8e8 100644 --- a/tst/testinstall/kernel/streams.tst +++ b/tst/testinstall/kernel/streams.tst @@ -66,6 +66,12 @@ gap> INPUT_TEXT_FILE(fail); Error, must be a string (not a boolean or fail) gap> IS_END_OF_FILE(fail); Error, must be an integer (not a boolean or fail) +gap> IS_END_OF_FILE(-1); +fail +gap> IS_END_OF_FILE(0); +false +gap> IS_END_OF_FILE(254); +fail gap> OUTPUT_TEXT_FILE(fail, fail); Error, must be a string (not a boolean or fail) gap> OUTPUT_TEXT_FILE("test", fail); @@ -74,8 +80,20 @@ Error, must be a boolean (not a boolean or fail) # gap> POSITION_FILE(fail); Error, must be an integer (not a boolean or fail) +gap> POSITION_FILE(-1); +fail +gap> IsInt(POSITION_FILE(4)); +true +gap> POSITION_FILE(254); +fail + +# gap> READ_BYTE_FILE(fail); Error, must be an integer (not a boolean or fail) +gap> READ_BYTE_FILE(-1); +fail + +# gap> READ_LINE_FILE(fail); Error, must be an integer (not a boolean or fail) gap> READ_ALL_FILE(fail,fail); @@ -86,10 +104,20 @@ gap> SEEK_POSITION_FILE(fail,fail); Error, must be an integer (not a boolean or fail) gap> SEEK_POSITION_FILE(1,fail); Error, must be an integer (not a boolean or fail) + +# gap> WRITE_BYTE_FILE(fail,fail); Error, must be an integer (not a boolean or fail) gap> WRITE_BYTE_FILE(1,fail); Error, must be an integer (not a boolean or fail) +gap> WRITE_BYTE_FILE(-1,65); +fail +gap> WRITE_BYTE_FILE(0,65); +true +gap> WRITE_BYTE_FILE(254,65); +fail + +# gap> READ_STRING_FILE(fail); Error, must be an integer (not a boolean or fail) diff --git a/tst/testinstall/kernel/stringobj.tst b/tst/testinstall/kernel/stringobj.tst new file mode 100644 index 0000000000..b27bf85803 --- /dev/null +++ b/tst/testinstall/kernel/stringobj.tst @@ -0,0 +1,126 @@ +# +# Tests for functions defined in src/strinobj.c +# +gap> START_TEST("kernel/strinobj.tst"); + +# +gap> s := EmptyString(2); +"" +gap> EmptyString(-1); +Error, must be an non-negative integer (not a integer) + +# +gap> ShrinkAllocationString(s); +gap> ShrinkAllocationString(1); +Error, must be a string, not a integer) + +# +gap> CHAR_INT(fail); +Error, must be an integer (not a boolean or fail) +gap> CHAR_INT(-1); +Error, must be an integer between 0 and 255 +gap> CHAR_INT(65); +'A' + +# +gap> INT_CHAR(1); +Error, must be a character (not a integer) +gap> INT_CHAR('A'); +65 + +# +gap> CHAR_SINT(fail); +Error, must be an integer (not a boolean or fail) +gap> CHAR_SINT(255); +Error, must be an integer between -128 and 127 +gap> CHAR_SINT(65); +'A' + +# +gap> SINT_CHAR(1); +Error, must be a character (not a integer) +gap> SINT_CHAR('A'); +65 + +# +gap> INTLIST_STRING("ABC", 1); +[ 65, 66, 67 ] +gap> INTLIST_STRING("ABC", -1); +[ 65, 66, 67 ] +gap> INTLIST_STRING(1, -1); +Error, must be a string, not a integer) + +# +gap> SINTLIST_STRING("ABC"); +[ 65, 66, 67 ] +gap> SINTLIST_STRING(1); +Error, must be a string, not a integer) + +# +gap> STRING_SINTLIST([ 65, 66, 67 ]); +"ABC" +gap> STRING_SINTLIST([ 65 .. 67 ]); +"ABC" +gap> STRING_SINTLIST(1); +Error, must be a plain list of small integers or a range, not a integer +gap> STRING_SINTLIST([ 'B' ]); +Error, must be a plain list of small integers or a range, not a list (pl\ +ain,hom) + +# +gap> REVNEG_STRING(1); +Error, must be a string, not a integer) + +# +gap> CONV_STRING(1); +Error, ConvString: must be a string (not a integer) + +# +gap> COPY_TO_STRING_REP(1); +Error, CopyToStringRep: must be a string (not a integer) + +# +gap> POSITION_SUBSTRING("abc","x",0); +fail +gap> POSITION_SUBSTRING("abc","b",0); +2 +gap> POSITION_SUBSTRING("abc","b",3); +fail +gap> POSITION_SUBSTRING(1,2,3); +Error, POSITION_SUBSTRING: must be a string (not a integer) +gap> POSITION_SUBSTRING("abc",2,3); +Error, POSITION_SUBSTRING: must be a string (not a integer) +gap> POSITION_SUBSTRING("abc","b",-1); +Error, POSITION_SUBSTRING: must be a non-negative integer (not a integer\ +) + +# +gap> s:=" abc\n xyz\n";; NormalizeWhitespace(s); s; +"abc xyz" +gap> NormalizeWhitespace(1); +Error, NormalizeWhitespace: must be a string (not a integer) + +# +gap> s:="abcdabcd";; REMOVE_CHARACTERS(s, "db"); s; +"acac" +gap> REMOVE_CHARACTERS(1,1); +Error, RemoveCharacters: first argument must be a string (not a integ\ +er) +gap> REMOVE_CHARACTERS(s,1); +Error, RemoveCharacters: second argument must be a string (not a integer\ +) + +# +gap> s:="abc";; TranslateString(s,UPPERCASETRANSTABLE); s; +"ABC" +gap> TranslateString(1,1); +Error, TranslateString: first argument must be a string (not a intege\ +r) +gap> TranslateString("abc",1); +Error, TranslateString: second argument must be a string (not a intege\ +r) +gap> TranslateString("abc","def"); +Error, TranslateString: second argument must have length >= 256 + +# +gap> STOP_TEST("kernel/strinobj.tst", 1);