Start working on build system.

This commit is contained in:
jmsgrogan 2023-12-20 16:58:22 +00:00
parent 4b308f6c32
commit 521486be62
88 changed files with 1065 additions and 349 deletions

View file

@ -2,19 +2,29 @@
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
SOURCE_DIR=$SCRIPT_DIR/src SOURCE_DIR=$SCRIPT_DIR/src
CORE_SRC_DIR=$SOURCE_DIR/base/core
g++ $SOURCE_DIR/main.cpp \ g++ $SOURCE_DIR/main.cpp \
$SOURCE_DIR/base/core/base_types/Error.cpp \ $CORE_SRC_DIR/base_types/Error.cpp \
$SOURCE_DIR/base/core/base_types/Index.cpp \ $CORE_SRC_DIR/base_types/Index.cpp \
$SOURCE_DIR/base/core/data_structures/String.cpp \ $SOURCE_DIR/base/compiler/BuildLibrary.cpp \
$SOURCE_DIR/base/core/file_utilities/FileSystemPath.cpp \ $SOURCE_DIR/base/compiler/BuildSession.cpp \
$SOURCE_DIR/base/core/file_utilities/File.cpp \ $CORE_SRC_DIR/data_structures/String.cpp \
$SOURCE_DIR/base/core/file_utilities/Directory.cpp \ $CORE_SRC_DIR/encoding/CharUtils.cpp \
$SOURCE_DIR/base/core/encoding/CharUtils.cpp \ $CORE_SRC_DIR/filesystem/FileSystemPath.cpp \
$CORE_SRC_DIR/filesystem/File.cpp \
$CORE_SRC_DIR/filesystem/Directory.cpp \
$CORE_SRC_DIR/logging/ConsoleLogger.cpp \
$CORE_SRC_DIR/logging/Logger.cpp \
$CORE_SRC_DIR/time/Time.cpp \
-o builder -g -fno-exceptions -fno-rtti \ -o builder -g -fno-exceptions -fno-rtti \
-I$SOURCE_DIR/base/core/data_structures \ -I$CORE_SRC_DIR/base_types \
-I$SOURCE_DIR/base/core/base_types \ -I$SOURCE_DIR/base/compiler \
-I$SOURCE_DIR/base/core/memory \ -I$CORE_SRC_DIR/data_structures \
-I$SOURCE_DIR/base/core/loggers \ -I$CORE_SRC_DIR/encoding \
-I$SOURCE_DIR/base/core/encoding \ -I$CORE_SRC_DIR/filesystem \
-I$SOURCE_DIR/base/core/file_utilities -I$CORE_SRC_DIR/logging \
-I$CORE_SRC_DIR/memory \
-I$CORE_SRC_DIR/system/process \
-I$CORE_SRC_DIR/time

View file

@ -0,0 +1,25 @@
#include "BuildLibrary.h"
#include "Logger.h"
#include "Directory.h"
BuildLibrary::BuildLibrary(const FileSystemPath& build_config)
: m_build_config(build_config)
{
}
Status BuildLibrary::scan()
{
LOG_INFO("Scanning build file at: " << m_build_config);
const auto search_dir = m_build_config.parent_path();
const auto status = Directory::getFilesWithExtension(search_dir,
".cpp",
m_sources,
true);
return status;
}
const Vector<FileSystemPath>& BuildLibrary::get_sources() const
{
return m_sources;
}

View file

@ -0,0 +1,22 @@
#pragma once
#include "FileSystemPath.h"
#include "String.h"
class BuildLibrary
{
public:
BuildLibrary() = default;
BuildLibrary(const FileSystemPath& build_config);
Status scan();
const Vector<FileSystemPath>& get_sources() const;
private:
FileSystemPath m_build_config;
Vector<FileSystemPath> m_sources;
Vector<FileSystemPath> m_includes;
String m_name;
};

View file

@ -0,0 +1,73 @@
#include "BuildSession.h"
#include "Logger.h"
#include "Process.h"
#include "Directory.h"
BuildSession::BuildSession(const String& source_dir,
const String& build_dir)
: m_source_dir(source_dir)
{
if (build_dir.empty())
{
m_build_dir = FileSystemPath::current_dir().value();
}
else
{
m_build_dir = build_dir;
}
}
Status BuildSession::scan()
{
LOG_INFO("Scanning sources at:" << m_source_dir);
Vector<FileSystemPath> toml_files;
STATUS_CHECK(Directory::getFilesWithExtension(
m_source_dir,
".toml",
toml_files,
true), "Error looking for build files");
for(const auto& toml_file : toml_files)
{
if (toml_file.file_name() == "build")
{
STATUS_CHECK(add_library(toml_file),
"Error adding library");
}
}
return {};
}
Status BuildSession::add_library(const FileSystemPath& config_path)
{
LOG_INFO("Adding library at: " << config_path);
BuildLibrary lib(config_path);
STATUS_CHECK(lib.scan(), "Error scanning library");
m_libraries.push_back(lib);
return {};
}
Status BuildSession::build()
{
for(const auto& library : m_libraries)
{
for(const auto& source : library.get_sources())
{
String compiler_command = m_compiler_command + " -c ";
compiler_command += source.str() + " ";
LOG_INFO("Running command: " << compiler_command);
const auto self_name = Process::get_self_name();
if (!self_name.ok())
{
return Status(self_name.error());
}
LOG_INFO("Self name is: " << self_name.value());
break;
}
break;
}
return {};
}

View file

@ -0,0 +1,24 @@
#pragma once
#include "BuildLibrary.h"
#include "Error.h"
class BuildSession
{
public:
BuildSession(const String& source_dir,
const String& build_dir = {});
Status scan();
Status build();
Status add_library(const FileSystemPath& config_path);
private:
String m_compiler_command{"g++"};
String m_compiler_flags{"-g -fno-exceptions -fno-rtti"};
FileSystemPath m_source_dir;
FileSystemPath m_build_dir;
Vector<BuildLibrary> m_libraries;
};

View file

