Skip to content

Commit

Permalink
Merge pull request #304 from PRUNERS/issue293-tempfile-error-checks
Browse files Browse the repository at this point in the history
Issue293 tempfile error checks
  • Loading branch information
mikebentley15 authored Dec 12, 2019
2 parents 5e75aab + 8f3be82 commit 15ead85
Show file tree
Hide file tree
Showing 16 changed files with 497 additions and 350 deletions.
40 changes: 40 additions & 0 deletions documentation/flit-helpers.md
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,28 @@ auto absolute = flit::realpath(os.path.join(".", "output", "..", "output",
This will resolve as expected.


### `flit::dirname()`

Returns the parent directory path of the given path.

```c++
auto parent = flit::dirname("a/b/c");
```

The above will return `"a/b"` as the parent.


### `flit::basename()`

Returns the last component of a path, which may be a file or a directory.

```c++
auto filename = flit::basename("dir/subdir/file.txt");
```

The above will result in `"file.txt"`.


### Class `TempDir`

An RAII-style class that creates a temporary directory. When the class goes
Expand Down Expand Up @@ -576,6 +598,24 @@ modified. This is to prevent unintended consequences in code.
- `flit::ltrim()`: trims whitespace from the left-hand side of a string
- `flit::trim()`: trims whitespace from both the left and right


### `flit::rstrip()`, `flit::lstrip()`, and `flit::strip()` (in `src/flitHelpers.h`)

These three are similar to the `flit::trim()` functions. These, however, can
strip off any amount of an arbitrary string from the right, left, or both
sides, respectively.

- `flit::rstrip()`: strip any amount of a given string from the right and return
- `flit::lstrip()`: strip any amount of a given string from the left and return
- `flit::strip()`: strip from both sides

```c++
auto stripped = flit::rstrip("-*--*- hello -*--*-", "-*-");
```

This will result in `"-*--*- hello "`, since only the right side was stripped.


### `flit::l2norm()` (in `src/flitHelpers.h`)

Computes the L2 norm between two `std::vector<T>` instances. The type of `T`
Expand Down
38 changes: 38 additions & 0 deletions src/flitHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,44 @@ inline std::string trim(const std::string &text) {
return text.substr(left, right - left);
}

inline std::string lstrip(const std::string &text,
const std::string &to_remove)
{
if (to_remove.size() == 0) { return text; }
auto left = text.begin();
while (static_cast<size_t>(std::distance(left, text.end()))
>= to_remove.size())
{
if (!std::equal(to_remove.begin(), to_remove.end(), left)) {
break;
}
std::advance(left, to_remove.size());
}
return std::string(left, text.end());
}

inline std::string rstrip(const std::string &text,
const std::string &to_remove)
{
if (to_remove.size() == 0) { return text; }
auto right = text.rbegin();
while (static_cast<size_t>(std::distance(right, text.rend()))
>= to_remove.size())
{
if (!std::equal(to_remove.rbegin(), to_remove.rend(), right)) {
break;
}
std::advance(right, to_remove.size());
}
return text.substr(0, std::distance(right, text.rend()));
}

inline std::string strip(const std::string &text,
const std::string &to_remove)
{
return lstrip(rstrip(text, to_remove), to_remove);
}

template <typename F, typename I>
F as_float_impl(I val) {
static_assert(sizeof(F) == sizeof(I), "cannot convert types of different sizes");
Expand Down
42 changes: 40 additions & 2 deletions src/fsutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,46 @@ std::string which(const std::string &command, const std::string &path) {
throw std::ios_base::failure("Could not find " + command + " in path");
}

std::string dirname(const std::string &path) {
if (path == "") { return "."; }
if (path.size() >= separator.size() &&
std::equal(separator.begin(), separator.end(), path.begin()))
{
auto modified = flit::dirname(strip(path, separator));
if (modified == ".") { return separator; }
return separator + modified;
}

auto stripped = rstrip(path, separator);
auto last_sep = std::find_end(stripped.begin(), stripped.end(),
separator.begin(), separator.end());
if (last_sep == stripped.end()) {
return ".";
}
return rstrip(std::string(stripped.begin(), last_sep), separator);
}

std::string basename(const std::string &path) {
if (path == "") { return ""; }
auto stripped = strip(path, separator);
if (stripped == "") { return separator; } // if the path was only separators
auto last_sep = std::find_end(stripped.begin(), stripped.end(),
separator.begin(), separator.end());
if (last_sep == stripped.end()) {
return stripped;
}
std::advance(last_sep, separator.size());
return std::string(last_sep, stripped.end());
}

TempFile::TempFile(const std::string &parent) {
std::string ftemplate = join(parent, "flit-tempfile-XXXXXX");
std::unique_ptr<char> fname_buf(new char[ftemplate.size() + 1]);
strcpy(fname_buf.get(), ftemplate.data());
mkstemp(fname_buf.get());
auto status = mkstemp(fname_buf.get());
if (status == -1) {
throw std::ios_base::failure("Could not create file with mkstemp()");
}
name = fname_buf.get();
out.exceptions(std::ios::failbit);
out.open(name);
Expand All @@ -264,7 +299,10 @@ TempDir::TempDir(const std::string &parent) {
std::string dtemplate = join(parent, "flit-tempfile-XXXXXX");
std::unique_ptr<char> dname_buf(new char[dtemplate.size() + 1]);
strcpy(dname_buf.get(), dtemplate.data());
mkdtemp(dname_buf.get());
auto status = mkdtemp(dname_buf.get());
if (status == nullptr) {
throw std::ios_base::failure("Could not create directory with mkdtemp()");
}
_name = dname_buf.get();
}

Expand Down
2 changes: 2 additions & 0 deletions src/fsutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ void chdir(const std::string &directory);
std::string which(const std::string &command);
std::string which(const std::string &command, const std::string &path);
std::string realpath(const std::string &relative);
std::string dirname(const std::string &path);
std::string basename(const std::string &path);

/** constructor changes current dir, destructor undoes it */
class PushDir {
Expand Down
43 changes: 21 additions & 22 deletions src/tinydir.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ This header file was downloaded from GitHub at the following address:
https://github.com/cxong/tinydir/blob/1.2.4/tinydir.h
This is tinydir version 1.2.4 from 19 Oct 2019.
This is tinydir after version 1.2.4 from 10 Oct 2019. Git sha sum:
5d907978e1e6f2a3b0ad8d51fa186d6fda863ea6
It has then been slightly modified for use with FLiT
Tinydir is used to list the contents of a directory in a cross-platform way.
*/
Expand Down Expand Up @@ -106,7 +110,9 @@ extern "C" {
# include <sys/param.h>
# if defined(BSD)
# include <limits.h>
# define _TINYDIR_PATH_MAX PATH_MAX
# ifdef PATH_MAX
# define _TINYDIR_PATH_MAX PATH_MAX
# endif
# endif
#endif

Expand Down Expand Up @@ -506,6 +512,7 @@ int tinydir_next(tinydir_dir *dir)
_TINYDIR_FUNC
int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
{
const _tinydir_char_t *filename;
if (dir == NULL || file == NULL)
{
errno = EINVAL;
Expand All @@ -520,45 +527,37 @@ int tinydir_readfile(const tinydir_dir *dir, tinydir_file *file)
errno = ENOENT;
return -1;
}
if (_tinydir_strlen(dir->path) +
_tinydir_strlen(
filename =
#ifdef _MSC_VER
dir->_f.cFileName
dir->_f.cFileName;
#else
dir->_e->d_name
dir->_e->d_name;
#endif
) + 1 + _TINYDIR_PATH_EXTRA >=
if (_tinydir_strlen(dir->path) +
_tinydir_strlen(filename) + 1 + _TINYDIR_PATH_EXTRA >=
_TINYDIR_PATH_MAX)
{
/* the path for the file will be too long */
errno = ENAMETOOLONG;
return -1;
}
if (_tinydir_strlen(
#ifdef _MSC_VER
dir->_f.cFileName
#else
dir->_e->d_name
#endif
) >= _TINYDIR_FILENAME_MAX)
if (_tinydir_strlen(filename) >= _TINYDIR_FILENAME_MAX)
{
errno = ENAMETOOLONG;
return -1;
}

_tinydir_strcpy(file->path, dir->path);
_tinydir_strcat(file->path, TINYDIR_STRING("/"));
_tinydir_strcpy(file->name,
#ifdef _MSC_VER
dir->_f.cFileName
#else
dir->_e->d_name
#endif
);
_tinydir_strcat(file->path, file->name);
_tinydir_strcpy(file->name, filename);
_tinydir_strcat(file->path, filename);
#ifndef _MSC_VER
#ifdef __MINGW32__
if (_tstat(
#elif (defined _BSD_SOURCE) || (defined _DEFAULT_SOURCE) \
|| ((defined _XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) \
|| ((defined _POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L))
if (lstat(
#else
if (stat(
#endif
Expand Down
2 changes: 2 additions & 0 deletions tests/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ flit_src/tst_flitHelpers_h
flit_src/tst_flit_cpp
flit_src/tst_fsutil
flit_src/tst_subprocess
flit_src/*.gcda
flit_src/*.gcno
6 changes: 6 additions & 0 deletions tests/flit_src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ FLITLIB := $(FLITLIBDIR)/libflit.so

CFLAGS := -O0 -g
CFLAGS += -std=c++11
CFLAGS += -fprofile-arcs
CFLAGS += -ftest-coverage
CFLAGS += -fPIC
LDFLAGS := -L$(FLITLIBDIR) -lflit
LDFLAGS += -Wl,-rpath=$(FLITLIBDIR)
SRC := $(wildcard *.cpp)
DEPS := $(SRC:%.cpp=%.d)
TARGETS := $(SRC:%.cpp=%)
GCOV_FILES := $(SRC:%.cpp=%.gcda)
GCOV_FILES += $(SRC:%.cpp=%.gcno)
RUN_TARGETS := $(TARGETS:%=run_%)
HARNESS := ../test_harness.h
CFLAGS += $(addprefix -I,$(dir $(HARNESS)))
Expand Down Expand Up @@ -38,6 +43,7 @@ help:
clean:
rm -f $(DEPS)
rm -f $(TARGETS)
rm -f $(GCOV_FILES)

run_% : %
@$(call color_out_noline,BROWN, running)
Expand Down
21 changes: 8 additions & 13 deletions tests/flit_src/tst_FlitCsv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
#include "test_harness.h"

#include "FlitCsv.h"
#include "FlitCsv.cpp"

namespace {

Expand Down Expand Up @@ -118,15 +119,14 @@ std::ostream& operator<<(std::ostream& out, flit::CsvRow& row) {
} // end of unnamed namespace

namespace tst_CsvRow {
void tst_CsvRow_header() {
TH_TEST(tst_CsvRow_header) {
flit::CsvRow row {"1", "2", "3", "4"};
TH_EQUAL(row.header(), nullptr);
row.setHeader(&row);
TH_EQUAL(row.header(), &row);
}
TH_REGISTER(tst_CsvRow_header);

void tst_CsvRow_operator_brackets_string() {
TH_TEST(tst_CsvRow_operator_brackets_string) {
flit::CsvRow row {"1", "2", "3", "4"};
flit::CsvRow header {"a", "b", "c", "d"};
row.setHeader(&header);
Expand All @@ -144,9 +144,8 @@ void tst_CsvRow_operator_brackets_string() {
row.setHeader(nullptr);
TH_THROWS(row["a"], std::logic_error);
}
TH_REGISTER(tst_CsvRow_operator_brackets_string);

void tst_CsvRow_operator_brackets_int() {
TH_TEST(tst_CsvRow_operator_brackets_int) {
flit::CsvRow row {"1", "2", "3", "4"};
flit::CsvRow header {"a", "b", "c", "d"};
row.setHeader(&header);
Expand All @@ -166,11 +165,10 @@ void tst_CsvRow_operator_brackets_int() {
TH_EQUAL(row.at(2), "3");
TH_THROWS(row.at(4), std::out_of_range);
}
TH_REGISTER(tst_CsvRow_operator_brackets_int);
} // end of namespace tst_CsvRow

namespace tst_CsvReader {
void tst_CsvReader_oneRowAtATime() {
TH_TEST(tst_CsvReader_oneRowAtATime) {
std::istringstream in(
"first,second,third,fourth\n" // header row
"a, b,c,\n"
Expand Down Expand Up @@ -217,9 +215,8 @@ void tst_CsvReader_oneRowAtATime() {
TH_EQUAL(row, expected_row);
TH_VERIFY(!reader);
}
TH_REGISTER(tst_CsvReader_oneRowAtATime);

void tst_CsvReader_createRowVector() {
TH_TEST(tst_CsvReader_createRowVector) {
std::istringstream in(
"first,second,third,fourth\n" // header row
"a, b,c,\n"
Expand Down Expand Up @@ -251,7 +248,7 @@ void tst_CsvReader_createRowVector() {
namespace tst_CsvWriter {

/// Tests that the CsvWriter will end the file in a newline (if writing rows)
void tst_CsvWriter_write_row_addsNewline() {
TH_TEST(tst_CsvWriter_write_row_addsNewline) {
std::istringstream in(
"first,second,third,fourth\n" // header row
"a, b,c,"
Expand All @@ -268,10 +265,9 @@ void tst_CsvWriter_write_row_addsNewline() {
TH_EQUAL(out.str().back(), '\n');
TH_EQUAL(in.str() + '\n', out.str());
}
TH_REGISTER(tst_CsvWriter_write_row_addsNewline);

/// Tests that CsvWriter can write out the exact same csv read in
void tst_CsvWriter_write_row_exactly() {
TH_TEST(tst_CsvWriter_write_row_exactly) {
std::istringstream in(
"first,second,third,fourth\n" // header row
"a, b,c,\n"
Expand All @@ -291,7 +287,6 @@ void tst_CsvWriter_write_row_exactly() {

TH_EQUAL(in.str(), out.str());
}
TH_REGISTER(tst_CsvWriter_write_row_exactly);

} // end of namespace tst_CsvWriter

Loading

0 comments on commit 15ead85

Please sign in to comment.