Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions include/platformstl/filesystem/FILE_stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
* Purpose: Facade for the standard C Streams API.
*
* Created: 31st May 2009
* Updated: 20th March 2025
* Updated: 23rd September 2026
*
* Home: http://stlsoft.org/
*
* Copyright (c) 2019-2025, Matthew Wilson and Synesis Information Systems
* Copyright (c) 2019-2026, Matthew Wilson and Synesis Information Systems
* Copyright (c) 2009-2019, Matthew Wilson and Synesis Software
* All rights reserved.
*
Expand Down Expand Up @@ -53,8 +53,8 @@
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
# define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_FILE_STREAM_MAJOR 2
# define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_FILE_STREAM_MINOR 1
# define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_FILE_STREAM_REVISION 5
# define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_FILE_STREAM_EDIT 28
# define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_FILE_STREAM_REVISION 6
# define PLATFORMSTL_VER_PLATFORMSTL_FILESYSTEM_HPP_FILE_STREAM_EDIT 29
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */


Expand Down Expand Up @@ -270,12 +270,31 @@ class FILE_stream_base
return write_text_(ps, cch);
}

/// [DEPRECATED] Writes \c cb bytes from the memory block pointed to by
/// \c pv to the underlying file stream.
///
/// \deprecated Use write_binary() instead
///
/// \exception X Thrown in \c cb bytes cannot be written to the
/// underlying stream
STLSOFT_DEPRECATED_("write(void const*, size_t) is deprecated and will be removed from a future version of STLSoft; use write_binary() instead")
class_type& write(void const* pv, size_type cb)
{
return write_binary(pv, cb);
}

/// Writes \c cb bytes from the memory block pointed to by \c pv to the
/// underlying file stream.
///
/// \note Every byte is written, including embedded NULs. Character
/// overloads of <code>write()</code> stop at the first NUL. Newline
/// translation follows the stream's open mode, so open with
/// <code>"wb"</code> when the stored bytes must match the memory
/// block.
///
/// \exception X Thrown in \c cb bytes cannot be written to the
/// underlying stream
class_type& write(void const* pv, size_type cb)
class_type& write_binary(void const* pv, size_type cb)
{
return write_bytes_(pv, cb);
}
Expand Down
1 change: 1 addition & 0 deletions test/component/platformstl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# SIS:AUTO_GENERATED: Remove this line if you edit the file, otherwise it will be overwritten
add_subdirectory(diagnostics)
add_subdirectory(filesystem)
add_subdirectory(system)
2 changes: 2 additions & 0 deletions test/component/platformstl/filesystem/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SIS:AUTO_GENERATED: Remove this line if you edit the file, otherwise it will be overwritten
add_subdirectory(test.component.platformstl.filesystem.file_lines)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# SIS:AUTO_GENERATED: Remove this line if you edit the file, otherwise it will be overwritten
define_automated_test_program(test.component.platformstl.filesystem.file_lines entry.cpp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
/* /////////////////////////////////////////////////////////////////////////
* File: test.component.platformstl.filesystem.file_lines/entry.cpp
*
* Purpose: Component-tests for `platformstl::file_lines`.
*
* Created: 23rd September 2026
* Updated: 23rd September 2026
*
* ////////////////////////////////////////////////////////////////////// */


/* /////////////////////////////////////////////////////////////////////////
* includes
*/

/* /////////////////////////////////////
* test component header file include(s)
*/

#include <platformstl/filesystem/file_lines.hpp>

/* /////////////////////////////////////
* general includes
*/

/* xTests header files */
#include <xtests/terse-api.h>
#include <xtests/util/temp_file.hpp>
#include <xtests/xtests.h>

/* STLSoft header files */
#include <platformstl/exception/invalid_file_type_exception.hpp>
#include <platformstl/filesystem/FILE_stream.hpp>

/* Standard C header files */
#include <stdlib.h>


/* /////////////////////////////////////////////////////////////////////////
* forward declarations
*/

namespace {

void TEST_EMPTY_FILE();
void TEST_FILE_WITH_ONE_LINE_UNTERMINATED();
void TEST_FILE_WITH_ONE_LINE_TERMINATED();
void TEST_FILE_WITH_THREE_LINES();
void TEST_FILE_WITH_ONE_LINE_TERMINATED_BY_CRLF();
void TEST_FILE_WITH_THREE_LINES_SEPARATED_BY_CRLF();
void TEST_FILE_WITH_CONSECUTIVE_CRLF_GIVES_EMPTY_LINE();
void TEST_FILE_WITH_ONE_LINE_TERMINATED_BY_CR();
void TEST_FILE_WITH_THREE_LINES_SEPARATED_BY_CR();
void TEST_FILE_WITH_CONSECUTIVE_CR_GIVES_EMPTY_LINE();
void TEST_FILE_CONTAINING_NUL_CHARACTER_THROWS();
} // anonymous namespace


/* /////////////////////////////////////////////////////////////////////////
* main()
*/

int main(int argc, char* argv[])
{
int retCode = EXIT_SUCCESS;
int verbosity = 2;

XTESTS_COMMANDLINE_PARSEVERBOSITY(argc, argv, &verbosity);

if (XTESTS_START_RUNNER("test.component.platformstl.filesystem.file_lines", verbosity))
{
XTESTS_RUN_CASE(TEST_EMPTY_FILE);
XTESTS_RUN_CASE(TEST_FILE_WITH_ONE_LINE_UNTERMINATED);
XTESTS_RUN_CASE(TEST_FILE_WITH_ONE_LINE_TERMINATED);
XTESTS_RUN_CASE(TEST_FILE_WITH_THREE_LINES);
XTESTS_RUN_CASE(TEST_FILE_WITH_ONE_LINE_TERMINATED_BY_CRLF);
XTESTS_RUN_CASE(TEST_FILE_WITH_THREE_LINES_SEPARATED_BY_CRLF);
XTESTS_RUN_CASE(TEST_FILE_WITH_CONSECUTIVE_CRLF_GIVES_EMPTY_LINE);
XTESTS_RUN_CASE(TEST_FILE_WITH_ONE_LINE_TERMINATED_BY_CR);
XTESTS_RUN_CASE(TEST_FILE_WITH_THREE_LINES_SEPARATED_BY_CR);
XTESTS_RUN_CASE(TEST_FILE_WITH_CONSECUTIVE_CR_GIVES_EMPTY_LINE);
XTESTS_RUN_CASE_THAT_THROWS(TEST_FILE_CONTAINING_NUL_CHARACTER_THROWS, platformstl::invalid_file_type_exception);

XTESTS_PRINT_RESULTS();

XTESTS_END_RUNNER_UPDATE_EXITCODE(&retCode);
}

return retCode;
}


/* /////////////////////////////////////////////////////////////////////////
* test function implementations
*/

namespace {

using ::xtests::cpp::util::temp_file;


void TEST_EMPTY_FILE()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

platformstl::file_lines lines(f.c_str());

TEST_INT_EQ(0u, lines.size());
}

void TEST_FILE_WITH_ONE_LINE_UNTERMINATED()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "w");

