diff options
author | Roland Reichwein <mail@reichwein.it> | 2023-01-02 16:32:01 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2023-01-02 16:32:01 +0100 |
commit | d00dc2c69164d8a8850d317f2868c6f131b7f679 (patch) | |
tree | c206c5088be0ed2fa0af692f1e0bc739f66d0b0a |
First lib versionv1.0
-rw-r--r-- | Makefile | 44 | ||||
-rw-r--r-- | common.mk | 85 | ||||
-rw-r--r-- | debian/README.Debian | 13 | ||||
-rw-r--r-- | debian/changelog | 5 | ||||
-rw-r--r-- | debian/compat | 1 | ||||
-rw-r--r-- | debian/control | 16 | ||||
-rw-r--r-- | debian/copyright | 4 | ||||
-rwxr-xr-x | debian/rules | 4 | ||||
-rw-r--r-- | debian/source/format | 1 | ||||
-rw-r--r-- | file.cpp | 46 | ||||
-rw-r--r-- | file.h | 15 | ||||
-rw-r--r-- | mime.cpp | 41 | ||||
-rw-r--r-- | mime.h | 5 | ||||
-rw-r--r-- | stringutil.cpp | 66 | ||||
-rw-r--r-- | stringutil.h | 10 | ||||
-rw-r--r-- | tempfile.cpp | 42 | ||||
-rw-r--r-- | tempfile.h | 17 | ||||
-rw-r--r-- | url.cpp | 32 | ||||
-rw-r--r-- | url.h | 6 |
19 files changed, 453 insertions, 0 deletions
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 <mail@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 <mail@reichwein.it> 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 <mail@reichwein.it> +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 <mail@reichwein.it>, 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 <fstream> + +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<char*>(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<uint8_t>& data) +{ + File::setFile(filename, reinterpret_cast<const char*>(data.data()), data.size()); +} + @@ -0,0 +1,15 @@ +#pragma once + +#include <cstdint> +#include <filesystem> +#include <string> +#include <vector> + +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<uint8_t>& 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 <boost/algorithm/string/predicate.hpp> +#include <boost/beast/http.hpp> + +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"; +} + @@ -0,0 +1,5 @@ +#pragma once + +#include <string> + +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 <boost/algorithm/string/predicate.hpp> +#include <boost/algorithm/string/case_conv.hpp> + +#include <cstdarg> + +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<std::string> split(std::string value, const std::string separators) +{ + std::vector<std::string> 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<std::string> 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<std::string> &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 <string> +#include <vector> + +std::string strfmt(const char* fmt, ...); + +std::vector<std::string> split(std::string value, const std::string separators = "\r\n "); +std::string join(std::vector<std::string> vs, std::string separator = "\n"); +bool startsWithAnyOfLower(const std::string &s, const std::vector<std::string> &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 <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <iostream> + +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 <filesystem> + +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(); + }; + + @@ -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<char>(i); + } catch (...) { + return result; + } + + pos += 2; + } else { + result += c; + } + pos++; + } + + return result; +} + @@ -0,0 +1,6 @@ +#pragma once + +#include <string> + +std::string urlDecode(std::string s); + |