summaryrefslogtreecommitdiff
path: root/wx+
diff options
context:
space:
mode:
Diffstat (limited to 'wx+')
-rw-r--r--wx+/button.cpp15
-rw-r--r--wx+/create_pch.cpp8
-rw-r--r--wx+/dir_picker.h8
-rw-r--r--wx+/serialize.h322
-rw-r--r--wx+/zlib_wrap.cpp54
-rw-r--r--wx+/zlib_wrap.h115
6 files changed, 488 insertions, 34 deletions
diff --git a/wx+/button.cpp b/wx+/button.cpp
index 1e9cb7f0..0b193cfb 100644
--- a/wx+/button.cpp
+++ b/wx+/button.cpp
@@ -8,6 +8,7 @@
#include <algorithm>
#include <limits>
#include <cmath>
+#include <zen/string_tools.h>
#include <wx/dcmemory.h>
#include <wx/image.h>
#include "image_tools.h"
@@ -79,7 +80,7 @@ void makeWhiteTransparent(wxImage& image) //assume black text on white backgroun
unsigned char* alphaLast = alphaFirst + image.GetWidth() * image.GetHeight();
//dist(black, white)
- double distBlackWhite = std::sqrt(3.0 * 255 * 255);
+ const double distBlackWhite = 255 * std::sqrt(3.0);
const unsigned char* bytePos = image.GetData();
@@ -101,12 +102,14 @@ void makeWhiteTransparent(wxImage& image) //assume black text on white backgroun
wxSize getSizeNeeded(const wxString& text, wxFont& font)
{
- wxCoord width, height;
- wxMemoryDC dc;
+ const wxString& textFormatted = replaceCpy(text, L"&", L"", false); //remove accelerator
+
+ wxCoord width = 0;
+ wxCoord height = 0;
- wxString textFormatted = text;
- textFormatted.Replace(wxT("&"), wxT(""), false); //remove accelerator
+ wxMemoryDC dc;
dc.GetMultiLineTextExtent(textFormatted, &width, &height, nullptr, &font);
+
return wxSize(width, height);
}
@@ -138,7 +141,7 @@ wxBitmap BitmapButton::createBitmapFromText(const wxString& text)
wxString textLabelFormatted = text;
if ((accelPos = text.find(wxT("&"))) != wxString::npos)
{
- textLabelFormatted.Replace(wxT("&"), wxT(""), false); //remove accelerator
+ replace(textLabelFormatted, L"&", L"", false); //remove accelerator
indexAccel = static_cast<int>(accelPos);
}
diff --git a/wx+/create_pch.cpp b/wx+/create_pch.cpp
new file mode 100644
index 00000000..a9b2ea37
--- /dev/null
+++ b/wx+/create_pch.cpp
@@ -0,0 +1,8 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved *
+// **************************************************************************
+
+//dummy file for Visual Studio to compile precompiled header:
+//attaching pch to any other cpp file triggers a full rebuild each time code is changed! \ No newline at end of file
diff --git a/wx+/dir_picker.h b/wx+/dir_picker.h
index 5f18b6fb..51bd9757 100644
--- a/wx+/dir_picker.h
+++ b/wx+/dir_picker.h
@@ -22,10 +22,14 @@ public:
#ifdef FFS_WIN
//fix wxWidgets localization gap:
wxButton* button = dynamic_cast<wxButton*>(m_pickerIface);
- if (button) button->SetLabel(_("Browse"));
+ if (button)
+ {
+ button->SetLabel(_("Browse")); //button width needs to be adapted for very long translations
+ SetMinSize(button->GetBestSize()); //SetSize and wxButton::SetSize just do nothing!!??
+ }
#endif
}
};
}
-#endif // DIR_PICKER_I18N_H_INCLUDED
+#endif // DIR_PICKER_I18N_H_INCLUDED
diff --git a/wx+/serialize.h b/wx+/serialize.h
index f49bff04..030b55c7 100644
--- a/wx+/serialize.h
+++ b/wx+/serialize.h
@@ -8,14 +8,306 @@
#define SERIALIZE_H_INCLUDED
#include <cstdint>
-#include <wx/stream.h>
+#include <zen/string_base.h>
#include <zen/file_io.h>
+#ifdef FFS_WIN
+warn_static("get rid of wx, then move to zen")
+#endif
+
+#include <wx/stream.h>
+
namespace zen
{
+//high-performance unformatted serialization (avoiding wxMemoryOutputStream/wxMemoryInputStream inefficiencies)
+
+/*
+--------------------------
+|Binary Container Concept|
+--------------------------
+binary container for data storage: must support "basic" std::vector interface (e.g. std::vector<char>, std::string, Zbase<char>)
+*/
+
+//binary container reference implementations
+typedef Zbase<char> Utf8String; //ref-counted + COW text stream + guaranteed performance: exponential growth
+class BinaryStream; //ref-counted byte stream + guaranteed performance: exponential growth -> no COW, but 12% faster than Utf8String (due to no null-termination?)
+
+class BinaryStream //essentially a std::vector<char> with ref-counted semantics
+{
+public:
+ BinaryStream() : buffer(std::make_shared<std::vector<char>>()) {}
+
+ typedef std::vector<char>::value_type value_type;
+ typedef std::vector<char>::iterator iterator;
+ typedef std::vector<char>::const_iterator const_iterator;
+
+ iterator begin() { return buffer->begin(); }
+ iterator end () { return buffer->end (); }
+
+ const_iterator begin() const { return buffer->begin(); }
+ const_iterator end () const { return buffer->end (); }
+
+ void resize(size_t len) { buffer->resize(len); }
+ size_t size() const { return buffer->size(); }
+ bool empty() const { return buffer->empty(); }
+
+ inline friend bool operator==(const BinaryStream& lhs, const BinaryStream& rhs) { return *lhs.buffer == *rhs.buffer; }
+
+private:
+ std::shared_ptr<std::vector<char>> buffer; //always bound!
+ //perf: shared_ptr indirection irrelevant: less than 1% slower!
+};
+
+//----------------------------------------------------------------------
+//functions based on binary container abstraction
+template <class BinContainer> void saveBinStream(const Zstring& filename, const BinContainer& cont); //throw FileError
+template <class BinContainer> BinContainer loadBinStream(const Zstring& filename); //throw FileError, ErrorNotExisting
+
+
+/*
+-----------------------------
+|Binary Input Stream Concept|
+-----------------------------
+struct BinInputStream
+{
+ const void* requestRead(size_t len); //expect external read of len bytes
+};
+
+------------------------------
+|Binary Output Stream Concept|
+------------------------------
+struct BinOutputStream
+{
+ void* requestWrite(size_t len); //expect external write of len bytes
+};
+*/
+
+//binary input/output stream reference implementation
+class UnexpectedEndOfStreamError {};
+
+struct BinStreamIn //throw UnexpectedEndOfStreamError
+{
+ BinStreamIn(const BinaryStream& cont) : buffer(cont), pos(0) {} //this better be cheap!
+
+ const void* requestRead(size_t len) //throw UnexpectedEndOfStreamError
+ {
+ if (pos + len > buffer.size())
+ throw UnexpectedEndOfStreamError();
+ size_t oldPos = pos;
+ pos += len;
+ return &*buffer.begin() + oldPos;
+ }
+
+private:
+ const BinaryStream buffer;
+ size_t pos;
+};
+
+struct BinStreamOut
+{
+ void* requestWrite(size_t len)
+ {
+ size_t oldSize = buffer.size();
+ buffer.resize(buffer.size() + len);
+ return &*buffer.begin() + oldSize;
+ }
+
+ BinaryStream get() { return buffer; }
+
+private:
+ BinaryStream buffer;
+};
+
+//----------------------------------------------------------------------
+//functions based on binary stream abstraction
+template <class N, class BinOutputStream> void writeNumber (BinOutputStream& stream, const N& num); //
+template <class C, class BinOutputStream> void writeContainer(BinOutputStream& stream, const C& str); //throw ()
+template < class BinOutputStream> void writeArray (BinOutputStream& stream, const void* data, size_t len); //
+
+//----------------------------------------------------------------------
+
+template <class N, class BinInputStream> N readNumber (BinInputStream& stream); //
+template <class C, class BinInputStream> C readContainer(BinInputStream& stream); //throw UnexpectedEndOfStreamError (corrupted data)
+template < class BinInputStream> void readArray (BinInputStream& stream, void* data, size_t len); //
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//-----------------------implementation-------------------------------
+template <class BinContainer> inline
+void saveBinStream(const Zstring& filename, const BinContainer& cont) //throw FileError
+{
+ assert_static(sizeof(typename BinContainer::value_type) == 1); //expect: bytes (until further)
+
+ FileOutput fileOut(filename, zen::FileOutput::ACC_OVERWRITE); //throw FileError
+ if (!cont.empty())
+ fileOut.write(&*cont.begin(), cont.size()); //throw FileError
+}
+
+
+template <class BinContainer> inline
+BinContainer loadBinStream(const Zstring& filename) //throw FileError, ErrorNotExisting
+{
+ assert_static(sizeof(typename BinContainer::value_type) == 1); //expect: bytes (until further)
+
+ FileInput fileIn(filename); //throw FileError, ErrorNotExisting
+
+ BinContainer contOut;
+ const size_t blockSize = 64 * 1024;
+ do
+ {
+ contOut.resize(contOut.size() + blockSize);
+
+ const size_t bytesRead = fileIn.read(&*contOut.begin() + contOut.size() - blockSize, blockSize); //throw FileError
+ if (bytesRead < blockSize)
+ contOut.resize(contOut.size() - (blockSize - bytesRead)); //caveat: unsigned arithmetics
+ }
+ while (!fileIn.eof());
+
+ return contOut;
+}
+
+
+template <class BinOutputStream> inline
+void writeArray(BinOutputStream& stream, const void* data, size_t len)
+{
+ std::copy(static_cast<const char*>(data),
+ static_cast<const char*>(data) + len,
+ static_cast< char*>(stream.requestWrite(len)));
+}
+
+
+template <class N, class BinOutputStream> inline
+void writeNumber(BinOutputStream& stream, const N& num)
+{
+ assert_static((IsArithmetic<N>::value || IsSameType<N, bool>::value));
+ writeArray(stream, &num, sizeof(N));
+}
+
+
+template <class C, class BinOutputStream> inline
+void writeContainer(BinOutputStream& stream, const C& cont) //don't even consider UTF8 conversions here! "string" is expected to handle arbitrary binary data!
+{
+ const auto len = cont.size();
+ writeNumber(stream, static_cast<std::uint32_t>(len));
+ if (len > 0)
+ writeArray(stream, &*cont.begin(), sizeof(typename C::value_type) * len); //don't use c_str(), but access uniformly via STL interface
+}
+
+
+template <class BinInputStream> inline
+void readArray(BinInputStream& stream, void* data, size_t len)
+{
+ const char* const src = static_cast<const char*>(stream.requestRead(len)); //expect external write of len bytes
+ std::copy(src, src + len, static_cast<char*>(data));
+}
+
+
+template <class N, class BinInputStream> inline
+N readNumber(BinInputStream& stream)
+{
+ assert_static((IsArithmetic<N>::value || IsSameType<N, bool>::value));
+ N num = 0;
+ readArray(stream, &num, sizeof(N));
+ return num;
+}
+
+
+template <class C, class BinInputStream> inline
+C readContainer(BinInputStream& stream)
+{
+ C cont;
+ auto strLength = readNumber<std::uint32_t>(stream);
+ if (strLength > 0)
+ try
+ {
+ cont.resize(strLength); //throw std::bad_alloc
+ readArray(stream, &*cont.begin(), sizeof(typename C::value_type) * strLength);
+ }
+ catch (std::bad_alloc&) //most likely this is due to data corruption!
+ {
+ throw UnexpectedEndOfStreamError();
+ }
+ return cont;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#ifdef FFS_WIN
+warn_static("get rid of wx, then move to zen")
+#endif
+
+
+
//unchecked, unformatted serialization
-template <class T> T readPOD (wxInputStream& stream);
+template <class T> T readPOD (wxInputStream& stream);
template <class T> void readPOD (wxInputStream& stream, T& pod);
template <class T> void writePOD(wxOutputStream& stream, const T& pod);
@@ -116,29 +408,6 @@ private:
};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-//-----------------------implementation-------------------------------
template <class T> inline
T readPOD(wxInputStream& stream)
{
@@ -235,7 +504,7 @@ void CheckedReader::readString(S& str) const //checked read operation
}
catch (std::exception&) { throwException(); }
check();
- if (stream_.LastRead() != str.length() * sizeof(typename S::value_type)) //some additional check
+ if (stream_.LastRead() != str.size() * sizeof(typename S::value_type)) //some additional check
throwException();
}
@@ -260,6 +529,7 @@ void CheckedWriter::writeString(const S& str) const //checked write operation
{
zen::writeString(stream_, str);
check();
+ //warn_static("buggy check if length 0!")
if (stream_.LastWrite() != str.length() * sizeof(typename S::value_type)) //some additional check
throwException();
}
diff --git a/wx+/zlib_wrap.cpp b/wx+/zlib_wrap.cpp
new file mode 100644
index 00000000..22285bab
--- /dev/null
+++ b/wx+/zlib_wrap.cpp
@@ -0,0 +1,54 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved *
+// **************************************************************************
+
+#include "zlib_wrap.h"
+#ifdef FFS_WIN
+#include <../src/zlib/zlib.h> //not really a "nice" place to look for a stable solution
+#elif defined FFS_LINUX
+#include <zlib.h> //let's pray this is the same version wxWidgets is linking against!
+#endif
+
+using namespace zen;
+
+
+size_t zen::impl::zlib_compressBound(size_t len)
+{
+ return ::compressBound(static_cast<uLong>(len)); //upper limit for buffer size, larger than input size!!!
+}
+
+
+size_t zen::impl::zlib_compress(const void* src, size_t srcLen, void* trg, size_t trgLen, int level) //throw ZlibInternalError
+{
+ uLongf bufferSize = static_cast<uLong>(trgLen);
+ const int rv = ::compress2(static_cast<Bytef*>(trg), //Bytef* dest,
+ &bufferSize, //uLongf* destLen,
+ static_cast<const Bytef*>(src), //const Bytef* source,
+ static_cast<uLong>(srcLen), //uLong sourceLen,
+ level); //int level
+ // Z_OK: success
+ // Z_MEM_ERROR: not enough memory
+ // Z_BUF_ERROR: not enough room in the output buffer
+ if (rv != Z_OK || bufferSize > trgLen)
+ throw ZlibInternalError();
+ return bufferSize;
+}
+
+
+size_t zen::impl::zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen) //throw ZlibInternalError
+{
+ uLongf bufferSize = static_cast<uLong>(trgLen);
+ const int rv = ::uncompress(static_cast<Bytef*>(trg), //Bytef* dest,
+ &bufferSize, //uLongf* destLen,
+ static_cast<const Bytef*>(src), //const Bytef* source,
+ static_cast<uLong>(srcLen)); //uLong sourceLen
+ // Z_OK: success
+ // Z_MEM_ERROR: not enough memory
+ // Z_BUF_ERROR: not enough room in the output buffer
+ // Z_DATA_ERROR: input data was corrupted or incomplete
+ if (rv != Z_OK || bufferSize > trgLen)
+ throw ZlibInternalError();
+ return bufferSize;
+}
diff --git a/wx+/zlib_wrap.h b/wx+/zlib_wrap.h
new file mode 100644
index 00000000..7b196a75
--- /dev/null
+++ b/wx+/zlib_wrap.h
@@ -0,0 +1,115 @@
+// **************************************************************************
+// * This file is part of the FreeFileSync project. It is distributed under *
+// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
+// * Copyright (C) ZenJu (zhnmju123 AT gmx DOT de) - All Rights Reserved *
+// **************************************************************************
+
+#ifndef SIMPLE_H_INCLUDED_18134135134135345489
+#define SIMPLE_H_INCLUDED_18134135134135345489
+
+#include <wx+/serialize.h>
+
+namespace zen
+{
+class ZlibInternalError {};
+
+// compression level must be between 0 and 9:
+// 0: no compression
+// 9: best compression
+template <class BinContainer> //as specified in serialize.h
+BinContainer compress(const BinContainer& stream, int level); //throw ZlibInternalError
+//caveat: output stream is physically larger than input! => strip additional reserved space if needed: "BinContainer(output.begin(), output.end())"
+
+template <class BinContainer>
+BinContainer decompress(const BinContainer& stream); //throw ZlibInternalError
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//######################## implementation ##########################
+namespace impl
+{
+size_t zlib_compressBound(size_t len);
+size_t zlib_compress (const void* src, size_t srcLen, void* trg, size_t trgLen, int level); //throw ZlibInternalError
+size_t zlib_decompress(const void* src, size_t srcLen, void* trg, size_t trgLen); //throw ZlibInternalError
+}
+
+
+template <class BinContainer>
+BinContainer compress(const BinContainer& stream, int level) //throw ZlibInternalError
+{
+ BinContainer contOut;
+
+ //save uncompressed stream size for decompression
+ const std::uint64_t uncompressedSize = stream.size(); //use portable number type!
+ contOut.resize(sizeof(uncompressedSize));
+ std::copy(reinterpret_cast<const char*>(&uncompressedSize),
+ reinterpret_cast<const char*>(&uncompressedSize) + sizeof(uncompressedSize),
+ &*contOut.begin());
+
+ const size_t bufferEstimate = impl::zlib_compressBound(stream.size()); //upper limit for buffer size, larger than input size!!!
+
+ contOut.resize(contOut.size() + bufferEstimate);
+
+ const size_t bytesWritten = impl::zlib_compress(&*stream.begin(),
+ stream.size(),
+ &*contOut.begin() + contOut.size() - bufferEstimate,
+ bufferEstimate,
+ level); //throw ZlibInternalError
+ if (bytesWritten < bufferEstimate)
+ contOut.resize(contOut.size() - (bufferEstimate - bytesWritten)); //caveat: unsigned arithmetics
+ //caveat: physical memory consumption still *unchanged*!
+
+ return contOut;
+}
+
+
+template <class BinContainer>
+BinContainer decompress(const BinContainer& stream) //throw ZlibInternalError
+{
+ //retrieve size of uncompressed data
+ std::uint64_t uncompressedSize = 0; //use portable number type!
+ if (stream.size() < sizeof(uncompressedSize))
+ throw ZlibInternalError();
+ std::copy(&*stream.begin(),
+ &*stream.begin() + sizeof(uncompressedSize),
+ reinterpret_cast<char*>(&uncompressedSize));
+
+ BinContainer contOut;
+ try
+ {
+ contOut.resize(uncompressedSize); //throw std::bad_alloc
+ }
+ catch (std::bad_alloc&) //most likely due to data corruption!
+ {
+ throw ZlibInternalError();
+ }
+
+ const size_t bytesWritten = impl::zlib_decompress(&*stream.begin() + sizeof(uncompressedSize),
+ stream.size() - sizeof(uncompressedSize),
+ &*contOut.begin(),
+ uncompressedSize); //throw ZlibInternalError
+ if (bytesWritten != uncompressedSize)
+ throw ZlibInternalError();
+
+ return contOut;
+}
+}
+
+#endif //SIMPLE_H_INCLUDED_18134135134135345489
bgstack15