1 //=============================================================================
2 //
3 // Adventure Game Studio (AGS)
4 //
5 // Copyright (C) 1999-2011 Chris Jones and 2011-20xx others
6 // The full list of copyright holders can be found in the Copyright.txt
7 // file, which is part of this source code distribution.
8 //
9 // The AGS source code is provided under the Artistic License 2.0.
10 // A copy of this license can be found in the file License.txt and at
11 // http://www.opensource.org/licenses/artistic-license-2.0.php
12 //
13 //=============================================================================
14 
15 #ifdef _DEBUG
16 
17 #include <string.h>
18 #include "ac/game_version.h"
19 #include "debug/assert.h"
20 #include "script/script_api.h"
21 #include "script/runtimescriptvalue.h"
22 
ScriptVSprintf__(char * buffer,size_t buf_length,const char * format,...)23 const char *ScriptVSprintf__(char *buffer, size_t buf_length, const char *format, ...)
24 {
25     va_list args;
26     va_start(args, format);
27     const char *res_buffer = ScriptVSprintf(buffer, buf_length, format, args);
28     va_end(args);
29     return res_buffer;
30 }
31 
Test_ScriptSprintf()32 void Test_ScriptSprintf()
33 {
34     const int argi = 123;
35     const float argf = 0.456F;
36     char *argcc = "string literal";
37     RuntimeScriptValue params[10];
38     params[0].SetInt32(argi);
39     params[1].SetFloat(argf);
40     params[2].SetStringLiteral(argcc);
41 
42     char ScSfBuffer[STD_BUFFER_SIZE];
43     //
44     // Called-from-script variant
45     //
46     // Correct format, extra placeholder
47     const char *result =
48         ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE,
49                       "testing ScriptSprintf:\nThis is int: %10d\nThis is float: %.4f\nThis is string: '%s'\nThis placeholder will be ignored: %d",
50                       params, 3);
51     assert(strcmp(result, "testing ScriptSprintf:\nThis is int:        123\nThis is float: 0.4560\nThis is string: 'string literal'\nThis placeholder will be ignored: %d") == 0);
52     // Literal percent sign
53     result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%d%%", params, 3);
54     assert(strcmp(result, "123%") == 0);
55     result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "123%%", NULL, 0);
56     assert(strcmp(result, "123%") == 0);
57     result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%%5d%%0.5f%%s", params, 3);
58     assert(strcmp(result, "%5d%0.5f%s") == 0);
59 
60     // Invalid format
61     result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%zzzzzz", params, 3);
62     assert(strcmp(result, "%zzzzzz") == 0);
63     result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%12.34%d", params, 3);
64     assert(strcmp(result, "%12.34123") == 0);
65 
66     // Not enough arguments
67     result = ScriptSprintf(ScSfBuffer, STD_BUFFER_SIZE, "%5d%0.5f%s", params, 0);
68     assert(strcmp(result, "%5d%0.5f%s") == 0);
69 
70     // Not enough buffer space
71     result = ScriptSprintf(ScSfBuffer, 9, "12345678%d", params, 3);
72     assert(strcmp(result, "12345678") == 0);
73     result = ScriptSprintf(ScSfBuffer, 11, "12345678%d", params, 3);
74     assert(strcmp(result, "1234567812") == 0);
75     // Not enough buffer space and not enough params
76     result = ScriptSprintf(ScSfBuffer, 10, "12345678%d", params, 0);
77     assert(strcmp(result, "12345678%") == 0);
78     result = ScriptSprintf(ScSfBuffer, 11, "12345678%d", params, 0);
79     assert(strcmp(result, "12345678%d") == 0);
80 
81     // Test null string pointer in backward-compatibility mode
82     loaded_game_file_version = kGameVersion_312;
83     params[0].SetStringLiteral(NULL);
84     result = ScriptSprintf(ScSfBuffer, 10, "A%sB", params, 1);
85     assert(strcmp(result, "A(null)B") == 0);
86     loaded_game_file_version = kGameVersion_Undefined;
87 
88     //
89     // Called-from-plugin variant
90     // Note that since this is variadic function, number of parameters must
91     // always be equal or higher than number of placeholders in buffer string.
92     //
93     // Correct format, matching number of arguments
94     result =
95         ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE,
96         "testing ScriptVSprintf:\nThis is int: %10d\nThis is float: %.4f\nThis is string: '%s'\n",
97         argi, argf, argcc);
98     assert(strcmp(result, "testing ScriptVSprintf:\nThis is int:        123\nThis is float: 0.4560\nThis is string: 'string literal'\n") == 0);
99     // Literal percent sign
100     result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%d%%", argi);
101     assert(strcmp(result, "123%") == 0);
102     result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "123%%");
103     assert(strcmp(result, "123%") == 0);
104     result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%%5d%%0.5f%%s");
105     assert(strcmp(result, "%5d%0.5f%s") == 0);
106 
107     // Invalid format
108     result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%zzzzzz", argi, argf, argcc);
109     assert(strcmp(result, "%zzzzzz") == 0);
110     result = ScriptVSprintf__(ScSfBuffer, STD_BUFFER_SIZE, "%12.34%d", argi, argf, argcc);
111     assert(strcmp(result, "%12.34123") == 0);
112 
113     // Not enough buffer space
114     result = ScriptVSprintf__(ScSfBuffer, 9, "12345678%d", argi, argf, argcc);
115     assert(strcmp(result, "12345678") == 0);
116     result = ScriptVSprintf__(ScSfBuffer, 11, "12345678%d", argi, argf, argcc);
117     assert(strcmp(result, "1234567812") == 0);
118 
119     // Test null string pointer in backward-compatibility mode
120     loaded_game_file_version = kGameVersion_312;
121     result = ScriptVSprintf__(ScSfBuffer, 10, "A%sB", NULL);
122     assert(strcmp(result, "A(null)B") == 0);
123     loaded_game_file_version = kGameVersion_Undefined;
124 }
125 
126 #endif // _DEBUG
127