Skip to content

Commit 0ca2d4b

Browse files
authored
Update read_string_from_file to not include line feed (#288)
* Update read_string_from_file to not include line feed * fixup! Update read_string_from_file to not include line feed
1 parent 2201b99 commit 0ca2d4b

File tree

3 files changed

+132
-244
lines changed

3 files changed

+132
-244
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
- forbidden scripts from accessing and changing any files outside game root or game settings directory
3030
- file related opcodes moved from CLEO core into separated plugin
3131
- opcode **0A9E ([write_to_file](https://library.sannybuilder.com/#/sa/file/0A9E))** now supports literal numbers and strings
32+
- opcode **0AD7 ([read_string_from_file](https://library.sannybuilder.com/#/sa/file/0AD7))** no longer includes new line character(s) at end of read string
3233
- fixed bug causing file stream opcodes not working correctly when read-write modes are used
3334
- fixed buffer overflows in file stream read opcodes
3435
- added/fixed support of all file stream opcodes in legacy mode (Cleo3)

cleo_plugins/FileSystemOperations/FileSystemOperations.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,22 @@ class FileSystemOperations
329329
// use caller's size argument, ignoring actual target type size. Intended for legacy reasons.
330330
bool ok = File::readString(handle, result.data, size) != nullptr;
331331

332+
// remove line ending characters if present
333+
if (ok && !IsLegacyScript(thread))
334+
{
335+
auto last = (int)strlen(result.data) - 1;
336+
while (last >= 0)
337+
{
338+
if (result.data[last] != '\n' && result.data[last] != '\r')
339+
{
340+
break;
341+
}
342+
343+
result.data[last] = '\0';
344+
last--;
345+
}
346+
}
347+
332348
OPCODE_CONDITION_RESULT(ok);
333349
return OR_CONTINUE;
334350
}
Lines changed: 115 additions & 244 deletions
Original file line numberDiff line numberDiff line change
@@ -1,252 +1,123 @@
11
{$CLEO .s}
2-
{$USE debug}
3-
{$USE file}
4-
{$USE bitwise}
5-
var 0@ : Integer
6-
var 1@ : Integer
7-
var 2@ : Integer
8-
var 3@ : Integer
9-
var 4@ : Integer
10-
var 5@ : Integer
11-
var 6@ : Integer
12-
var 7@ : Integer
13-
var 8@ : Integer
14-
var 9@ : Integer
15-
var 10@ : Integer
16-
17-
goto @DATA_END
2+
goto @TEST_DATA_END
183
hex
19-
"t1" 0A "t2" 0D 0A "t3" 09 "e s" 0A "very long test no.4" 0A "even longer test string to read number 5" 0A
20-
end
21-
:DATA_END
22-
23-
24-
script_name "0AD7" // read_string_from_file
25-
debug_on
26-
trace "0AD7 (read_string_from_file)"
27-
28-
29-
// open the file
30-
wait 0
31-
if
32-
0@ = open_file ".\0AD7.s" {mode} "r"
33-
then
34-
trace "~g~~h~~h~0AD7 (read_string_from_file), #0 PASSED"
35-
else
36-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #0 FAILED! Failed to open file."
4+
"1234567890ABCDEF1234567890ABCDE" 00 // data A - 32 characters
5+
"123" 0A // data B
6+
"12" 0D 0A // data C
7+
"1234" // padding
378
end
9+
:TEST_DATA_END
10+
const Test_Data_Offset_A = 7 // skip goto + target
11+
const Test_Data_Offset_B = 39
12+
const Test_Data_Offset_C = 43
3813

14+
{$INCLUDE_ONCE ../cleo_tester.inc}
3915

40-
// seek file to hex data block
41-
wait 0
42-
file_seek 0@ {offset} 7 {origin} SeekOrigin.Begin
43-
trace "~g~~h~~h~0AD7 (read_string_from_file), #1 PASSED"
44-
45-
46-
// read 0
47-
wait 0
48-
1@ = 0xcccccccc
49-
2@ = 0xcccccccc
50-
3@ = 0xcccccccc
51-
if
52-
0AD7: read_string_from_file 0@ {store_to} 2@s {max_lenght} 0 // tested opcode
53-
then
54-
trace "~g~~h~~h~0AD7 (read_string_from_file), #2 PASSED"
55-
else
56-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #2 FAILED! Condition result: FALSE"
57-
end
58-
if and
59-
1@ == 0xcccccccc
60-
2@ == 0xcccccccc
61-
3@ == 0xcccccccc
62-
then
63-
trace "~g~~h~~h~0AD7 (read_string_from_file), #3 PASSED"
64-
else
65-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #3 FAILED!~n~%08x %08x %08x Expected~n~%08x %08x %08x Occured" 0xcccccccc 0xcccccccc 0xcccccccc 1@ 2@ 3@
66-
end
67-
68-
69-
// read 1
70-
wait 0
71-
1@ = 0xcccccccc
72-
2@ = 0xcccccccc
73-
3@ = 0xcccccccc
74-
4@ = 0xcccccccc
75-
if
76-
0AD7: read_string_from_file 0@ {store_to} 2@s {max_lenght} 1 // tested opcode
77-
then
78-
trace "~g~~h~~h~0AD7 (read_string_from_file), #4 PASSED"
79-
else
80-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #4 FAILED! Condition result: FALSE"
81-
end
82-
if and
83-
1@ == 0xcccccccc
84-
2@s == ''
85-
4@ == 0xcccccccc
86-
then
87-
trace "~g~~h~~h~0AD7 (read_string_from_file), #5 PASSED"
88-
else
89-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #5 FAILED!~n~%08x '%s' %08x Expected~n~%08x '%s' %08x Occured" 0xcccccccc '' 0xcccccccc 1@ 2@s 4@
90-
end
91-
92-
93-
// read ended by new line
94-
wait 0
95-
1@ = 0xcccccccc
96-
2@ = 0xcccccccc
97-
3@ = 0xcccccccc
98-
4@ = 0xcccccccc
99-
if
100-
0AD7: read_string_from_file 0@ {store_to} 2@s {max_lenght} 8 // tested opcode
101-
then
102-
trace "~g~~h~~h~0AD7 (read_string_from_file), #6 PASSED"
103-
else
104-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #6 FAILED! Condition result: FALSE"
105-
end
106-
string_format 6@s {format} "t1%c" {args} 0x0A // ended with new line
107-
if and
108-
1@ == 0xcccccccc
109-
2@s == 6@s
110-
4@ == 0xcccccccc
111-
then
112-
trace "~g~~h~~h~0AD7 (read_string_from_file), #7 PASSED"
113-
else
114-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #7 FAILED!~n~%08x '%s' %08x %08x Expected~n~%08x '%s' %08x %08x Occured" 0xcccccccc 6@s 0xcccccccc 1@ 2@s 4@
115-
end
116-
117-
118-
// read ended by new line (Windows)
119-
wait 0
120-
1@ = 0xcccccccc
121-
2@ = 0xcccccccc
122-
3@ = 0xcccccccc
123-
4@ = 0xcccccccc
124-
if
125-
0AD7: read_string_from_file 0@ {store_to} 2@s {max_lenght} 8 // tested opcode
126-
then
127-
trace "~g~~h~~h~0AD7 (read_string_from_file), #8 PASSED"
128-
else
129-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #8 FAILED! Condition result: FALSE"
130-
end
131-
string_format 6@s {format} "t2%c%c" {args} 0x0D 0x0A // ended with new line
132-
if and
133-
1@ == 0xcccccccc
134-
2@s == 6@s
135-
4@ == 0xcccccccc
136-
then
137-
trace "~g~~h~~h~0AD7 (read_string_from_file), #9 PASSED"
138-
else
139-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #9 FAILED!~n~%08x '%s' %08x Expected~n~%08x '%s' %08x Occured" 0xcccccccc 6@s 0xcccccccc 1@ 2@s 4@
140-
end
141-
142-
143-
// read not splited by tab or space
144-
wait 0
145-
1@ = 0xcccccccc
146-
2@ = 0xcccccccc
147-
3@ = 0xcccccccc
148-
4@ = 0xcccccccc
149-
if
150-
0AD7: read_string_from_file 0@ {store_to} 2@s {max_lenght} 8 // tested opcode
151-
then
152-
trace "~g~~h~~h~0AD7 (read_string_from_file), #10 PASSED"
153-
else
154-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #10 FAILED! Condition result: FALSE"
155-
end
156-
string_format 6@s {format} "t3%ce s%c" {args} 0x09 0x0A
157-
if and
158-
1@ == 0xcccccccc
159-
2@s == 6@s
160-
4@ == 0xcccccccc
161-
then
162-
trace "~g~~h~~h~0AD7 (read_string_from_file), #11 PASSED"
163-
else
164-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #11 FAILED!~n~%08x '%s' %08x Expected~n~%08x '%s' %08x Occured" 0xcccccccc 6@s 0xcccccccc 1@ 2@s 4@
165-
end
166-
167-
168-
// read longer than longString variable (expect overflow)
169-
wait 0
170-
1@ = 0xcccccccc
171-
2@ = 0xcccccccc
172-
3@ = 0xcccccccc
173-
4@ = 0xcccccccc
174-
5@ = 0xcccccccc
175-
6@ = 0xcccccccc
176-
7@ = 0xcccccccc
177-
8@ = 0xcccccccc
178-
if
179-
0AD7: read_string_from_file 0@ {store_to} 2@s {max_lenght} 32 // tested opcode
180-
then
181-
trace "~g~~h~~h~0AD7 (read_string_from_file), #12 PASSED"
182-
else
183-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #12 FAILED! Condition result: FALSE"
184-
end
185-
9@ = allocate_memory 64
186-
string_format 9@ {format} "very long test no.4%c" {args} 0x0A
187-
10@ = get_var_pointer 2@
188-
if and
189-
1@ == 0xcccccccc
190-
is_memory_equal 9@ 10@ {size} 21 // including terminator
191-
8@ == 0xcccccccc
192-
then
193-
trace "~g~~h~~h~0AD7 (read_string_from_file), #13 PASSED"
194-
else
195-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #13 FAILED!~n~%08x '%s' %08x Expected~n~%08x '%s' %08x Occured" 0xcccccccc 9@ 0xcccccccc 1@ 10@ 8@
196-
end
197-
free_memory 9@
198-
199-
200-
// read limited by max_lenght param
201-
wait 0
202-
1@ = 0xcccccccc
203-
2@ = 0xcccccccc
204-
3@ = 0xcccccccc
205-
if
206-
0AD7: read_string_from_file 0@ {store_to} 2@s {max_lenght} 4 // tested opcode
207-
then
208-
trace "~g~~h~~h~0AD7 (read_string_from_file), #14 PASSED"
209-
else
210-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #14 FAILED! Condition result: FALSE"
211-
end
212-
if and
213-
1@ == 0xcccccccc
214-
2@ == 0x00657665 // "eve\0"
215-
3@ == 0xcccccccc
216-
then
217-
trace "~g~~h~~h~0AD7 (read_string_from_file), #15 PASSED"
218-
else
219-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #15 FAILED!~n~%08x %08x %08x Expected~n~%08x %08x %08x Occured" 0xcccccccc 0x00657665 0xcccccccc 1@ 2@ 3@
220-
end
16+
script_name "0AD7"
17+
test("0AD7 (read_string_from_file)", tests)
18+
terminate_this_custom_script
22119

22220

223-
// read into memory address
224-
wait 0
225-
1@ = allocate_memory 64
226-
if
227-
0AD7: read_string_from_file 0@ {store_to} 1@ {max_lenght} 64 // tested opcode
228-
then
229-
trace "~g~~h~~h~0AD7 (read_string_from_file), #16 PASSED"
230-
else
231-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #16 FAILED! Condition result: FALSE"
232-
end
233-
2@ = allocate_memory 64
234-
string_format 2@ {format} "n longer test string to read number 5%c" {args} 0x0A
235-
if
236-
is_memory_equal 1@ 2@ {size} 39 // including terminator
237-
then
238-
trace "~g~~h~~h~0AD7 (read_string_from_file), #17 PASSED"
239-
else
240-
breakpoint "~r~~h~~h~~h~0AD7 (read_string_from_file), #17 FAILED!~n~'%s' Expected~n~'%s' Occured" 0xcccccccc 1@ 2@
21+
function tests
22+
before_each(@setup)
23+
after_each(@cleanup)
24+
25+
it("should read nothing", test1)
26+
it("should read one", test2)
27+
it("should read two", test3)
28+
it("should read four", test4)
29+
it("should read eight", test5)
30+
it("should overflow dest string variable", test6)
31+
it("should read till line feed (\\n)", test7)
32+
it("should read till line feed (\\r\\n)", test8)
33+
34+
return
35+
36+
:setup
37+
0@ = open_file {filePathName} ".\0AD7.s" {mode} "r"
38+
1@ = 0xCCCCCCCC
39+
2@ = 0xCCCCCCCC
40+
3@ = 0xCCCCCCCC
41+
4@ = 0xCCCCCCCC
42+
return
43+
44+
:cleanup
45+
close_file 0@
46+
return
47+
48+
function test1
49+
file_seek 0@ {offset} Test_Data_Offset_A {origin} SeekOrigin.Begin
50+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 0
51+
assert_result_true()
52+
assert_eq(1@, 0xCCCCCCCC)
53+
assert_eq(2@, 0xCCCCCCCC)
54+
assert_eq(3@, 0xCCCCCCCC)
55+
assert_eq(4@, 0xCCCCCCCC)
56+
end
57+
58+
function test2
59+
file_seek 0@ {offset} Test_Data_Offset_A {origin} SeekOrigin.Begin
60+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 1
61+
assert_result_true()
62+
assert_eq(1@, 0xCCCCCCCC)
63+
assert_eqs(2@s, "") // just terminator character
64+
assert_eq(3@, 0xCCCCCCCC)
65+
assert_eq(4@, 0xCCCCCCCC)
66+
end
67+
68+
function test3
69+
file_seek 0@ {offset} Test_Data_Offset_A {origin} SeekOrigin.Begin
70+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 2
71+
assert_result_true()
72+
assert_eq(1@, 0xCCCCCCCC)
73+
assert_eqs(2@s, "1")
74+
assert_eq(3@, 0xCCCCCCCC)
75+
assert_eq(4@, 0xCCCCCCCC)
76+
end
77+
78+
function test4
79+
file_seek 0@ {offset} Test_Data_Offset_A {origin} SeekOrigin.Begin
80+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 4
81+
assert_result_true()
82+
assert_eq(1@, 0xCCCCCCCC)
83+
assert_eqs(2@s, "123")
84+
assert_eq(3@, 0xCCCCCCCC)
85+
assert_eq(4@, 0xCCCCCCCC)
86+
end
87+
88+
function test5
89+
file_seek 0@ {offset} Test_Data_Offset_A {origin} SeekOrigin.Begin
90+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 8
91+
assert_result_true()
92+
assert_eq(1@, 0xCCCCCCCC)
93+
assert_eqs(2@s, "1234567")
94+
assert_eq(4@, 0xCCCCCCCC)
95+
end
96+
97+
function test6
98+
file_seek 0@ {offset} Test_Data_Offset_A {origin} SeekOrigin.Begin
99+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 10
100+
assert_result_true()
101+
assert_eq(1@, 0xCCCCCCCC)
102+
assert_eqs(2@s, "12345678")
103+
assert_eqs(4@s, "9") // overflowed data
104+
end
105+
106+
function test7
107+
file_seek 0@ {offset} Test_Data_Offset_B {origin} SeekOrigin.Begin
108+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 8
109+
assert_result_true()
110+
assert_eq(1@, 0xCCCCCCCC)
111+
assert_eqs(2@s, "123")
112+
assert_eq(4@, 0xCCCCCCCC)
113+
end
114+
115+
function test8
116+
file_seek 0@ {offset} Test_Data_Offset_C {origin} SeekOrigin.Begin
117+
read_string_from_file 0@ {storeTo} 2@s {maxLength} 8
118+
assert_result_true()
119+
assert_eq(1@, 0xCCCCCCCC)
120+
assert_eqs(2@s, "12")
121+
assert_eq(4@, 0xCCCCCCCC)
122+
end
241123
end
242-
free_memory 1@
243-
free_memory 2@
244-
245-
246-
// close the file
247-
wait 0
248-
close_file 0@
249-
trace "~g~~h~~h~0AD7 (read_string_from_file), #18 PASSED"
250-
251-
252-
terminate_this_custom_script

0 commit comments

Comments
 (0)