summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2023-01-02 16:32:01 +0100
committerRoland Reichwein <mail@reichwein.it>2023-01-02 16:32:01 +0100
commitd00dc2c69164d8a8850d317f2868c6f131b7f679 (patch)
treec206c5088be0ed2fa0af692f1e0bc739f66d0b0a
First lib versionv1.0
-rw-r--r--Makefile44
-rw-r--r--common.mk85
-rw-r--r--debian/README.Debian13
-rw-r--r--debian/changelog5
-rw-r--r--debian/compat1
-rw-r--r--debian/control16
-rw-r--r--debian/copyright4
-rwxr-xr-xdebian/rules4
-rw-r--r--debian/source/format1
-rw-r--r--file.cpp46
-rw-r--r--file.h15
-rw-r--r--mime.cpp41
-rw-r--r--mime.h5
-rw-r--r--stringutil.cpp66
-rw-r--r--stringutil.h10
-rw-r--r--tempfile.cpp42
-rw-r--r--tempfile.h17
-rw-r--r--url.cpp32
-rw-r--r--url.h6
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());
+}
+
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 <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";
+}
+
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 <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();
+ };
+
+
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<char>(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 <string>
+
+std::string urlDecode(std::string s);
+