@ -1,5 +1,8 @@
#include "Error.h" #include "Error.h"
#include <string.h>
#include <errno.h>
Error::Error(const String& msg) Error::Error(const String& msg)
: m_message(msg) : m_message(msg)
{ {
@ -9,3 +12,32 @@ const String& Error::msg() const
{ {
return m_message; return m_message;
} }
String Error::from_errno()
{
return ::strerror(errno);
}
Status::Status(const Error& err)
: m_error(err),
m_ok(false)
{
}
void Status::on_errno(const String& prefix_msg)
{
String errno_msg(::strerror(errno));
m_error = Error(prefix_msg + " | " + errno_msg);
m_ok = false;
}
const Error& Status::error() const
{
return m_error;
}
bool Status::ok() const
{
return m_ok;
}

View file

@ -2,6 +2,31 @@
#include "String.h" #include "String.h"
#define IF_OK_AND_TRUE(PRED) \
const auto _result = PRED; \
if (!_result.ok()){return Status(_result.error());} \
if (_result.value())
#define ERROR_IF_NOT_OK_OR_TRUE(PRED, msg) \
{const auto _result = PRED; \
if (!_result.ok()){return {_result.error()};} \
if (!_result.value()){return {Error(msg)};}}
#define ON_ERRNO(msg) \
{Status _status; \
_status.on_errno("Failed to get directory content in opendir"); \
return _status;} \
#define ON_ERRNO_RESULT(msg) \
return {Error(_s(msg) + " | " + Error::from_errno())};
#define STATUS_CHECK(PRED, error_msg) \
{const auto _status = PRED; \
if (!_status.ok()){ \
const auto message = _s(error_msg) + "|" + _status.error().msg(); \
return Status(Error(message)); \
}}
class Error class Error
{ {
public: public:
@ -10,6 +35,26 @@ public:
Error() = default; Error() = default;
const String& msg() const; const String& msg() const;
static String from_errno();
private: private:
String m_message; String m_message;
}; };
class Status
{
public:
Status() = default;
Status(const Error& err);
void on_errno(const String& prefix_msg);
const Error& error() const;
bool ok() const;
private:
Error m_error;
bool m_ok{true};
};

View file

@ -6,7 +6,7 @@ template<typename T>
class Result class Result
{ {
public: public:
Result(const T& val) Result(const T& val = T())
: m_value(val) : m_value(val)
{ {
@ -19,6 +19,12 @@ public:
} }
void on_error(const Error& error)
{
m_error = error;
m_ok = false;
}
const Error& error() const const Error& error() const
{ {
return m_error; return m_error;
@ -34,6 +40,11 @@ public:
return m_value; return m_value;
} }
T& value()
{
return m_value;
}
private: private:
T m_value; T m_value;
Error m_error; Error m_error;

View file

@ -1,6 +1,7 @@
#include "String.h" #include "String.h"
#include <stdio.h> #include <stdio.h>
#include <stdarg.h>
String::String() String::String()
{ {
@ -17,6 +18,49 @@ String::String(const char* data)
append(data); append(data);
} }
String String::fmt(const char* fmt, ...)
{
String ret;
va_list args;
va_start(args, fmt);
char format_delim = '%';
bool in_format = false;
while(*fmt != '\0')
{
if (*fmt == format_delim)
{
in_format = true;
}
else if(in_format && *fmt == 's')
{
in_format = false;
const auto s = va_arg(args, char*);
ret.append(s);
}
else if(in_format && *fmt == 'd')
{
in_format = false;
const auto i = va_arg(args, int);
ret += to_string(i);
}
else if(in_format && *fmt == 'c')
{
in_format = false;
const auto c = va_arg(args, int);
ret +=c;
}
else
{
ret += *fmt;
}
++fmt;
}
va_end(args);
return ret;
}
void String::append(const char* data) void String::append(const char* data)
{ {
if (data == nullptr) if (data == nullptr)
@ -26,9 +70,18 @@ void String::append(const char* data)
} }
auto loc = data; auto loc = data;
bool first=true;
while(*loc != '\0') while(*loc != '\0')
{ {
m_data.push_back(*loc); if (!m_data.empty() && first)
{
m_data[m_data.size() - 1] = *loc;
}
else
{
m_data.push_back(*loc);
}
first = false;
loc++; loc++;
} }
m_data.push_back('\0'); m_data.push_back('\0');
@ -46,7 +99,7 @@ bool String::empty() const
void String::append(const Vector<Byte>& data) void String::append(const Vector<Byte>& data)
{ {
if (data.capacity() == 0) if (data.empty())
{ {
m_data.push_back('\0'); m_data.push_back('\0');
return; return;
@ -79,7 +132,7 @@ Pair<String, String> String::rsplit(char c) const
slice(0, index.value(), left); slice(0, index.value(), left);
String right; String right;
slice(index.value(), size(), right); slice(index.value() + 1, size(), right);
return {left, right}; return {left, right};
} }
return {*this, {}}; return {*this, {}};
@ -87,7 +140,7 @@ Pair<String, String> String::rsplit(char c) const
bool String::slice(std::size_t idx, String& out) const bool String::slice(std::size_t idx, String& out) const
{ {
if (idx >= m_data.size() - 1) if (idx >= m_data.size())
{ {
return false; return false;
} }
@ -102,7 +155,7 @@ bool String::slice(std::size_t idx, String& out) const
bool String::slice(std::size_t start, std::size_t end, String& out) const bool String::slice(std::size_t start, std::size_t end, String& out) const
{ {
if (end >= m_data.size() - 1) if (end >= m_data.size())
{ {
return false; return false;
} }
@ -181,6 +234,12 @@ String& String::operator<<(const char* body)
return *this; return *this;
} }
String& String::operator<<(const String& body)
{
*this += body;
return *this;
}
bool String::operator==(const String& other) const bool String::operator==(const String& other) const
{ {
return m_data == other.m_data; return m_data == other.m_data;
@ -193,12 +252,7 @@ bool String::operator!=(const String& other) const
String& String::operator<<(size_t idx) String& String::operator<<(size_t idx)
{ {
/* *this += to_string(idx);
const auto num_digits = static_cast<unsigned>(log10(double(idx))) + 1;
char body[num_digits+1];
snprintf(body, num_digits+1, "%d", static_cast<int>(idx));
append(body);
*/
return *this; return *this;
} }
@ -225,6 +279,10 @@ String String::operator+(const String& str) const
String& String::operator+=(char c) String& String::operator+=(char c)
{ {
if (m_data.empty())
{
m_data.push_back('\0');
}
m_data.push_back('\0'); m_data.push_back('\0');
m_data[m_data.size()-2] = c; m_data[m_data.size()-2] = c;
return *this; return *this;

View file

@ -14,6 +14,10 @@ public:
String(const char* data); String(const char* data);
static String fmt(const char* fmt, ...);
void append(const Vector<Byte>& data);
const Vector<char>& data() const; const Vector<char>& data() const;
bool empty() const; bool empty() const;
@ -36,10 +40,19 @@ public:
char operator[](std::size_t idx) const; char operator[](std::size_t idx) const;
String& operator<<(const String& body);
String& operator<<(const char* body); String& operator<<(const char* body);
String& operator<<(size_t idx); String& operator<<(size_t idx);
template<typename T>
String& operator<<(const T& stringable)
{
*this += stringable.str();
return *this;
}
String& operator+=(const String& str); String& operator+=(const String& str);
String& operator+=(char c); String& operator+=(char c);
@ -51,9 +64,9 @@ public:
bool operator!=(const String& other) const; bool operator!=(const String& other) const;
private: private:
void append(const Vector<Byte>& data);
void append(const char* data); void append(const char* data);
Vector<char> m_data; Vector<char> m_data;
}; };
using _s = String;

View file

@ -12,7 +12,6 @@ public:
Vector(std::size_t size) Vector(std::size_t size)
{ {
resize(size); resize(size);
m_size = size;
} }
Vector(const Vector& v) Vector(const Vector& v)
@ -56,22 +55,20 @@ public:
{ {
v.m_data[idx] = m_data[idx]; v.m_data[idx] = m_data[idx];
} }
v.m_size = slice_idx;
return true; return true;
} }
bool slice(std::size_t slice_start, std::size_t slice_end, Vector& v) const bool slice(std::size_t slice_start, std::size_t slice_end, Vector& v) const
{ {
if (slice_end >= m_size) if (slice_end > m_size)
{ {
return false; return false;
} }
v.resize(slice_end - slice_start); v.resize(slice_end - slice_start);
for(std::size_t idx=slice_start; idx<slice_end;idx++) for(std::size_t idx=slice_start; idx<slice_end;idx++)
{ {
v.m_data[idx] = m_data[idx]; v.m_data[idx - slice_start] = m_data[idx];
} }
v.m_size = slice_end;
return true; return true;
} }
@ -90,36 +87,46 @@ public:
return m_size == 0; return m_size == 0;
} }
void clear() void clear(bool update_sizes=true)
{ {
if (has_allocated()) if (has_allocated())
{ {
m_allocator.delete_array(m_data); m_allocator.delete_array(m_data);
m_data = nullptr; m_data = nullptr;
m_capacity = 0; if (update_sizes)
m_size = 0; {
m_capacity = 0;
m_size = 0;
}
} }
} }
void resize(std::size_t size) void resize(std::size_t size)
{ {
resize_capacity(size); resize_capacity(size);
m_size = size;
} }
void resize(std::size_t size, const T& value) void resize(std::size_t size, const T& value)
{ {
resize_capacity(size); resize_capacity(size);
m_size = size;
fill_with(value); fill_with(value);
} }
void extend(const Vector& other) void extend(const Vector& other)
{ {
resize(m_size + other.m_size); size_t resize_delta{0};
for(std::size_t idx=0;idx<other.m_size;idx++) if (other.m_size > remaining_capacity())
{
resize_delta = other.m_size - remaining_capacity();
resize_capacity(m_capacity + resize_delta);
}
for(size_t idx=0;idx<other.m_size;idx++)
{ {
m_data[idx + m_size] = other[idx]; m_data[idx + m_size] = other[idx];
} }
m_size = m_size + other.m_size; m_size += other.m_size;
} }
T pop_back() T pop_back()
@ -162,7 +169,6 @@ public:
{ {
m_data[idx] = v.m_data[idx]; m_data[idx] = v.m_data[idx];
} }
m_size = v.size();
return *this; return *this;
} }
@ -196,6 +202,11 @@ private:
return m_capacity > 0; return m_capacity > 0;
} }
size_t remaining_capacity() const
{
return m_capacity - m_size;
}
void resize_capacity(std::size_t new_capacity) void resize_capacity(std::size_t new_capacity)
{ {
if (!has_allocated()) if (!has_allocated())
@ -206,23 +217,18 @@ private:
else if (new_capacity != m_capacity) else if (new_capacity != m_capacity)
{ {
auto temp = m_allocator.alloc_array(new_capacity); auto temp = m_allocator.alloc_array(new_capacity);
for(std::size_t idx=0; idx<new_capacity; idx++) auto min_capacity = new_capacity;
if (m_capacity < min_capacity)
{
min_capacity = m_capacity;
}
for(size_t idx=0; idx<min_capacity; idx++)
{ {
temp[idx] = m_data[idx]; temp[idx] = m_data[idx];
} }
auto old_size = m_size; clear(false);
clear();
m_data = temp; m_data = temp;
m_capacity = new_capacity; m_capacity = new_capacity;
m_size = old_size;
if (old_size > m_capacity)
{
m_size = m_capacity;
}
}
else if(m_size != m_capacity)
{
m_size = m_capacity;
} }
} }

View file

@ -1,94 +0,0 @@
#include "Directory.h"
#include <dirent.h>
#include <stdio.h>
#include <sys/stat.h>
Vector<FileSystemPath> Directory::getSubdirectories(const FileSystemPath& path)
{
Vector<FileSystemPath> ret;
auto dirp = ::opendir(path.as_string().raw());
while(auto ep = ::readdir(dirp))
{
auto rel_path = String(ep->d_name);
if (rel_path == "." || rel_path == "..")
{
continue;
}
auto full_path = path.join(rel_path);
struct stat sb;
auto rc = lstat(full_path.as_string().raw(), &sb);
if (rc == -1)
{
printf("Got error");
}
if (S_ISDIR(sb.st_mode))
{
printf("Adding full path: %s\n", full_path.as_string().raw());
ret.push_back(full_path);
}
}
::closedir(dirp);
return ret;
}
Vector<FileSystemPath> Directory::getFiles(const FileSystemPath& path, bool recursive)
{
Vector<FileSystemPath> paths;
if (path.is_directory())
{
for (const auto& entry : getSubdirectories(path))
{
if (entry.is_regular_file())
{
paths.push_back(entry);
}
else if(recursive && entry.is_directory())
{
const auto child_paths = getFiles(entry, recursive);
paths.extend(child_paths);
}
}
}
return paths;
}
Vector<FileSystemPath> Directory::getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive)
{
Vector<FileSystemPath> paths;
if (path.is_directory())
{
for (const auto& entry : getSubdirectories(path))
{
if (entry.is_regular_file() && entry.extension() == extension)
{
paths.push_back(entry);
}
else if(recursive && entry.is_directory())
{
const auto child_paths = getFilesWithExtension(entry, extension, recursive);
paths.extend(child_paths);
}
}
}
return paths;
}
void Directory::create(const FileSystemPath& path, bool existsOk)
{
(void)existsOk;
FileSystemPath working_path;
if (path.is_directory())
{
working_path = path;
}
else
{
working_path = path.parent_path();
}
if (!working_path.exists())
{
//std::filesystem::create_directories(working_path);
}
}

View file

@ -1,16 +0,0 @@
#pragma once
#include "Vector.h"
#include "FileSystemPath.h"
class Directory
{
public:
static Vector<FileSystemPath> getSubdirectories(const FileSystemPath& path);
static void create(const FileSystemPath& path, bool existsOK = false);
static Vector<FileSystemPath> getFiles(const FileSystemPath& path, bool recursive=false);
static Vector<FileSystemPath> getFilesWithExtension(const FileSystemPath& path, const String& extension, bool recursive=false);
};

View file

@ -0,0 +1,128 @@
#include "Directory.h"
#include "ConsoleLogger.h"
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
Status Directory::getDirectoryContents(const FileSystemPath& path, Vector<FileSystemPath>& ret)
{
Status status;
errno = 0;
auto dirp = ::opendir(path.str().raw());
if (dirp == nullptr)
{
ON_ERRNO("Failed to get directory content in opendir");
}
while(auto ep = ::readdir(dirp))
{
auto rel_path = String(ep->d_name);
if (rel_path == "." || rel_path == "..")
{
continue;
}
const auto full_path = path.join(rel_path);
IF_OK_AND_TRUE(full_path.is_regular_file_or_directory())
{
ret.push_back(full_path);
}
}
String errno_msg;
if (errno != 0)
{
errno_msg = "Failed traversing dirp structure | ";
errno_msg += Error::from_errno();
}
errno = 0;
const auto rc = ::closedir(dirp);
if (rc != 0)
{
errno_msg += "Failed to close dirp";
errno_msg += Error::from_errno();
}
if (!errno_msg.empty())
{
return Status(errno_msg);
}
return {};
}
Status Directory::getFiles(const FileSystemPath& path,
Vector<FileSystemPath>& ret,
bool recursive,
const String& extension)
{
const auto is_dir = path.is_directory();
if (!is_dir.ok())
{
return Status(is_dir.error());
}
if (!is_dir.value())
{
return {};
}
Vector<FileSystemPath> dir_contents;
STATUS_CHECK(getDirectoryContents(path, dir_contents),
"Failed to get directory contents");
for (const auto& entry : dir_contents)
{
IF_OK_AND_TRUE(entry.is_regular_file())
{
if (!extension.empty())
{
if (entry.extension() == extension)
{
ret.push_back(entry);
}
}
else
{
LOG_INFO("Adding entry " << entry);
ret.push_back(entry);
}
}
else if(recursive)
{
IF_OK_AND_TRUE(entry.is_directory())
{
Vector<FileSystemPath> child_paths;
STATUS_CHECK(getFiles(entry, child_paths, recursive), "Failed to get files");
ret.extend(child_paths);
}
}
}
return {};
}
Status Directory::getFilesWithExtension(const FileSystemPath& path,
const String& extension,
Vector<FileSystemPath>& ret,
bool recursive)
{
return getFiles(path, ret, recursive, extension);
}
Status Directory::create(const FileSystemPath& path, bool existsOk)
{
(void)existsOk;
FileSystemPath working_path;
if (path.is_directory().value())
{
working_path = path;
}
else
{
working_path = path.parent_path();
}
if (!working_path.exists())
{
//std::filesystem::create_directories(working_path);
}
return {};
}

View file

@ -0,0 +1,24 @@
#pragma once
#include "Vector.h"
#include "FileSystemPath.h"
#include "Result.h"
class Directory
{
public:
static Status getDirectoryContents(const FileSystemPath& path,
Vector<FileSystemPath>& content);
static Status create(const FileSystemPath& path, bool existsOK = false);
static Status getFiles(const FileSystemPath& path,
Vector<FileSystemPath>& content,
bool recursive=false,
const String& extension = {});
static Status getFilesWithExtension(const FileSystemPath& path,
const String& extension,
Vector<FileSystemPath>& content,
bool recursive=false);
};

View file

@ -16,7 +16,7 @@
class FileImpl class FileImpl
{ {
public: public:
void do_open(const FileSystemPath& path, File::AccessMode accessMode) Status do_open(const FileSystemPath& path, File::AccessMode accessMode)
{ {
int flags{0}; int flags{0};
if (accessMode == File::AccessMode::Read) if (accessMode == File::AccessMode::Read)
@ -28,8 +28,15 @@ public:
flags |= O_WRONLY; flags |= O_WRONLY;
flags |= O_CREAT; flags |= O_CREAT;
} }
errno = 0;
m_fd = ::open(path.str().raw(), flags);
if (m_fd < 0)
{
Status ret;
ret.on_errno("Failed to open file with");
return ret;
}
m_fd = ::open(path.as_string().raw(), flags);
if (accessMode == File::AccessMode::Read) if (accessMode == File::AccessMode::Read)
{ {
m_open_for_read = true; m_open_for_read = true;
@ -38,13 +45,22 @@ public:
{ {
m_open_for_write = true; m_open_for_write = true;
} }
return {};
} }
void do_close() Status do_close()
{ {
::close(m_fd); errno = 0;
const auto rc = ::close(m_fd);
if (rc < 0)
{
Status ret;
ret.on_errno("Failed to close file with");
return ret;
}
m_open_for_read = false; m_open_for_read = false;
m_open_for_write = false; m_open_for_write = false;
return {};
} }
bool is_ok() const bool is_ok() const
@ -68,35 +84,56 @@ public:
const auto rc = ::read(m_fd, bytes.data(), bytes.capacity()); const auto rc = ::read(m_fd, bytes.data(), bytes.capacity());
if (rc < 0) if (rc < 0)
{ {
const auto last_err = errno; const auto msg = _s("Error in read impl | ") + Error::from_errno();
String msg(::strerror(last_err));
return Result<std::size_t>(Error(msg)); return Result<std::size_t>(Error(msg));
} }
return Result<std::size_t>(rc); return Result<std::size_t>(rc);
} }
std::size_t do_write(const VecBytes& bytes) Result<std::size_t> do_write(const VecBytes& bytes)
{ {
return ::write(m_fd, bytes.data(), bytes.size()); errno = 0;
const auto rc = ::write(m_fd, bytes.data(), bytes.size());
if (rc < 0)
{
const auto msg = _s("Error in write impl | ") + Error::from_errno();
return Result<std::size_t>(Error(msg));
}
return Result<std::size_t>(rc);
} }
std::size_t do_write(const Vector<char>& bytes, int size = -1) Result<std::size_t> do_write(const Vector<char>& bytes, int size = -1)
{ {
errno = 0;
int rc = 0;
if (size > -1) if (size > -1)
{ {
return ::write(m_fd, bytes.data(), size); rc = ::write(m_fd, bytes.data(), size);
} }
else else
{ {
return ::write(m_fd, bytes.data(), bytes.size()); rc = ::write(m_fd, bytes.data(), bytes.size());
} }
if (rc < 0)
{
const auto msg = _s("Error in write impl | ") + Error::from_errno();
return Result<std::size_t>(Error(msg));
}
return Result<std::size_t>(rc);
} }
void update_size() Status update_size()
{ {
struct stat buf; struct stat buf;
::fstat(m_fd, &buf); const auto rc = ::fstat(m_fd, &buf);
if (rc != 0)
{
Status ret;
ret.on_errno("Failed to get size with fstat");
return ret;
}
m_size = buf.st_size; m_size = buf.st_size;
return {};
} }
bool m_open_for_write{false}; bool m_open_for_write{false};
@ -123,41 +160,77 @@ String File::getExtension() const
return m_path.extension(); return m_path.extension();
} }
bool File::readBinary(VecBytes& buffer) Status File::readBinary(VecBytes& buffer)
{ {
auto ok = open(AccessMode::Read, true); auto status = open(AccessMode::Read, true);
if (!ok) if (!status.ok())
{ {
return false; return status;
} }
m_impl->update_size(); status = m_impl->update_size();
buffer.resize(m_impl->m_size); if (!status.ok())
const auto result = m_impl->do_read(buffer);
buffer.resize(result.value());
return true;
}
String File::readText()
{
VecBytes buffer;
auto ok = open(AccessMode::Read, true);
if (!ok)
{ {
return {}; return status;
} }
m_impl->update_size();
buffer.resize(m_impl->m_size); buffer.resize(m_impl->m_size);
const auto result = m_impl->do_read(buffer); const auto result = m_impl->do_read(buffer);
if (!result.ok()) if (!result.ok())
{ {
printf("Got error: %s\n", result.error().msg()); return Status(result.error());
return {}; }
buffer.resize(result.value());
return {};
}
Status File::readText(String& ret)
{
auto status = open(AccessMode::Read, true);
if (!status.ok())
{
return status;
} }
buffer.resize(result.value()); VecBytes buffer;
return String(buffer); status = m_impl->update_size();
if (status.ok() && m_impl->m_size > 0)
{
buffer.resize(m_impl->m_size);
const auto result = m_impl->do_read(buffer);
if (!result.ok())
{
return Status(result.error());
}
buffer.resize(result.value());
ret.append(buffer);
}
else
{
buffer.resize(1024);
while(true)
{
const auto result = m_impl->do_read(buffer);
if (!result.ok())
{
return Status(result.error());
}
if (result.value() < 1024)
{
if (result.value() > 0)
{
buffer.resize(result.value());
ret.append(buffer);
}
break;
}
else
{
ret.append(buffer);
}
}
}
return {};
} }
String File::dumpBinary() String File::dumpBinary()
@ -192,7 +265,7 @@ String File::dumpBinary()
Optional<Byte> File::readNextByte() Optional<Byte> File::readNextByte()
{ {
if (!open(AccessMode::Read)) if (!open(AccessMode::Read).ok())
{ {
return {}; return {};
} }
@ -216,20 +289,19 @@ Optional<Byte> File::readNextByte()
} }
} }
bool File::open(AccessMode accessMode, bool binary) Status File::open(AccessMode accessMode, bool binary)
{ {
if (m_path.is_absolute() && !m_path.parent_path().exists()) if (m_path.is_absolute() && !m_path.parent_path().exists())
{ {
Directory::create(m_path.parent_path(), true); Directory::create(m_path.parent_path(), true);
} }
m_impl->do_open(m_path, accessMode); return m_impl->do_open(m_path, accessMode);
return true;
} }
void File::close() Status File::close()
{ {
m_impl->do_close(); return m_impl->do_close();
} }
FileFormat::Format File::inferFormat() const FileFormat::Format File::inferFormat() const
@ -239,27 +311,34 @@ FileFormat::Format File::inferFormat() const
return {}; return {};
} }
void File::writeText(const String& text) Status File::writeText(const String& text)
{ {
bool had_to_open{false}; bool had_to_open{false};
Status status;
if (!m_impl->is_open_for_write()) if (!m_impl->is_open_for_write())
{ {
had_to_open = true; had_to_open = true;
m_impl->do_open(m_path, File::AccessMode::Write); status = m_impl->do_open(m_path, File::AccessMode::Write);
if (!status.ok())
{
return status;
}
}
const auto result = m_impl->do_write(text.data(), text.data().size() - 1);
if (!result.ok())
{
return Status(result.error());
} }
m_impl->do_write(text.data(), text.data().size() - 1);
if (had_to_open) if (had_to_open)
{ {
m_impl->do_close(); status = m_impl->do_close();
} }
return status;
} }
Vector<String> File::readLines() Status File::readLines(Vector<String>& lines)
{ {
Vector<String> content;
/* /*
if (!pathExists()) if (!pathExists())
{ {
@ -279,10 +358,10 @@ Vector<String> File::readLines()
close(); close();
*/ */
return content; return {};
} }
String File::read() Status File::read(String& ret)
{ {
/* /*
if (!pathExists()) if (!pathExists())
@ -300,11 +379,10 @@ String File::read()
close(); close();
*/ */
String buffer; return {};
return buffer;
} }
bool File::pathExists() const bool File::exists() const
{ {
return m_path.exists(); return m_path.exists();
} }

