Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dbjdbj no boost #32

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
401 changes: 240 additions & 161 deletions cli/cli.h

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions cli/cliasyncsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,21 +32,21 @@

#include <string>
#include <boost/asio.hpp>
#include "cli.h" // CliSession
#include "cli.h" // cli_session_type

namespace cli
{

class CliAsyncSession : public CliSession
class cli_async_session : public cli_session_type
{
public:
CliAsyncSession( boost::asio::io_service& ios, Cli& cli ) :
CliSession(cli, std::cout, 1),
cli_async_session( boost::asio::io_service& ios, Cli& cli ) :
cli_session_type(cli, std::cout, 1),
input( ios, ::dup( STDIN_FILENO ) )
{
Read();
}
~CliAsyncSession()
~cli_async_session()
{
input.close();
}
Expand Down
8 changes: 4 additions & 4 deletions cli/clifilesession.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,17 @@
#include <string>
#include <iostream>
#include <stdexcept> // std::invalid_argument
#include "cli.h" // CliSession
#include "cli.h" // cli_session_type

namespace cli
{

class CliFileSession : public CliSession
class cli_file_session : public cli_session_type
{
public:
/// @throw std::invalid_argument if @c _in or @c out are invalid streams
CliFileSession(Cli& cli, std::istream& _in=std::cin, std::ostream& out=std::cout) :
CliSession(cli, out, 1),
cli_file_session(cli_type& cli, std::istream& _in=std::cin, std::ostream& out=std::cout) :
cli_session_type(cli, out, 1),
exit(false),
in(_in)
{
Expand Down
14 changes: 8 additions & 6 deletions cli/clilocalsession.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,22 @@
#ifndef CLILOCALSESSION_H_
#define CLILOCALSESSION_H_

// dbj added
#define _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS
#include <boost/asio.hpp>
#include "keyboard.h"
#include "inputhandler.h"
#include "cli.h" // CliSession
#include "cli.h" // cli_session_type

namespace cli
{

class CliLocalTerminalSession : public CliSession
class cli_local_terminal_session : public cli_session_type
{
public:

CliLocalTerminalSession(Cli& _cli, boost::asio::io_service& ios, std::ostream& _out, std::size_t historySize = 100) :
CliSession(_cli, _out, historySize),
cli_local_terminal_session(cli_type& _cli, boost::asio::io_service& ios, std::ostream& _out, std::size_t historySize = 100) :
cli_session_type(_cli, _out, historySize),
kb(ios),
ih(*this, kb)
{
Expand All @@ -52,10 +54,10 @@ class CliLocalTerminalSession : public CliSession

private:
Keyboard kb;
InputHandler ih;
input_handler ih;
};

using CliLocalSession = CliLocalTerminalSession;
using cli_local_session = cli_local_terminal_session;

} // namespace cli

Expand Down
18 changes: 18 additions & 0 deletions cli/dbj/LICENCE.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
/*
Copyright 2017,2018,2019 by dbj@dbj.org

Licensed under the GNU GPL License, Version 3.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License in the file LICENSE enclosed in
this project.

https://www.gnu.org/licenses/gpl-3.0.html

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

85 changes: 85 additions & 0 deletions cli/dbj/dbj_algo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#pragma once
#include "LICENCE.h"

#if __cplusplus < 201703
#include "string_veiw.h"
#endif

#include <algorithm>

namespace dbj {
namespace algorithm {

// NOTE: wherever possible I am using string_view
#if __cplusplus < 201703
using bpstd::string_view ; // back-port std project
#endif

using namespace std;
using string_vector = vector<string>;

// synopsis:
// dbj::algorithm::starts_with(name, line)
// returns true if line strate with name
// NOTE: this should work with C++11 also
inline bool starts_with(string_view prefix, string_view text)
{
if ((prefix.size() > text.size())) return false;
return (
std::equal(prefix.begin(), prefix.end(), text.begin())
);
}

namespace {
// anonymous ns makes this static in essence
char const * white_space = " \t\n\r\f\v";
// I had to do this since inline globals have not
// appeared before C++17
}
// dbj note: string_view remove_prexif and removse_suffix are
// simplifying and speeding up things here considerably
inline string trim_left(string_view text, char const * t = white_space) {
text.remove_prefix(text.find_first_not_of(t));
return text.data();
}

inline string trim_right(string_view text, char const * t = white_space) {
text.remove_suffix(text.find_last_not_of(t) + 1);
return text.data();
}

inline string trim(string_view text, char const * t = white_space) {

return trim_left(trim_right(text, t), t);
}

// https://github.com/fenbf/StringViewTests/blob/master/StringViewTest.cpp
// works on pointers rather than iterators
// code by JFT
// DBJ: changed argument types to be string_view, not string
// now this is even faster
string_vector fast_string_split(
const string_view & str,
const string_view & delims = " \t\v\n\r\f"
)
{
string_vector output;
//output.reserve(str.size() / 2);

for (
auto first = str.data(), second = str.data(), last = first + str.size();
second != last && first != last;
first = second + 1)
{
second = std::find_first_of(
first, last, std::cbegin(delims), std::cend(delims)
);

if (first != second)
output.emplace_back(first, second);
}

return output;
}
}
} // dbj
196 changes: 196 additions & 0 deletions cli/dbj/dbj_buf.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
#pragma once

#define DBJ_BUFFER_TESTING

#include "LICENCE.h"
#include "dbj_insider.h"

#include <system_error>
#include <cassert>
#include <memory>
#include <string_view>
#include <type_traits>
#include <cstdint>
#include <cstddef>
#include <cstring>

// 2019-01-30 dbj@dbj.org created
//
// char runtime dynamic buffer type
// faster and lighter vs the usual suspects: string and vector
// note: this is part of the core , thus we will try and absolutely minimise
// the dependancies thus we will sometimes
// reimplement things here which perhaps exist in other projects
//
// note: this is not C++17 way of doing things
// so that good legacy code can enjoy this too

namespace dbj {
namespace buf {
#if __cplusplus < 201703
using bpstd::string_view; // back-port std project
#endif
// plenty of space -- 65535
// in posix terms BUFSIZ * 2 * 64 aka 64KB
constexpr std::size_t max_length = UINT16_MAX;

namespace {
using namespace ::dbj::util;
using inside_1_and_max =
insider<size_t, 1,
::dbj::buf::max_length
, insider_error_code_throw_policy
>;
}

struct unique_arr_ptr final
{
using value_type = char;
using type = std::unique_ptr<char[]>;
using ref_type = type & ;
};

using buff_type = typename unique_arr_ptr::type;
using buff_ref_type = typename unique_arr_ptr::ref_type;

// always use this function to make_buff fresh buff_type-es!
DBJ_NODISCARD inline buff_type make_buff (inside_1_and_max size_) noexcept
{
return std::make_unique<char[]>(size_ + 1);
}

DBJ_NODISCARD inline auto length(buff_ref_type buf_ref_)
noexcept -> inside_1_and_max
{
return std::strlen(buf_ref_.get());
}

DBJ_NODISCARD inline buff_type assign(char const * first_, char const * last_) noexcept
{
assert( first_ && last_ );
size_t N = std::distance( first_, last_ );
assert(N > 0);
buff_type sp_ = make_buff(N);
auto * rez_ = std::copy(first_, last_, sp_.get() );
assert(rez_);
return sp_; // the move
}

/*
make_buff from array of char's
*/
template<size_t N>
DBJ_NODISCARD inline auto assign(const char(&charr)[N]) noexcept -> buff_type
{
assert(N > 0);
buff_type sp_ = make_buff (N);
void * rez_ = ::memcpy(sp_.get(), charr, N);
assert(rez_);
return sp_; // the move
}

/* make_buff buff_type from string_view */
DBJ_NODISCARD inline auto assign ( string_view sv_) noexcept -> buff_type
{
assert(!sv_.empty());
// is this naive?
// should I use strnlen() ?
inside_1_and_max N = sv_.size();
buff_type sp_ = make_buff (N);
void * rez_ = ::memcpy(sp_.get(), sv_.data(), N);
assert(rez_);
return sp_;
}

/*
make_buff buff_type<C> from buff_type<C>
this is clever since we do not deal
with C *, but... can we rely on the the caller
making a properly zero terminated string in there
so that strlen will work?
*/
DBJ_NODISCARD inline auto assign (buff_ref_type buf_ref_) noexcept -> buff_type
{
buff_type & from_ = buf_ref_;
assert(from_);
inside_1_and_max N = ::dbj::buf::length (buf_ref_);
assert(N > 1);
buff_type sp_ = ::dbj::buf::make_buff (N);
assert(sp_);
void * rez_ = ::memcpy(sp_.get(), buf_ref_.get(), N);
assert(rez_);
return sp_;
}

/*
assign array to instance of unique_ptr<T[]>
note: "any" type will do as long as std::unique_ptr
will accept it
*/
template<typename C, size_t N>
inline auto assign ( std::unique_ptr<C[]> & sp_, const C(&arr)[N]) noexcept -> std::unique_ptr<C[]> &
{
// sp_.release();
sp_ = std::make_unique<C[]>(N + 1);
assert(sp_);
void * rez_ = ::memcpy(sp_.get(), arr, N);
assert(rez_);
return sp_;
}

// do not try this at home. ever.
extern "C" inline void secure_reset(void *s, size_t n) noexcept
{
volatile char *p = (char *)s;
while (n--) *p++ = 0;
}

// dangerously low, but it works
inline buff_ref_type fill( buff_ref_type buff_, char val_ , size_t N = 0 ) noexcept
{
if (!N) N = ::dbj::buf::length(buff_);
::std::fill(buff_.get(), buff_.get() + N, val_ );
return buff_;
}

inline std::ostream & operator << ( std::ostream & os, buff_ref_type the_buffer_ )
{
return os << the_buffer_.get();
}

} // buf
} // dbj

#ifdef DBJ_BUFFER_TESTING
#define TU(x) std::cout << "\nExpression: '" << (#x) << "'\n\tResult: '" << (x) << "'\n"
#include <iostream>

namespace {
inline bool dbj_testing_dbj_unique_ptr_buffer()
{
using namespace ::dbj::buf;
// 1
{
TU( make_buff (BUFSIZ) );
TU( assign("string literall") );
TU( assign(std::string("std::string")) );
TU( assign(dbj::string_view("std::stringview")) );

}
// 2
{
buff_type buff_1 = make_buff(0xF);
// buff_type is a smart pointer
// it does not know its own safe length
TU( fill( buff_1 , '*', 0xF ) ) ;
}
return true;
} // testing_dbj_buffer

static auto dbj_testing_dbj_buffer_result
= dbj_testing_dbj_unique_ptr_buffer();
}

#endif // DBJ_BUFFER_TESTING
#undef TU
#undef DBJ_BUFFER_TESTING