12
12
* ### Serializing:
13
13
* - **Fundamental Types**: Written directly in their binary form.
14
14
* - **Strings**: The string's length is written first, followed by the string
15
- * data, and a `|` delimiter to mark the end.
15
+ * data, and a `|` delimiter to mark the end. String size should not exceed 1MB.
16
16
*
17
17
* ### Deserializing:
18
18
* - **Fundamental Types**: Reads the binary data back into the appropriate
@@ -59,11 +59,19 @@ class Serializer {
59
59
* @param out The output stream (std::ofstream).
60
60
* @param data The string to be serialized.
61
61
*
62
- * @note The string is serialized by first storing its length, followed by the
63
- * content.
62
+ * @note The string is serialized by first storing its length, followed by
63
+ * the content. String length should not exceed 1MB
64
64
*/
65
65
static void serialize (std::ofstream &out, const std::string &data) {
66
66
std::uint32_t length = data.size ();
67
+
68
+ // Check if the string exceeds the size limit of 1MB.
69
+ const std::uint32_t max_size = 1024 * 1024 ;
70
+ if (length > max_size) {
71
+ throw std::runtime_error (
72
+ " String exceeds the maximum size of 1MB." );
73
+ }
74
+
67
75
serialize (out, length); // Serialize the length of the string.
68
76
out.write (data.c_str (), length); // Serialize the string characters.
69
77
out.put (' |' ); // Add a delimiter to denote the end of the string.
@@ -77,8 +85,8 @@ class Serializer {
77
85
class Deserializer {
78
86
public:
79
87
/* *
80
- * @brief Deserializes fundamental data types (like int, float, double, etc.) from
81
- * a binary file.
88
+ * @brief Deserializes fundamental data types (like int, float, double,
89
+ * etc.) from a binary file.
82
90
* @tparam T The type of the data to be deserialized.
83
91
* @param in The input stream (std::ifstream).
84
92
* @param data The variable where the deserialized data will be stored.
@@ -126,131 +134,97 @@ class Deserializer {
126
134
* @return void
127
135
*/
128
136
void tests () {
129
- try {
130
- std::ofstream outFile (" test_output.bin" , std::ios::binary);
131
- if (!outFile) {
132
- throw std::runtime_error (" Error opening file for output." );
133
- }
137
+ // Serialize fundamental types and string
138
+ std::ofstream outFile (" test_output.bin" , std::ios::binary);
139
+ if (!outFile) {
140
+ throw std::runtime_error (" Error opening file for output." );
141
+ }
134
142
135
- int testInt = 12345 ;
136
- double testDouble = 9876.54321 ;
137
- char testChar = ' A' ;
138
- std::string testString = " Testing String Serialization!" ;
143
+ int testInt = 12345 ;
144
+ double testDouble = 9876.54321 ;
145
+ char testChar = ' A' ;
146
+ std::string testString = " Testing String Serialization!" ;
139
147
140
- // Serialize the data
141
- Serializer::serialize (outFile, testInt);
142
- Serializer::serialize (outFile, testDouble);
143
- Serializer::serialize (outFile, testChar);
144
- Serializer::serialize (outFile, testString);
148
+ // Serialize the data
149
+ Serializer::serialize (outFile, testInt);
150
+ Serializer::serialize (outFile, testDouble);
151
+ Serializer::serialize (outFile, testChar);
152
+ Serializer::serialize (outFile, testString);
145
153
146
- outFile.close ();
154
+ outFile.close ();
147
155
148
- std::ifstream inFile (" test_output.bin" , std::ios::binary);
149
- if (!inFile) {
150
- throw std::runtime_error (" Error opening file for input." );
151
- }
156
+ // Deserialize the data and assert
157
+ std::ifstream inFile (" test_output.bin" , std::ios::binary);
158
+ if (!inFile) {
159
+ throw std::runtime_error (" Error opening file for input." );
160
+ }
152
161
153
- int intResult;
154
- double doubleResult;
155
- char charResult;
156
- std::string stringResult;
162
+ int intResult;
163
+ double doubleResult;
164
+ char charResult;
165
+ std::string stringResult;
157
166
158
- // Deserialize the data
159
- Deserializer::deserialize (inFile, intResult);
160
- Deserializer::deserialize (inFile, doubleResult);
161
- Deserializer::deserialize (inFile, charResult);
162
- Deserializer::deserialize (inFile, stringResult);
167
+ // Deserialize the data
168
+ Deserializer::deserialize (inFile, intResult);
169
+ Deserializer::deserialize (inFile, doubleResult);
170
+ Deserializer::deserialize (inFile, charResult);
171
+ Deserializer::deserialize (inFile, stringResult);
163
172
164
- inFile.close ();
173
+ inFile.close ();
165
174
166
- // Assert that the original and deserialized values are the same
167
- assert (testInt == intResult);
168
- assert (testDouble == doubleResult);
169
- assert (testChar == charResult);
170
- assert (testString == stringResult);
175
+ // Assert that the original and deserialized values are the same
176
+ assert (testInt == intResult);
177
+ assert (testDouble == doubleResult);
178
+ assert (testChar == charResult);
179
+ assert (testString == stringResult);
171
180
172
- std::cout << " All tests passed!\n " ;
173
- } catch (const std::exception &e) {
174
- std::cerr << " Test failed: " << e.what () << std::endl;
175
- }
181
+ std::cout << " Basic serialization/deserialization tests passed!\n " ;
176
182
177
- // Test for file opening failure
183
+ // Test for string too large error
178
184
try {
179
- std::ifstream inFile (" non_existent_file.bin" , std::ios::binary);
180
- if (!inFile) {
181
- throw std::runtime_error (" Error opening non-existent file." );
182
- }
185
+ std::ofstream largeOutFile (" large_string.bin" , std::ios::binary);
186
+ // Create a string larger than 1MB
187
+ std::string largeString (1024 * 1024 + 1 , ' A' );
188
+ Serializer::serialize (largeOutFile, largeString); // Should throw an error
189
+ largeOutFile.close ();
190
+ assert (false ); // If we reach here, the test has failed.
183
191
} catch (const std::runtime_error &e) {
184
- assert (std::string (e.what ()) == " Error opening non-existent file." );
185
- std::cout << " File opening error test passed!\n " ;
192
+ assert (std::string (e.what ()) ==
193
+ " String exceeds the maximum size of 1MB." );
194
+ std::cout << " Large string serialization error test passed!\n " ;
186
195
}
187
-
188
- // Test for deserialization failure (e.g., wrong file format)
196
+ // Test for missing delimiter in string serialization
189
197
try {
190
- std::ofstream outFile (" wrong_format.bin" , std::ios::binary);
191
- outFile << " This is not serialized data" ; // Writing incorrect data
192
- outFile.close ();
193
-
194
- std::ifstream inFile (" wrong_format.bin" , std::ios::binary);
195
- if (!inFile) {
196
- throw std::runtime_error (" Error opening file for input." );
197
- }
198
+ std::ofstream missingDelimiterOutFile (" missing_delimiter.bin" ,std::ios::binary);
198
199
199
- int intResult;
200
- // Deserialize expecting binary data, this should fail
201
- Deserializer::deserialize (inFile, intResult);
200
+ std::string incompleteString = " Incomplete string test" ;
201
+ std::uint32_t length = incompleteString.size ();
202
202
203
- inFile.close ();
204
- } catch (const std::exception &e) {
205
- std::cout << " Deserialization error test passed: " << e.what ()
206
- << std::endl;
207
- }
203
+ // Serialize string length and content without the delimiter
204
+ missingDelimiterOutFile.write (reinterpret_cast <const char *>(&length),sizeof (length));
205
+ missingDelimiterOutFile.write (incompleteString.c_str (), length); // No delimiter '|'
206
+ missingDelimiterOutFile.close ();
208
207
209
- // Test for string too large error
210
- try {
211
- std::ofstream outFile (" large_string.bin" , std::ios::binary);
212
- std::string largeString (1024 * 1024 + 1 ,
213
- ' A' ); // String larger than 1MB
214
- Serializer::serialize (outFile,
215
- largeString); // Should succeed in serialization
216
- outFile.close ();
208
+ std::ifstream missingDelimiterInFile (" missing_delimiter.bin" ,std::ios::binary);
217
209
218
- std::ifstream inFile (" large_string.bin" , std::ios::binary);
219
210
std::string deserializedString;
220
- Deserializer::deserialize (
221
- inFile, deserializedString); // Should fail in deserialization
222
- inFile.close ();
223
- } catch (const std::runtime_error &e) {
224
- assert (std::string (e.what ()) ==
225
- " Deserialized string length is too large." );
226
- std::cout << " Large string error test passed!\n " ;
227
- }
211
+ Deserializer::deserialize (missingDelimiterInFile,deserializedString); // Should throw an error
212
+ missingDelimiterInFile.close ();
228
213
229
- // Test for missing delimiter
230
- try {
231
- std::ofstream outFile (" missing_delimiter.bin" , std::ios::binary);
232
- std::string testString = " Test String" ;
233
- std::uint32_t length = testString.size ();
234
- outFile.write (reinterpret_cast <const char *>(&length), sizeof (length));
235
- outFile.write (testString.c_str (), length); // No delimiter
236
- outFile.close ();
237
-
238
- std::ifstream inFile (" missing_delimiter.bin" , std::ios::binary);
239
- std::string deserializedString;
240
- Deserializer::deserialize (inFile, deserializedString); // Should fail
241
- inFile.close ();
214
+ assert (false );
242
215
} catch (const std::runtime_error &e) {
243
216
assert (std::string (e.what ()) ==
244
217
" Delimiter '|' not found after string." );
245
218
std::cout << " Missing delimiter error test passed!\n " ;
246
219
}
247
- // Clean up temporary files that were created during testing.
248
- std::remove (" test_output.bin" );
249
- std::remove (" wrong_format.bin" );
220
+
221
+ // Clean up temporary files that were created during testing
250
222
std::remove (" large_string.bin" );
251
223
std::remove (" missing_delimiter.bin" );
252
- }
224
+ std::remove ( " test_output.bin " );
253
225
226
+ std::cout << " All tests passed successfully!\n " ;
227
+ }
254
228
/* *
255
229
* @brief Main function
256
230
* @returns 0 on successful exit
0 commit comments