From d00dc2c69164d8a8850d317f2868c6f131b7f679 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Mon, 2 Jan 2023 16:32:01 +0100 Subject: First lib version --- Makefile | 44 +++++++++++++++++++++++++++ common.mk | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ debian/README.Debian | 13 ++++++++ debian/changelog | 5 ++++ debian/compat | 1 + debian/control | 16 ++++++++++ debian/copyright | 4 +++ debian/rules | 4 +++ debian/source/format | 1 + file.cpp | 46 ++++++++++++++++++++++++++++ file.h | 15 ++++++++++ mime.cpp | 41 +++++++++++++++++++++++++ mime.h | 5 ++++ stringutil.cpp | 66 ++++++++++++++++++++++++++++++++++++++++ stringutil.h | 10 +++++++ tempfile.cpp | 42 ++++++++++++++++++++++++++ tempfile.h | 17 +++++++++++ url.cpp | 32 ++++++++++++++++++++ url.h | 6 ++++ 19 files changed, 453 insertions(+) create mode 100644 Makefile create mode 100644 common.mk create mode 100644 debian/README.Debian create mode 100644 debian/changelog create mode 100644 debian/compat create mode 100644 debian/control create mode 100644 debian/copyright create mode 100755 debian/rules create mode 100644 debian/source/format create mode 100644 file.cpp create mode 100644 file.h create mode 100644 mime.cpp create mode 100644 mime.h create mode 100644 stringutil.cpp create mode 100644 stringutil.h create mode 100644 tempfile.cpp create mode 100644 tempfile.h create mode 100644 url.cpp create mode 100644 url.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..fe17e98 --- /dev/null +++ b/Makefile @@ -0,0 +1,44 @@ +include common.mk + +PROJECTNAME=libreichwein + +CXXFLAGS+= -fvisibility=hidden -fPIC + +PROGSRC=\ + file.cpp \ + mime.cpp \ + stringutil.cpp \ + tempfile.cpp \ + url.cpp + +SRC=$(PROGSRC) +HEADERS=$(PROGSRC:.cpp=.h) + +all: $(PROJECTNAME).a + +install: + mkdir -p $(DESTDIR)/usr/lib + cp $(PROJECTNAME).a $(DESTDIR)/usr/lib/ + mkdir -p $(DESTDIR)/usr/include/libreichwein + cp $(HEADERS) $(DESTDIR)/usr/include/libreichwein/ + +$(PROJECTNAME).a: $(SRC:.cpp=.o) + ar rcs $@ $^ + +%.d: %.cpp + $(CXX) $(CXXFLAGS) -MM -MP -MF $@ -c $< + +%.o: %.cpp %.d + $(CXX) $(CXXFLAGS) -c $< -o $@ + +# dependencies + +ADD_DEP=Makefile + +# misc --------------------------------------------------- +clean: + -rm -f *.o *.a *.d + +.PHONY: clean all install + +-include $(wildcard $(SRC:.cpp=.d)) diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..0b5c4d8 --- /dev/null +++ b/common.mk @@ -0,0 +1,85 @@ +CXX=clang++-14 + +ifeq ($(shell which $(CXX)),) +CXX=clang++-13 +endif + +ifeq ($(shell which $(CXX)),) +CXX=clang++-11 +endif + +ifeq ($(shell which $(CXX)),) +CXX=g++-11 +endif + +ifeq ($(shell which $(CXX)),) +CXX=g++-10 +endif + +ifeq ($(shell which $(CXX)),) +CXX=g++-8 +endif + +ifeq ($(shell which $(CXX)),) +CXX=clang++ +endif + +ifeq ($(shell which $(CXX)),) +CXX=g++-10 +endif + +ifeq ($(shell which $(CXX)),) +CXX=g++-9 +endif + +ifeq ($(shell which $(CXX)),) +CXX=g++ +endif + +ifeq ($(LINK_STATICALLY),1) +LDFLAGS+=-static +endif + +ifeq ($(CXXFLAGS),) +CXXFLAGS=-O2 -g -DNDEBUG +#CXXFLAGS=-O0 -g -D_DEBUG +endif +# -fprofile-instr-generate -fcoverage-mapping +# gcc:--coverage + +CXXFLAGS+=-Wall -I. + +ifeq ($(CXX),clang++-11) +CXXFLAGS+=-std=c++20 #-stdlib=libc++ +else ifeq ($(CXX),clang++-14) +CXXFLAGS+=-std=c++2b #-stdlib=libc++ +else ifeq ($(CXX),clang++-13) +CXXFLAGS+=-std=c++2b #-stdlib=libc++ +else ifeq ($(CXX),g++-11) +CXXFLAGS+=-std=c++20 #-stdlib=libc++ +else +CXXFLAGS+=-std=c++17 +endif + +ifeq ($(CXX),clang++-11) +LIBS+= \ +-fuse-ld=lld-11 \ +-lstdc++ +#-lc++ \ +#-lc++abi +#-lc++fs +#-lstdc++fs +else ifeq ($(CXX),clang++-14) +LIBS+= \ +-fuse-ld=lld-14 \ +-lstdc++ +else ifeq ($(CXX),clang++-13) +LIBS+= \ +-fuse-ld=lld-13 \ +-lstdc++ +else +LIBS+= \ +-lstdc++ \ +-lstdc++fs +endif + diff --git a/debian/README.Debian b/debian/README.Debian new file mode 100644 index 0000000..38d75c5 --- /dev/null +++ b/debian/README.Debian @@ -0,0 +1,13 @@ +libreichwein for Debian +======================= + +libreichwein is a C++ library developed by Reichwein.IT and +used by several Reichwein.IT projects, including functions +not available in std or boost. + + +Contact +------- + +Reichwein IT + diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..1efd71a --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +libreichwein (1.0) unstable; urgency=medium + + * Initial release + + -- Roland Reichwein Mon, 02 Jan 2023 16:23:38 +0100 diff --git a/debian/compat b/debian/compat new file mode 100644 index 0000000..48082f7 --- /dev/null +++ b/debian/compat @@ -0,0 +1 @@ +12 diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..bf2df7b --- /dev/null +++ b/debian/control @@ -0,0 +1,16 @@ +Source: libreichwein +Section: devel +Priority: optional +Maintainer: Roland Reichwein +Build-Depends: debhelper (>= 12), libboost-all-dev | libboost1.71-all-dev, clang | g++-9, llvm | g++-9, lld | g++-9, pkg-config, googletest +Standards-Version: 4.5.0 +Homepage: http://www.reichwein.it/libreichwein/ + +Package: libreichwein-dev +Architecture: any +Depends: ${shlibs:Depends}, ${misc:Depends} +Homepage: http://www.reichwein.it/libreichwein/ +Description: C++ Library by Reichwein.IT + libreichwein is a C++ library developed by Reichwein.IT and + used by several Reichwein.IT projects, including functions + not available in std or boost. diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..a50fc15 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,4 @@ +Author: Roland Reichwein , 2023 + +Both upstream source code and Debian packaging is available +under the conditions of CC0 1.0 Universal diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..2d33f6a --- /dev/null +++ b/debian/rules @@ -0,0 +1,4 @@ +#!/usr/bin/make -f + +%: + dh $@ diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..89ae9db --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (native) diff --git a/file.cpp b/file.cpp new file mode 100644 index 0000000..47ab8be --- /dev/null +++ b/file.cpp @@ -0,0 +1,46 @@ +#include "file.h" + +#include + +namespace fs = std::filesystem; + +using namespace std::string_literals; + +std::string File::getFile(const fs::path& filename) +{ + std::ifstream file(filename.string(), std::ios::in | std::ios::binary | std::ios::ate); + + if (file.is_open()) { + std::ifstream::pos_type fileSize = file.tellg(); + file.seekg(0, std::ios::beg); + + std::string bytes(fileSize, ' '); + file.read(reinterpret_cast(bytes.data()), fileSize); + + return bytes; + + } else { + throw std::runtime_error("Opening "s + filename.string() + " for reading"); + } +} + +void File::setFile(const fs::path& filename, const std::string& s) +{ + File::setFile(filename, s.data(), s.size()); +} + +void File::setFile(const fs::path& filename, const char* data, size_t size) +{ + std::ofstream file(filename.string(), std::ios::out | std::ios::binary); + if (file.is_open()) { + file.write(data, size); + } else { + throw std::runtime_error("Opening "s + filename.string() + " for writing"); + } +} + +void File::setFile(const fs::path& filename, const std::vector& data) +{ + File::setFile(filename, reinterpret_cast(data.data()), data.size()); +} + diff --git a/file.h b/file.h new file mode 100644 index 0000000..e7e4cf6 --- /dev/null +++ b/file.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include +#include +#include + +namespace File { + +std::string getFile(const std::filesystem::path& filename); +void setFile(const std::filesystem::path& filename, const std::string& s); +void setFile(const std::filesystem::path& filename, const char* data, size_t size); +void setFile(const std::filesystem::path& filename, const std::vector& data); + +} diff --git a/mime.cpp b/mime.cpp new file mode 100644 index 0000000..f64d046 --- /dev/null +++ b/mime.cpp @@ -0,0 +1,41 @@ +#include "mime.h" + +#include +#include + +namespace beast = boost::beast; + +// Return a reasonable mime type based on the extension of a file. +std::string mime_type(const std::string& path) +{ + auto const ext = [&path] + { + auto const pos = path.rfind("."); + if (pos == std::string::npos) + return std::string{}; + return path.substr(pos); + }(); + if(boost::algorithm::istarts_with(ext, ".htm")) return "text/html"; + if(boost::algorithm::istarts_with(ext, ".html")) return "text/html"; + if(boost::algorithm::istarts_with(ext, ".php")) return "text/html"; + if(boost::algorithm::istarts_with(ext, ".css")) return "text/css"; + if(boost::algorithm::istarts_with(ext, ".txt")) return "text/plain"; + if(boost::algorithm::istarts_with(ext, ".js")) return "application/javascript"; + if(boost::algorithm::istarts_with(ext, ".json")) return "application/json"; + if(boost::algorithm::istarts_with(ext, ".xml")) return "application/xml"; + if(boost::algorithm::istarts_with(ext, ".swf")) return "application/x-shockwave-flash"; + if(boost::algorithm::istarts_with(ext, ".flv")) return "video/x-flv"; + if(boost::algorithm::istarts_with(ext, ".png")) return "image/png"; + if(boost::algorithm::istarts_with(ext, ".jpe")) return "image/jpeg"; + if(boost::algorithm::istarts_with(ext, ".jpeg")) return "image/jpeg"; + if(boost::algorithm::istarts_with(ext, ".jpg")) return "image/jpeg"; + if(boost::algorithm::istarts_with(ext, ".gif")) return "image/gif"; + if(boost::algorithm::istarts_with(ext, ".bmp")) return "image/bmp"; + if(boost::algorithm::istarts_with(ext, ".ico")) return "image/vnd.microsoft.icon"; + if(boost::algorithm::istarts_with(ext, ".tiff")) return "image/tiff"; + if(boost::algorithm::istarts_with(ext, ".tif")) return "image/tiff"; + if(boost::algorithm::istarts_with(ext, ".svg")) return "image/svg+xml"; + if(boost::algorithm::istarts_with(ext, ".svgz")) return "image/svg+xml"; + return "application/text"; +} + diff --git a/mime.h b/mime.h new file mode 100644 index 0000000..c05eb45 --- /dev/null +++ b/mime.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +std::string mime_type(const std::string& path); diff --git a/stringutil.cpp b/stringutil.cpp new file mode 100644 index 0000000..f87fa00 --- /dev/null +++ b/stringutil.cpp @@ -0,0 +1,66 @@ +#include "stringutil.h" + +#include +#include + +#include + +std::string strfmt(const char* fmt, ...) +{ + va_list args; + + va_start(args, fmt); + int size = std::vsnprintf(nullptr, 0, fmt, args); + va_end(args); + + std::string result(size, ' '); + + va_start(args, fmt); + std::vsnprintf(result.data(), size + 1, fmt, args); + va_end(args); + + return result; +} + +std::vector split(std::string value, const std::string separators) +{ + std::vector result; + + size_t pos0 = 0; + size_t pos1 = 0; + while (pos0 < value.size()) { + pos1 = value.find_first_of(separators, pos0); + if (pos1 == std::string::npos) + pos1 = value.size(); + std::string part = value.substr(pos0, pos1 - pos0); + //std::cout << "DEBUG: " << part << std::endl << std::flush; + if (part != "") + result.push_back(part); + pos0 = value.find_first_not_of(separators, pos1); + if (pos0 == std::string::npos) + pos0 = value.size(); + } + + return result; +} + +std::string join(std::vector vs, std::string separator) +{ + std::string s; + for (const auto& line : vs) { + if (s.size() > 0) + s += separator; + s += line; + } + + return s; +} + +bool startsWithAnyOfLower(const std::string &s, const std::vector &list) { + for (const std::string& element : list) { + if (boost::algorithm::starts_with(boost::algorithm::to_lower_copy(s), boost::algorithm::to_lower_copy(element))) + return true; + } + return false; +} + diff --git a/stringutil.h b/stringutil.h new file mode 100644 index 0000000..5110e2e --- /dev/null +++ b/stringutil.h @@ -0,0 +1,10 @@ +#pragma once + +#include +#include + +std::string strfmt(const char* fmt, ...); + +std::vector split(std::string value, const std::string separators = "\r\n "); +std::string join(std::vector vs, std::string separator = "\n"); +bool startsWithAnyOfLower(const std::string &s, const std::vector &list); diff --git a/tempfile.cpp b/tempfile.cpp new file mode 100644 index 0000000..f425db2 --- /dev/null +++ b/tempfile.cpp @@ -0,0 +1,42 @@ +#include "tempfile.h" + +#include +#include +#include + +#include + +namespace fs = std::filesystem; +using namespace std::string_literals; + +fs::path Tempfile::GetPath() const +{ + return m_path; +} + +Tempfile::Tempfile(const std::filesystem::path& extension) +{ + try { + fs::path path { fs::temp_directory_path() / "tempfileXXXXXX"}; + if (!extension.empty()) + path += extension; + + fs::path::string_type name{path.native()}; + int fd = mkstemps(name.data(), extension.native().size()); + if (fd == -1) + std::runtime_error("mkstemps: "s + strerror(errno)); + close(fd); + m_path = std::string{name}; + } catch (const std::exception& ex) { + throw std::runtime_error("Tempfile error: "s + ex.what()); + } +} + +Tempfile::~Tempfile() +{ + try { + fs::remove_all(m_path); + } catch (const std::exception& ex) { + std::cerr << "Warning: Couldn't remove temporary file " << m_path << std::endl; + } +} diff --git a/tempfile.h b/tempfile.h new file mode 100644 index 0000000..b9839a7 --- /dev/null +++ b/tempfile.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +class Tempfile +{ + std::filesystem::path m_path; + + public: + std::filesystem::path GetPath() const; + + // extension: e.g. ".zip" + Tempfile(const std::filesystem::path& extension = std::filesystem::path{}); + ~Tempfile(); + }; + + diff --git a/url.cpp b/url.cpp new file mode 100644 index 0000000..5baf603 --- /dev/null +++ b/url.cpp @@ -0,0 +1,32 @@ +#include "url.h" + +std::string urlDecode(std::string s) +{ + std::string result; + + size_t pos = 0; + while (pos < s.size()) { + char c {s[pos]}; + if (c == '+') { + result += ' '; + } else if (c == '%' && pos + 2 < s.size()) { + try { + int i = stoi(s.substr(pos + 1, 2), 0, 16); + if (i < 0 || i > 255) + return result; + + result += static_cast(i); + } catch (...) { + return result; + } + + pos += 2; + } else { + result += c; + } + pos++; + } + + return result; +} + diff --git a/url.h b/url.h new file mode 100644 index 0000000..bd60616 --- /dev/null +++ b/url.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +std::string urlDecode(std::string s); + -- cgit v1.2.3