Skip to content
This repository has been archived by the owner on Oct 8, 2024. It is now read-only.

Commit

Permalink
Avoid ICU dependency when using Qt
Browse files Browse the repository at this point in the history
  • Loading branch information
caesay committed Mar 10, 2024
1 parent f888209 commit ae0cfd2
Show file tree
Hide file tree
Showing 10 changed files with 295 additions and 68 deletions.
154 changes: 105 additions & 49 deletions for-cpp/Velopack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1242,14 +1242,93 @@ int subprocess_alive(struct subprocess_s *const process) {
#include <sstream>
#include <thread>
#include "Velopack.hpp"
// #include "subprocess.h"

// platform-specific includes
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#define PATH_MAX MAX_PATH
#include <Windows.h> // For GetCurrentProcessId, GetModuleFileName, MultiByteToWideChar, WideCharToMultiByte, LCMapStringEx
#elif defined(__unix__) || defined(__APPLE__)
#include <unistd.h> // For getpid
#include <libproc.h> // For proc_pidpath
#endif

// unicode string manipulation support
#if defined(QT_CORE_LIB)

#include <QString>
static std::string VeloString_ToLower(std::string_view s)
{
QString t = QString::fromStdString(std::string { s });
return t.toLower().toStdString();
}

static std::string VeloString_ToUpper(std::string_view s)
{
QString t = QString::fromStdString(std::string { s });
return t.toUpper().toStdString();
}

#elif defined(_WIN32)

#include <Windows.h>
#elif defined(__unix__) || defined(__APPLE__) && defined(__MACH__)
#include <unistd.h> // For getpid on UNIX-like systems
#include <libproc.h> // For proc_pidpath on UNIX-like systems
static std::string VeloString_Win32LCMap(std::string_view s, DWORD flags)
{
int size = MultiByteToWideChar(CP_UTF8, 0, s.data(), (int)s.size(), nullptr, 0);
std::wstring wide(size, 0);
MultiByteToWideChar(CP_UTF8, 0, s.data(), (int)s.size(), wide.data(), size);
size = LCMapStringEx(LOCALE_NAME_SYSTEM_DEFAULT, LCMAP_LINGUISTIC_CASING | flags, wide.data(), size, nullptr, 0, nullptr, nullptr, 0);
std::wstring wideResult(size, 0);
LCMapStringEx(LOCALE_NAME_SYSTEM_DEFAULT, LCMAP_LINGUISTIC_CASING | flags, wide.data(), wide.size(), wideResult.data(), size, nullptr, nullptr, 0);
int resultSize = WideCharToMultiByte(CP_UTF8, 0, wideResult.data(), size, nullptr, 0, nullptr, nullptr);
std::string result(resultSize, 0);
WideCharToMultiByte(CP_UTF8, 0, wideResult.data(), size, result.data(), resultSize, nullptr, nullptr);
return result;
}

static std::string VeloString_ToLower(std::string_view s)
{
return VeloString_Win32LCMap(s, LCMAP_LOWERCASE);
}

static std::string VeloString_ToUpper(std::string_view s)
{
return VeloString_Win32LCMap(s, LCMAP_UPPERCASE);
}

#elif defined(VELOPACK_NO_ICU)

static std::string VeloString_ToLower(std::string_view s)
{
std::string data(s);
std::transform(data.begin(), data.end(), data.begin(), [](unsigned char c){ return std::tolower(c); });
return data;
}

static std::string VeloString_ToUpper(std::string_view s)
{
std::string data(s);
std::transform(data.begin(), data.end(), data.begin(), [](unsigned char c){ return std::toupper(c); });
return data;
}

#else

#include <unicode/unistr.h>

static std::string VeloString_ToLower(std::string_view s)
{
std::string result;
return icu::UnicodeString::fromUTF8(s).toLower().toUTF8String(result);
}

static std::string VeloString_ToUpper(std::string_view s)
{
std::string result;
return icu::UnicodeString::fromUTF8(s).toUpper().toUTF8String(result);
}

#endif

static std::string nativeCurrentOsName()
Expand Down Expand Up @@ -1471,41 +1550,6 @@ namespace Velopack
#include <stdexcept>
#include "Velopack.hpp"

#ifdef _WIN32

#include <Windows.h>

static std::string FuString_Win32LCMap(std::string_view s, DWORD flags)
{
int size = MultiByteToWideChar(CP_UTF8, 0, s.data(), (int) s.size(), nullptr, 0);
std::wstring wide(size, 0);
MultiByteToWideChar(CP_UTF8, 0, s.data(), (int) s.size(), wide.data(), size);
size = LCMapStringEx(LOCALE_NAME_SYSTEM_DEFAULT, LCMAP_LINGUISTIC_CASING | flags, wide.data(), size, nullptr, 0, nullptr, nullptr, 0);
std::wstring wideResult(size, 0);
LCMapStringEx(LOCALE_NAME_SYSTEM_DEFAULT, LCMAP_LINGUISTIC_CASING | flags, wide.data(), wide.size(), wideResult.data(), size, nullptr, nullptr, 0);
int resultSize = WideCharToMultiByte(CP_UTF8, 0, wideResult.data(), size, nullptr, 0, nullptr, nullptr);
std::string result(resultSize, 0);
WideCharToMultiByte(CP_UTF8, 0, wideResult.data(), size, result.data(), resultSize, nullptr, nullptr);
return result;
}

static std::string FuString_ToLower(std::string_view s)
{
return FuString_Win32LCMap(s, LCMAP_LOWERCASE);
}

#else

#include <unicode/unistr.h>

static std::string FuString_ToLower(std::string_view s)
{
std::string result;
return icu::UnicodeString::fromUTF8(s).toLower().toUTF8String(result);
}

#endif

namespace Velopack
{

Expand Down Expand Up @@ -2033,6 +2077,18 @@ double Platform::parseDouble(std::string_view str)
throw std::runtime_error("ParseDouble failed, string is not a valid double");
}

std::string Platform::toLower(std::string_view str)
{
std::string result{""};
result = VeloString_ToLower(str); return result;
}

std::string Platform::toUpper(std::string_view str)
{
std::string result{""};
result = VeloString_ToUpper(str); return result;
}

int Platform::parseHex(std::string_view str)
{
int i = 0;
Expand Down Expand Up @@ -2143,21 +2199,21 @@ std::shared_ptr<VelopackAsset> VelopackAsset::fromNode(std::shared_ptr<JsonNode>
{
std::shared_ptr<VelopackAsset> asset = std::make_shared<VelopackAsset>();
for (const auto &[k, v] : *node->asObject()) {
if (FuString_ToLower(k) == "id")
if (Platform::toLower(k) == "id")
asset->packageId = v->asString();
else if (FuString_ToLower(k) == "version")
else if (Platform::toLower(k) == "version")
asset->version = v->asString();
else if (FuString_ToLower(k) == "type")
asset->type = FuString_ToLower(v->asString()) == "full" ? VelopackAssetType::full : VelopackAssetType::delta;
else if (FuString_ToLower(k) == "filename")
else if (Platform::toLower(k) == "type")
asset->type = Platform::toLower(v->asString()) == "full" ? VelopackAssetType::full : VelopackAssetType::delta;
else if (Platform::toLower(k) == "filename")
asset->fileName = v->asString();
else if (FuString_ToLower(k) == "sha1")
else if (Platform::toLower(k) == "sha1")
asset->sha1 = v->asString();
else if (FuString_ToLower(k) == "size")
else if (Platform::toLower(k) == "size")
asset->size = static_cast<int64_t>(v->asNumber());
else if (FuString_ToLower(k) == "markdown")
else if (Platform::toLower(k) == "markdown")
asset->notesMarkdown = v->asString();
else if (FuString_ToLower(k) == "html")
else if (Platform::toLower(k) == "html")
asset->notesHTML = v->asString();
}
return asset;
Expand All @@ -2168,9 +2224,9 @@ std::shared_ptr<UpdateInfo> UpdateInfo::fromJson(std::string_view json)
std::shared_ptr<JsonNode> node = JsonNode::parse(json);
std::shared_ptr<UpdateInfo> updateInfo = std::make_shared<UpdateInfo>();
for (const auto &[k, v] : *node->asObject()) {
if (FuString_ToLower(k) == "targetfullrelease")
if (Platform::toLower(k) == "targetfullrelease")
updateInfo->targetFullRelease = VelopackAsset::fromNode(v);
else if (FuString_ToLower(k) == "isdowngrade")
else if (Platform::toLower(k) == "isdowngrade")
updateInfo->isDowngrade = v->asBool();
}
return updateInfo;
Expand Down
18 changes: 18 additions & 0 deletions for-cpp/Velopack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@
// SOFTWARE.
//

// UNICODE SUPPORT NOTES
//
// To keep this library as light as possible, we will try to avoid using ICU4C
// if possible. If Qt is available, we will use its QString class to handle
// Unicode string manipulation. On Windows, we will use the Win32 unicode API.
// If neither of these are available, we will fall back to using ICU4C.
//
// On Windows, for full Unicode support, you will need to set the code page.
// https://learn.microsoft.com/en-us/windows/apps/design/globalizing/use-utf8-code-page
//
// If you would like to disable ICU4C and fall back to ASCII-only functions on,
// systems without an alternative implementation, uncomment the following define:
//
// #define VELOPACK_NO_ICU

#ifndef VELOPACK_H_INCLUDED
#define VELOPACK_H_INCLUDED

Expand All @@ -43,6 +58,7 @@ namespace Velopack
#endif // UNICODE
void startup(char **args, size_t c_args);
}

#endif // VELOPACK_H_INCLUDED

// Generated automatically with "fut". Do not edit.
Expand Down Expand Up @@ -211,6 +227,8 @@ class Platform
static std::string getUpdateExePath();
static std::string strTrim(std::string str);
static double parseDouble(std::string_view str);
static std::string toLower(std::string_view str);
static std::string toUpper(std::string_view str);
static int parseHex(std::string_view str);
static std::string pathParent(std::string str);
static std::string pathJoin(std::string s1, std::string s2);
Expand Down
22 changes: 18 additions & 4 deletions for-cs/Velopack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -683,6 +683,20 @@ public static double ParseDouble(string str)
throw new Exception("ParseDouble failed, string is not a valid double");
}

public static string ToLower(string str)
{
string result = "";
result = str.ToLower();
return result;
}

public static string ToUpper(string str)
{
string result = "";
result = str.ToLower();
return result;
}

public static int ParseHex(string str)
{
int i = 0;
Expand Down Expand Up @@ -849,7 +863,7 @@ public static VelopackAsset FromNode(JsonNode node)
VelopackAsset asset = new VelopackAsset();
foreach ((string k, JsonNode v) in node.AsObject())
{
switch (k.ToLower())
switch (Platform.ToLower(k))
{
case "id":
asset.PackageId = v.AsString();
Expand All @@ -858,7 +872,7 @@ public static VelopackAsset FromNode(JsonNode node)
asset.Version = v.AsString();
break;
case "type":
asset.Type = v.AsString().ToLower() == "full" ? VelopackAssetType.Full : VelopackAssetType.Delta;
asset.Type = Platform.ToLower(v.AsString()) == "full" ? VelopackAssetType.Full : VelopackAssetType.Delta;
break;
case "filename":
asset.FileName = v.AsString();
Expand Down Expand Up @@ -900,7 +914,7 @@ public static UpdateInfo FromJson(string json)
UpdateInfo updateInfo = new UpdateInfo();
foreach ((string k, JsonNode v) in node.AsObject())
{
switch (k.ToLower())
switch (Platform.ToLower(k))
{
case "targetfullrelease":
updateInfo.TargetFullRelease = VelopackAsset.FromNode(v);
Expand Down Expand Up @@ -1137,7 +1151,7 @@ public void Run()
List<string> args = new List<string>();
args = Environment.GetCommandLineArgs().ToList(); for (int i = 0; i < args.Count; i++)
{
string val = Platform.StrTrim(args[i]).ToLower();
string val = Platform.ToLower(Platform.StrTrim(args[i]));
if (val == "--veloapp-install")
{
Platform.Exit(0);
Expand Down
18 changes: 14 additions & 4 deletions for-js/Velopack.js
Original file line number Diff line number Diff line change
Expand Up @@ -682,6 +682,16 @@ class Platform {
}
throw new Error("ParseDouble failed, string is not a valid double");
}
static toLower(str) {
let result = "";
result = str.toLowerCase();
return result;
}
static toUpper(str) {
let result = "";
result = str.toLowerCase();
return result;
}
static parseHex(str) {
let i = 0;
if (!isNaN((i = parseInt(str, 16)))) {
Expand Down Expand Up @@ -855,7 +865,7 @@ class VelopackAsset {
static fromNode(node) {
let asset = new VelopackAsset();
for (const [k, v] of Object.entries(node.asObject())) {
switch (k.toLowerCase()) {
switch (Platform.toLower(k)) {
case "id":
asset.packageId = v.asString();
break;
Expand All @@ -864,7 +874,7 @@ class VelopackAsset {
break;
case "type":
asset.type =
v.asString().toLowerCase() == "full"
Platform.toLower(v.asString()) == "full"
? VelopackAssetType.FULL
: VelopackAssetType.DELTA;
break;
Expand Down Expand Up @@ -908,7 +918,7 @@ class UpdateInfo {
let node = JsonNode.parse(json);
let updateInfo = new UpdateInfo();
for (const [k, v] of Object.entries(node.asObject())) {
switch (k.toLowerCase()) {
switch (Platform.toLower(k)) {
case "targetfullrelease":
updateInfo.targetFullRelease = VelopackAsset.fromNode(v);
break;
Expand Down Expand Up @@ -1136,7 +1146,7 @@ class VelopackApp {
const args = [];
Array.prototype.push.apply(args, process.argv);
for (let i = 0; i < args.length; i++) {
let val = Platform.strTrim(args[i]).toLowerCase();
let val = Platform.toLower(Platform.strTrim(args[i]));
if (val == "--veloapp-install") {
Platform.exit(0);
}
Expand Down
Loading

0 comments on commit ae0cfd2

Please sign in to comment.