stm.write("abc");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(1u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
}

void TEST_FILE_WITH_ONE_LINE_TERMINATED()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "w");

stm.write_line("abc");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(1u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
}

void TEST_FILE_WITH_THREE_LINES()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "w");

stm.write_line("abc");
stm.write("\nghi");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(3u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
TEST_MS_EQ("", lines[1]);
TEST_MS_EQ("ghi", lines[2]);
}

void TEST_FILE_WITH_ONE_LINE_TERMINATED_BY_CRLF()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "wb");

stm.write("abc\r\n");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(1u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
}

void TEST_FILE_WITH_THREE_LINES_SEPARATED_BY_CRLF()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "wb");

stm.write("abc\r\ndef\r\nghi\r\n");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(3u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
TEST_MS_EQ("def", lines[1]);
TEST_MS_EQ("ghi", lines[2]);
}

void TEST_FILE_WITH_CONSECUTIVE_CRLF_GIVES_EMPTY_LINE()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "wb");

stm.write("abc\r\n\r\nghi");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(3u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
TEST_MS_EQ("", lines[1]);
TEST_MS_EQ("ghi", lines[2]);
}

void TEST_FILE_WITH_ONE_LINE_TERMINATED_BY_CR()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "wb");

stm.write("abc\r");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(1u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
}

void TEST_FILE_WITH_THREE_LINES_SEPARATED_BY_CR()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "wb");

stm.write("abc\rdef\rghi\r");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(3u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
TEST_MS_EQ("def", lines[1]);
TEST_MS_EQ("ghi", lines[2]);
}

void TEST_FILE_WITH_CONSECUTIVE_CR_GIVES_EMPTY_LINE()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
platformstl::FILE_stream stm(f.c_str(), "wb");

stm.write("abc\r\rghi");
}

platformstl::file_lines lines(f.c_str());

REQUIRE(TEST_INT_EQ(3u, lines.size()));
TEST_MS_EQ("abc", lines[0]);
TEST_MS_EQ("", lines[1]);
TEST_MS_EQ("ghi", lines[2]);
}

void TEST_FILE_CONTAINING_NUL_CHARACTER_THROWS()
{
temp_file f(temp_file::DeleteOnClose | temp_file::EmptyOnOpen | temp_file::CloseOnOpen);

{
char const contents[] = { 'a', 'b', 'c', '\0', 'd', 'e', 'f' };
platformstl::FILE_stream stm(f.c_str(), "wb");

stm.write_binary(contents, sizeof(contents));
}

platformstl::file_lines lines(f.c_str());
}
} // anonymous namespace


/* ///////////////////////////// end of file //////////////////////////// */

Loading