diff --git a/src/env_base.cpp b/src/env_base.cpp index cf956ad..81ccb50 100644 --- a/src/env_base.cpp +++ b/src/env_base.cpp @@ -122,6 +122,11 @@ void EnvBase::set_nolock (EnvBase& obj, std::string_view name, std::string_view obj.set_implem(name, value, m); } +EnvBase::size_type EnvBase::size_nolock(const EnvBase& obj) noexcept { + EmptyMutex m; + return obj.size_implem(m); +} + void EnvBase::clear() noexcept { StdMutex m(this->mutex()); call_noexcept([this,&m](){this->clear_implem(m);}, to_string_view(__func__)); @@ -134,6 +139,11 @@ void EnvBase::clear_nolock (EnvBase& obj) noexcept { return; } +std::unique_ptr EnvBase::to_c_array() const { + StdMutex m(this->mutex()); + return this->to_c_array_implem(m); +} + void EnvBase::set_all_into (EnvBase& other) const { const bool tg = this->is_global(); const bool og = other.is_global(); diff --git a/src/env_base.hpp b/src/env_base.hpp index a5b5187..cccf62e 100644 --- a/src/env_base.hpp +++ b/src/env_base.hpp @@ -22,6 +22,7 @@ #include #include #include +#include namespace duck { class EnvBase; @@ -74,6 +75,7 @@ namespace duck { size_type size() const noexcept; bool empty() const noexcept; void clear() noexcept; + std::unique_ptr to_c_array() const; virtual std::mutex& mutex() const noexcept = 0; @@ -83,14 +85,17 @@ namespace duck { virtual void clear_implem(Mutex& m) = 0; static void clear_nolock (EnvBase& obj) noexcept; - virtual std::optional get_implem (std::string_view name, Mutex& m) const = 0; - virtual std::string_view get_implem (std::string_view name, std::string_view def, Mutex& m) const = 0; virtual void set_implem (std::string_view name, std::string_view value, Mutex& m) = 0; static void set_nolock (EnvBase& obj, std::string_view name, std::string_view value); + virtual size_type size_implem(Mutex& m) const noexcept = 0; + static size_type size_nolock(const EnvBase& obj) noexcept; + virtual void unset_implem (std::string_view name, Mutex& m) = 0; virtual bool is_set_implem (std::string_view name, Mutex& m) const = 0; - virtual size_type size_implem(Mutex& m) const = 0; + virtual std::optional get_implem (std::string_view name, Mutex& m) const = 0; + virtual std::string_view get_implem (std::string_view name, std::string_view def, Mutex& m) const = 0; + virtual std::unique_ptr to_c_array_implem (Mutex& m) const = 0; virtual bool is_global() const noexcept = 0; virtual uint32_t class_identifier() const noexcept = 0; @@ -119,5 +124,4 @@ namespace duck { return (*m_env)[m_name]; } } //namespace detail - } //namespace duck diff --git a/src/env_fake.cpp b/src/env_fake.cpp index 4e4389e..82c2b95 100644 --- a/src/env_fake.cpp +++ b/src/env_fake.cpp @@ -20,6 +20,7 @@ #include "safe_print.hpp" #include "string_view_cat.hpp" #include "StringCRC32.hpp" +#include "env_to_c_array.hpp" #include #include #include @@ -125,7 +126,7 @@ bool EnvFake::is_set_implem (std::string_view name, Mutex& m) const { return run_if_found(m_map, name, [](auto&)noexcept{return true;}); } -auto EnvFake::size_implem (Mutex& m) const -> size_type { +auto EnvFake::size_implem (Mutex& m) const noexcept -> size_type { std::lock_guard lock(m); return m_map.size(); } @@ -173,4 +174,9 @@ EnvFake& EnvFake::operator= (const EnvBase& other) { uint32_t EnvFake::class_identifier() const noexcept { return duckcore::StringCRC32(__func__); } + +std::unique_ptr EnvFake::to_c_array_implem (Mutex& m) const { + std::scoped_lock lock(m); + return env_to_c_array(*this, EnvBase::size_nolock(*this)); +} } //namespace duck diff --git a/src/env_fake.hpp b/src/env_fake.hpp index 566f0f3..489daf4 100644 --- a/src/env_fake.hpp +++ b/src/env_fake.hpp @@ -48,7 +48,8 @@ namespace duck { virtual void set_implem (std::string_view name, std::string_view value, Mutex& m) override; virtual void unset_implem (std::string_view name, Mutex& m) override; virtual bool is_set_implem (std::string_view name, Mutex& m) const override; - virtual size_type size_implem (Mutex& m) const override; + virtual size_type size_implem (Mutex& m) const noexcept override; + virtual std::unique_ptr to_c_array_implem (Mutex& m) const override; virtual bool is_global() const noexcept override { return false; } virtual uint32_t class_identifier() const noexcept override; diff --git a/src/env_real.cpp b/src/env_real.cpp index cccbf02..68cdfd6 100644 --- a/src/env_real.cpp +++ b/src/env_real.cpp @@ -22,6 +22,7 @@ #include "string_view_cat.hpp" #include "safe_print.hpp" #include "StringCRC32.hpp" +#include "env_to_c_array.hpp" #include #include #include @@ -276,7 +277,7 @@ bool EnvReal::is_set_implem (std::string_view name, Mutex& m) const { ); } -auto EnvReal::size_implem (Mutex& m) const -> size_type { +auto EnvReal::size_implem (Mutex& m) const noexcept -> size_type { std::lock_guard lock(m); assert(environ); @@ -347,4 +348,9 @@ void EnvReal::set_all_into_implem (EnvBase& other) const { uint32_t EnvReal::class_identifier() const noexcept { return duckcore::StringCRC32(__func__); } + +std::unique_ptr EnvReal::to_c_array_implem (Mutex& m) const { + std::scoped_lock lock(m); + return env_to_c_array(*this, EnvBase::size_nolock(*this)); +} } //namespace duck diff --git a/src/env_real.hpp b/src/env_real.hpp index ceec3c5..b3d4b5d 100644 --- a/src/env_real.hpp +++ b/src/env_real.hpp @@ -69,7 +69,8 @@ namespace duck { virtual void set_implem (std::string_view name, std::string_view value, Mutex& m) override; virtual void unset_implem (std::string_view name, Mutex& m) override; virtual bool is_set_implem (std::string_view name, Mutex& m) const override; - virtual size_type size_implem(Mutex& m) const override; + virtual size_type size_implem(Mutex& m) const noexcept override; + virtual std::unique_ptr to_c_array_implem (Mutex& m) const override; virtual bool is_global() const noexcept override { return true; } virtual uint32_t class_identifier() const noexcept override; diff --git a/src/env_to_c_array.hpp b/src/env_to_c_array.hpp new file mode 100644 index 0000000..7a0f6cb --- /dev/null +++ b/src/env_to_c_array.hpp @@ -0,0 +1,61 @@ +/* Copyright 2020, Michele Santullo + * This file is part of user-gcc. + * + * User-gcc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * User-gcc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with user-gcc. If not, see . + */ + +#pragma once + +#include "env_base.hpp" +#include +#include +#include +#include + +namespace duck { + template + inline std::unique_ptr env_to_c_array (const E& env, typename E::size_type count) { + using std::pair; + using std::string_view; + typedef typename E::size_type size_type; + + const size_type all_str_size = std::accumulate( + env.begin(), + env.end(), + size_type{0}, + [](size_type s, const pair& itm) { + return s + itm.first.size() + itm.second.size() + 1 + 1; + } + ); + + auto buff = std::make_unique(count + 1 + (all_str_size + sizeof(char*) - 1) / sizeof(char*)); + size_type z = 0; + char* curr_str = reinterpret_cast(buff.get() + count + 1); + for (const auto& itm : env) { + std::copy(itm.first.begin(), itm.first.end(), curr_str); + curr_str[itm.first.size()] = '='; + std::copy(itm.second.begin(), itm.second.end(), curr_str + itm.first.size() + 1); + const std::size_t curr_size = itm.first.size() + itm.second.size() + 1 + 1; + curr_str[curr_size - 1] = '\0'; + assert(z < count); + buff[z] = curr_str; + + curr_str += curr_size; + ++z; + } + + buff[count] = nullptr; + return buff; + } +} //namespace duck