View file

@ -23,7 +23,7 @@ public:
~File(); ~File();
void close(); Status close();
String dumpBinary(); String dumpBinary();
@ -31,21 +31,21 @@ public:
FileFormat::Format inferFormat() const; FileFormat::Format inferFormat() const;
String readText(); Status readText(String& buffer);
Vector<String> readLines(); Status readLines(Vector<String>& lines);
String read(); Status read(String& buffer);
bool pathExists() const; bool exists() const;
bool open(AccessMode mode, bool binary = false); Status open(AccessMode mode, bool binary = false);
bool readBinary(VecBytes& bytes); Status readBinary(VecBytes& bytes);
Optional<Byte> readNextByte(); Optional<Byte> readNextByte();
void writeText(const String& text); Status writeText(const String& text);
private: private:
Ptr<FileImpl> m_impl; Ptr<FileImpl> m_impl;

View file

@ -4,26 +4,25 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <errno.h> #include <errno.h>
#include <stdio.h>
FileSystemPath::FileSystemPath()
{
}
FileSystemPath::FileSystemPath(const String& path) FileSystemPath::FileSystemPath(const String& path)
: m_path(path) : m_path(path)
{ {
} }
const String& FileSystemPath::as_string() const const String& FileSystemPath::str() const
{ {
return m_path; return m_path;
} }
Result<bool> FileSystemPath::is_empty() const Result<bool> FileSystemPath::is_empty() const
{ {
if (!is_regular_file()) ERROR_IF_NOT_OK_OR_TRUE(is_regular_file(),
{ "Requested empty check but target is not regular file.");
return {Error("Requested empty check but target is not regular file.")};
}
const auto size_result = get_size(); const auto size_result = get_size();
if (!size_result.ok()) if (!size_result.ok())
{ {
@ -34,21 +33,24 @@ Result<bool> FileSystemPath::is_empty() const
Result<size_t> FileSystemPath::get_size() const Result<size_t> FileSystemPath::get_size() const
{ {
if (!is_regular_file()) ERROR_IF_NOT_OK_OR_TRUE(is_regular_file(),
{ "Requested size check but target is not regular file.");
return {Error("Requested size but target is not regular file.")};
}
struct stat buf; struct stat buf;
::stat(m_path.raw(), &buf); errno = 0;
const auto rc = ::stat(m_path.raw(), &buf);
if (rc != 0)
{
ON_ERRNO_RESULT("Failed to stat file");
}
return buf.st_size; return buf.st_size;
} }
FileSystemPath FileSystemPath::current_dir() Result<FileSystemPath> FileSystemPath::current_dir()
{ {
errno = 0; errno = 0;
const auto path_max = ::pathconf(".", _PC_PATH_MAX); const auto path_max = ::pathconf(".", _PC_PATH_MAX);
std::size_t size{0}; size_t size{0};
if (path_max == -1) if (path_max == -1)
{ {
size = 1024; size = 1024;
@ -63,24 +65,48 @@ FileSystemPath FileSystemPath::current_dir()
} }
Vector<char> buffer(path_max); Vector<char> buffer(path_max);
errno = 0;
const auto ret = ::getcwd(buffer.data(), path_max); const auto ret = ::getcwd(buffer.data(), path_max);
if (ret == nullptr)
{
ON_ERRNO_RESULT("Failed to get cwd");
}
return FileSystemPath(String(buffer.data())); return FileSystemPath(String(buffer.data()));
} }
bool FileSystemPath::is_regular_file() const Result<bool> FileSystemPath::is_regular_file() const
{ {
struct stat path_stat; struct stat path_stat;
::stat(m_path.raw(), &path_stat); const auto rc = ::stat(m_path.raw(), &path_stat);
if (rc != 0)
{
ON_ERRNO_RESULT("Failed to stat file");
}
return S_ISREG(path_stat.st_mode); return S_ISREG(path_stat.st_mode);
} }
bool FileSystemPath::is_directory() const Result<bool> FileSystemPath::is_directory() const
{ {
struct stat path_stat; struct stat path_stat;
::stat(m_path.raw(), &path_stat); const auto rc = ::stat(m_path.raw(), &path_stat);
if (rc != 0)
{
ON_ERRNO_RESULT("Failed to stat file");
}
return S_ISDIR(path_stat.st_mode); return S_ISDIR(path_stat.st_mode);
} }
Result<bool> FileSystemPath::is_regular_file_or_directory() const
{
struct stat path_stat;
const auto rc = ::stat(m_path.raw(), &path_stat);
if (rc != 0)
{
ON_ERRNO_RESULT("Failed to stat file");
}
return S_ISREG(path_stat.st_mode) || S_ISDIR(path_stat.st_mode);
}
bool FileSystemPath::is_absolute() const bool FileSystemPath::is_absolute() const
{ {
return false; return false;
@ -100,6 +126,21 @@ String FileSystemPath::extension() const
return result; return result;
} }
String FileSystemPath::file_name() const
{
String name_and_ext;;
const auto split = m_path.rsplit('/');
if (split.second().empty())
{
name_and_ext = split.first();
}
else
{
name_and_ext = split.second();
}
return name_and_ext.rsplit('.').first();
}
bool FileSystemPath::exists() const bool FileSystemPath::exists() const
{ {
return ::access(m_path.raw(), F_OK) == 0; return ::access(m_path.raw(), F_OK) == 0;
@ -108,7 +149,7 @@ bool FileSystemPath::exists() const
FileSystemPath FileSystemPath::join(const String& entry) const FileSystemPath FileSystemPath::join(const String& entry) const
{ {
auto new_path = *this; auto new_path = *this;
new_path.m_path+=m_delimiter; new_path.m_path += m_delimiter;
new_path.m_path+=entry; new_path.m_path += entry;
return new_path; return new_path;
} }

View file

@ -6,16 +6,18 @@
class FileSystemPath class FileSystemPath
{ {
public: public:
FileSystemPath() = default; FileSystemPath();
FileSystemPath(const String& path); FileSystemPath(const String& path);
const String& as_string() const; const String& str() const;
static FileSystemPath current_dir(); static Result<FileSystemPath> current_dir();
String extension() const; String extension() const;
String file_name() const;
bool exists() const; bool exists() const;
Result<bool> is_empty() const; Result<bool> is_empty() const;
@ -24,9 +26,11 @@ public:
FileSystemPath join(const String& entry) const; FileSystemPath join(const String& entry) const;
bool is_regular_file() const; Result<bool> is_regular_file() const;
bool is_directory() const; Result<bool> is_directory() const;
Result<bool> is_regular_file_or_directory() const;
bool is_absolute() const; bool is_absolute() const;

View file

@ -1,17 +0,0 @@
#include "ConsoleLogger.h"
#include <stdio.h>
#include <stdarg.h>
void ConsoleLogger::logLine(const String& msg)
{
printf("%s\n", msg.raw());
}
void ConsoleLogger::logLine(const char* fmt, ...)
{
va_list(args);
va_start(args, fmt);
vprintf((String(fmt) + "\n").raw(), args);
va_end(args);
}

View file

@ -1,11 +0,0 @@
#pragma once
#include "String.h"
class ConsoleLogger
{
public:
static void logLine(const String& msg);
static void logLine(const char* fmt, ...);
};

View file

@ -0,0 +1,24 @@
#include "ConsoleLogger.h"
#include <stdio.h>
void ConsoleLogger::log_line(Level level,
const String& msg,
const String& fileName,
const String& functionName,
int lineNumber)
{
const auto log_msg = build_log_message(level,
msg,
fileName,
functionName,
lineNumber);
if (level == Level::INFO)
{
printf("%s\n", log_msg.raw());
}
else
{
fprintf(stderr, "%s\n", log_msg.raw());
}
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "Logger.h"
class ConsoleLogger : public Logger
{
public:
void log_line(Level level,
const String& line,
const String& fileName,
const String& functionName,
int lineNumber) override;
};

View file

@ -1,12 +1,5 @@
#pragma once #pragma once
#define MLOG_ALL(msg, level) {String mt_logstream;\
mt_logstream << msg; \
FileLogger::GetInstance().LogLine(level, mt_logstream, __FILE__, __FUNCTION__, __LINE__);};
#define MLOG_INFO(msg) MLOG_ALL(msg, "Info");
#define MLOG_ERROR(msg) MLOG_ALL(msg, "Error");
#include "Pointer.h" #include "Pointer.h"
#include "String.h" #include "String.h"

View file

@ -0,0 +1,48 @@
#include "Logger.h"
#include "Time.h"
#include "ConsoleLogger.h"
static Ptr<Logger> s_logger;
Logger* Logger::get_instance()
{
if (s_logger.get() == nullptr)
{
s_logger = Ptr<ConsoleLogger>::create();
}
return s_logger.get();
}
String Logger::build_log_message(Level level,
const String& msg,
const String& fileName,
const String& functionName,
int lineNumber)
{
String log_msg;
if (level == Level::INFO)
{
log_msg += "Info|";
}
else if (level == Level::ERROR)
{
log_msg += "Error|";
}
log_msg += Time::get_now_str() + "|";
String cleaned_filename;
if (auto index = fileName.rindex('/'); index.valid())
{
fileName.slice(index.value()+1, fileName.size(), cleaned_filename);
}
else
{
cleaned_filename = fileName;
}
log_msg += cleaned_filename + "::";
log_msg += functionName + "::";
log_msg += String::to_string(lineNumber) + "|";
log_msg += msg;
return log_msg;
}

View file

@ -0,0 +1,36 @@
#pragma once
#include "String.h"
#include "Pointer.h"
#define LOG_ALL(msg, level) {String mt_logstream;\
mt_logstream << msg; \
Logger::get_instance()->log_line(level, mt_logstream, __FILE__, __FUNCTION__, __LINE__);};
#define LOG_INFO(msg) LOG_ALL(msg, Logger::Level::INFO);
#define LOG_ERROR(msg) LOG_ALL(msg, Logger::Level::ERROR);
class Logger
{
public:
enum class Level
{
INFO,
ERROR
};
virtual ~Logger() = default;
virtual void log_line(Level level,
const String& line,
const String& fileName,
const String& functionName,
int lineNumber){};
static Logger* get_instance();
protected:
static String build_log_message(Level level,
const String& line,
const String& fileName,
const String& functionName,
int lineNumber);
};

View file

@ -12,7 +12,7 @@ public:
return new T; return new T;
} }
void do_delete(T** p) void do_delete(T* p)
{ {
delete p; delete p;
} }

View file

@ -27,17 +27,28 @@ public:
{ {
if (m_raw != nullptr) if (m_raw != nullptr)
{ {
m_allocator.do_delete(&m_raw); m_allocator.do_delete(m_raw);
} }
} }
Ptr(const Ptr& other) = delete; Ptr(const Ptr& other) = delete;
Ptr(Ptr&& other) Ptr(Ptr&& other)
: m_allocator(std::move(other.m_allocator)),
m_raw(other.m_raw)
{ {
other.m_raw = nullptr; *this = std::move(other);
}
Ptr<T>& operator=(const Ptr<T>& other) = delete;
template<typename U>
Ptr<T>& operator=(Ptr<U>&& other)
{
if (this->m_raw != other.get())
{
this->m_raw = dynamic_cast<T*>(other.get());
other.clear_raw();
}
return *this;
} }
T* get() T* get()
@ -55,6 +66,11 @@ public:
return m_raw; return m_raw;
} }
void clear_raw()
{
m_raw = nullptr;
}
private: private:
Allocator<T> m_allocator; Allocator<T> m_allocator;
T* m_raw{nullptr}; T* m_raw{nullptr};

View file

@ -2,7 +2,9 @@
#include "UnicodeUtils.h" #include "UnicodeUtils.h"
#ifdef _WIN32
#include "Win32BaseIncludes.h" #include "Win32BaseIncludes.h"
#endif
CommandLineArgs::CommandLineArgs() CommandLineArgs::CommandLineArgs()
: mArugments(), : mArugments(),
@ -46,7 +48,7 @@ FileSystemPath CommandLineArgs::getLaunchPath()
void CommandLineArgs::recordLaunchPath() void CommandLineArgs::recordLaunchPath()
{ {
mLaunchPath = FileSystemPath::current_dir(); mLaunchPath = FileSystemPath::current_dir().value();
} }
void CommandLineArgs::process(int argc, char *argv[]) void CommandLineArgs::process(int argc, char *argv[])

View file

@ -0,0 +1,40 @@
#pragma once
#include "String.h"
#include "File.h"
#include "Result.h"
#include <unistd.h>
class Process
{
public:
Status launch(const String& command)
{
const auto pid = fork();
if (pid < 0)
{
ON_ERRNO("Failed to fork");
}
if (pid == 0)
{
//pass
}
return {};
}
static Result<String> get_self_name()
{
FileSystemPath path(String("/proc/self/cmdline"));
File sys_file(path);
Result<String> ret;
const auto rc = sys_file.readText(ret.value());
if (!rc.ok())
{
ret.on_error(rc.error());
}
return ret;
}
};

View file

@ -0,0 +1,29 @@
#include "Time.h"
#include <time.h>
String Time::get_now_str()
{
time_t time_buf{0};
::time(&time_buf);
if (time_buf == -1)
{
return {};
}
struct tm tm_buf;
auto rc = ::gmtime_r(&time_buf, &tm_buf);
if (rc == nullptr)
{
return {};
}
String ret("T");
ret += String::to_string(tm_buf.tm_mday) + ":";
ret += String::to_string(tm_buf.tm_mon) + ":";
const auto year = (tm_buf.tm_year - 100) + 2000;
ret += String::to_string(year) + "Z";
ret += String::to_string(tm_buf.tm_hour) + ":";
ret += String::to_string(tm_buf.tm_min) + ":";
ret += String::to_string(tm_buf.tm_sec);
return ret;
}

View file

@ -0,0 +1,9 @@
#pragma once
#include "String.h"
class Time
{
public:
static String get_now_str();
};

View file

@ -1,43 +1,16 @@
#include "Vector.h" #include "BuildSession.h"
#include "String.h" #include "ConsoleLogger.h"
#include "FileSystemPath.h"
#include "Directory.h"
#include "File.h"
#include <stdio.h> int main(int argc, char** argv)
int main()
{ {
/* if (argc == 1)
FileSystemPath main_path(__FILE__);
printf("Starting build.\n");
auto main_directory = main_path.parent_path();
for(const auto& subdir : Directory::getSubdirectories(main_directory))
{ {
for(const auto& subsubdir : Directory::getSubdirectories(subdir)) LOG_ERROR("Missing arg with path to source dir");
{ return -1;
const auto build_file = subsubdir.join("build.toml");
if (build_file.exists())
{
printf("Found dir file: %s\n", build_file.as_string().raw());
// Gather all files
//const auto header_files = Directory::getFilesWithExtension(subsubdir, ".h", true);
//for(const auto& header : header_files)
//{
// printf("Found header file: %s\n", header.as_string().raw());
// }
// Gather all directories
// Build library
}
}
} }
*/
printf("Finished build.\n");
BuildSession build(argv[1]);
build.scan();
build.build();
return 0; return 0;
} }

View file

@ -3,21 +3,26 @@ SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
CORE_SRC_DIR=$SCRIPT_DIR/../src/base/core CORE_SRC_DIR=$SCRIPT_DIR/../src/base/core
g++ $SCRIPT_DIR/test_runner.cpp \ g++ $SCRIPT_DIR/test_runner.cpp \
$SCRIPT_DIR/../src/base/core/CommandLineArgs.cpp \ $CORE_SRC_DIR/system/process/CommandLineArgs.cpp \
$CORE_SRC_DIR/base_types/Error.cpp \ $CORE_SRC_DIR/base_types/Error.cpp \
$CORE_SRC_DIR/base_types/Index.cpp \ $CORE_SRC_DIR/base_types/Index.cpp \
$CORE_SRC_DIR/data_structures/String.cpp \ $CORE_SRC_DIR/data_structures/String.cpp \
$CORE_SRC_DIR/file_utilities/FileSystemPath.cpp \ $CORE_SRC_DIR/filesystem/FileSystemPath.cpp \
$CORE_SRC_DIR/loggers/ConsoleLogger.cpp \ $CORE_SRC_DIR/logging/Logger.cpp \
$CORE_SRC_DIR/logging/ConsoleLogger.cpp \
$CORE_SRC_DIR/time/Time.cpp \
$SCRIPT_DIR/test_utils/TestCaseRunner.cpp \ $SCRIPT_DIR/test_utils/TestCaseRunner.cpp \
$SCRIPT_DIR/core/TestFileSystemPath.cpp \
$SCRIPT_DIR/core/TestString.cpp \ $SCRIPT_DIR/core/TestString.cpp \
$SCRIPT_DIR/core/TestVector.cpp \ $SCRIPT_DIR/core/TestVector.cpp \
-o bootstrap_tests -g \ -o test_runner -g \
-I$SCRIPT_DIR/test_utils \ -I$SCRIPT_DIR/test_utils \
-I$CORE_SRC_DIR \ -I$CORE_SRC_DIR \
-I$CORE_SRC_DIR/encoding \ -I$CORE_SRC_DIR/encoding \
-I$CORE_SRC_DIR/loggers \ -I$CORE_SRC_DIR/logging \
-I$CORE_SRC_DIR/data_structures \ -I$CORE_SRC_DIR/data_structures \
-I$CORE_SRC_DIR/base_types \ -I$CORE_SRC_DIR/base_types \
-I$CORE_SRC_DIR/memory \ -I$CORE_SRC_DIR/memory \
-I$CORE_SRC_DIR/file_utilities -I$CORE_SRC_DIR/time \
-I$CORE_SRC_DIR/system/process \
-I$CORE_SRC_DIR/filesystem

View file

@ -0,0 +1,18 @@
#include "FileSystemPath.h"
#include "TestFramework.h"
//#include "TestUtils.h"
#include <iostream>
TEST_CASE(FileSystemPath_Join, "core")
{
FileSystemPath path("/home/jgrogan/code/compilz/src/src");
auto new_path = path.join("test");
REQUIRE(new_path.str() == "/home/jgrogan/code/compilz/src/src/test");
}
TEST_CASE(FileSystemPath_Extension, "core")
{
FileSystemPath path("test.dat");
REQUIRE(path.extension() == ".dat");
}

View file

@ -4,7 +4,7 @@
//#include "TestUtils.h" //#include "TestUtils.h"
#include <iostream> #include <iostream>
TEST_CASE(TestBasicStringOps, "core") TEST_CASE(String_Append, "core")
{ {
String str; String str;
str += 'a'; str += 'a';
@ -12,9 +12,10 @@ TEST_CASE(TestBasicStringOps, "core")
str += 'c'; str += 'c';
str += 'd'; str += 'd';
REQUIRE(str == "abcd"); REQUIRE(str == "abcd");
String long_string("abc/def/ghi/jkl");
} }
TEST_CASE(TestStringReverse, "core") TEST_CASE(String_Reverse, "core")
{ {
String str0; String str0;
str0.reverse(); str0.reverse();
@ -37,6 +38,35 @@ TEST_CASE(TestStringReverse, "core")
REQUIRE(str4 == "dcba"); REQUIRE(str4 == "dcba");
} }
TEST_CASE(String_Extend, "core")
{
String str("/home/jgrogan/code/compilz/src/src");
auto str_cpy = str;
str += "/";
str += "test";
REQUIRE(str == String("/home/jgrogan/code/compilz/src/src/test"));
str_cpy += "/";
str_cpy += "test";
REQUIRE(str == str_cpy);
}
TEST_CASE(String_Slice, "core")
{
String str("test.dat");
const auto rindex = str.rindex('.');
REQUIRE(rindex.valid());
REQUIRE(rindex.value() == 4);
String right;
str.slice(rindex.value(), str.size(), right);
REQUIRE(right == ".dat");
const auto split = str.rsplit('.');
REQUIRE(split.first() == "test");
REQUIRE(split.second() == "dat");
}
/* /*
TEST_CASE(TestStringUtils_StripSurroundingWhitepsace, "core") TEST_CASE(TestStringUtils_StripSurroundingWhitepsace, "core")
{ {

View file

@ -4,15 +4,38 @@
#include <stdio.h> #include <stdio.h>
TEST_CASE(TestVectorOps, "core") TEST_CASE(TestVectorExtend, "core")
{ {
Vector<size_t> vec; Vector<size_t> vec;
for(size_t idx=0;idx<100;idx++) for(size_t idx=0; idx<16; idx++)
{ {
vec.push_back(idx); vec.push_back(idx);
} }
for(size_t idx=0; idx<100; idx++) REQUIRE(vec.size() == 16);
Vector<size_t> vec0;
for(size_t idx=16; idx<19; idx++)
{ {
REQUIRE(vec[idx] == idx); vec0.push_back(idx);
} }
vec.extend(vec0);
REQUIRE(vec.size() == 19);
}
TEST_CASE(TestVectorSlize, "core")
{
Vector<size_t> vec;
for(size_t idx=0; idx<8; idx++)
{
vec.push_back(idx);
}
Vector<size_t> bottom_half;
vec.slice(4, bottom_half);
REQUIRE(bottom_half.size() == 4);
Vector<size_t> top_half;
vec.slice(4, 8, top_half);
REQUIRE(top_half.size() == 4);
} }

View file

@ -1,7 +1,7 @@
#include "TestFramework.h" #include "TestFramework.h"
#include "CommandLineArgs.h" #include "CommandLineArgs.h"
#include "ConsoleLogger.h" #include "Logger.h"
#ifdef _WIN32 #ifdef _WIN32
#include <windows.h> #include <windows.h>
@ -17,9 +17,9 @@ int main(int argc, char *argv[])
CommandLineArgs args; CommandLineArgs args;
args.process(argc, argv); args.process(argc, argv);
ConsoleLogger::logLine("Starting test run."); LOG_INFO("Starting test run.");
TestCaseRunner::getInstance().run(args.getUserArgs()); TestCaseRunner::getInstance().run(args.getUserArgs());
ConsoleLogger::logLine("Finished test run."); LOG_INFO("Finished test run.");
#ifdef _WIN32 #ifdef _WIN32
CoUninitialize(); CoUninitialize();

View file

@ -1,7 +1,7 @@
#include "TestCaseRunner.h" #include "TestCaseRunner.h"
#include "FileLogger.h" #include "FileLogger.h"
#include "ConsoleLogger.h" #include "Logger.h"
//#include "TestUiApplication.h" //#include "TestUiApplication.h"
bool TestCaseRunner::sLastTestFailed = false; bool TestCaseRunner::sLastTestFailed = false;
@ -66,22 +66,22 @@ bool TestCaseRunner::run(const Vector<String>& args)
} }
sLastTestFailed = false; sLastTestFailed = false;
ConsoleLogger::logLine("TestFramework: Running Test - %s", test_case->getName().raw()); LOG_INFO("TestFramework: Running Test - " << test_case->getName());
test_case->run(); test_case->run();
if (sLastTestFailed) if (sLastTestFailed)
{ {
ConsoleLogger::logLine("Failed at line %s", sFailureLine.raw()); LOG_INFO("Failed at line: " << sFailureLine);
mFailingTests.push_back(test_case->getName()); mFailingTests.push_back(test_case->getName());
} }
} }
if (mFailingTests.size() > 0) if (mFailingTests.size() > 0)
{ {
ConsoleLogger::logLine("%d failing tests", mFailingTests.size()); LOG_INFO(String::fmt("%d failing tests", mFailingTests.size()));
for(const auto& name : mFailingTests) for(const auto& name : mFailingTests)
{ {
ConsoleLogger::logLine(name); LOG_INFO(name);
} }
} }

View file

@ -20,7 +20,8 @@ struct Holder
if(!bool(predicate)) \ if(!bool(predicate)) \
{ \ { \
const auto msg = String::to_string(__LINE__) + String(" with check: '") + String(#predicate) + String("'"); \ const auto msg = String::to_string(__LINE__) + String(" with check: '") + String(#predicate) + String("'"); \
TestCaseRunner::getInstance().markTestFailure(msg); \ TestCaseRunner::getInstance().markTestFailure(msg); \
return; \
} \ } \