Repository: duckdb/duckdb
File: src/common/string_util.cpp (C++)

Code before:
		multiplier = 1000LL * 1000LL * 1000LL * 1000LL;
	} else if (unit == "kib") {
		multiplier = 1024LL;
	} else if (unit == "mib") {
		multiplier = 1024LL * 1024LL;
	} else if (unit == "gib") {
		multiplier = 1024LL * 1024LL * 1024LL;
	} else if (unit == "tib") {
		multiplier = 1024LL * 1024LL * 1024LL * 1024LL;
	} else {
		throw ParserException("Unknown unit for memory: '%s' (expected: KB, MB, GB, TB for 1000^i units or KiB, "
		                      "MiB, GiB, TiB for 1024^i units)",
		                      unit);
	}

	// Make sure the result is not greater than `idx_t` max value
	constexpr double max_value = static_cast<double>(NumericLimits<idx_t>::Maximum());
	const double double_multiplier = static_cast<double>(multiplier);

	if (limit > (max_value / double_multiplier)) {
		throw ParserException("Memory value out of range: value is too large");
	}

	return LossyNumericCast<idx_t>(static_cast<double>(multiplier) * limit);
}

string StringUtil::Upper(const string &str) {
	string copy(str);
	transform(copy.begin(), copy.end(), copy.begin(), [](unsigned char c) { return std::toupper(c); });
	return (copy);
}

string StringUtil::Lower(const string &str) {
	string copy(str);
	transform(copy.begin(), copy.end(), copy.begin(),
	          [](unsigned char c) { return StringUtil::CharacterToLower(static_cast<char>(c)); });
	return (copy);
}

string StringUtil::Title(const string &str) {
	string copy;
	bool first_character = true;
	for (auto c : str) {
		bool is_alpha = StringUtil::CharacterIsAlpha(c);
		if (is_alpha) {
			if (first_character) {
				copy += StringUtil::CharacterToUpper(c);
				first_character = false;
			} else {
				copy += StringUtil::CharacterToLower(c);
			}

Review comment (bug):
@Mytherin 
This is my only change from the original implementation (from `DBConfig`).
There used to be a bug when we try to set values like `343897438957348957 TiB` (the process actually crashed)

Code after:
		multiplier = 1000LL * 1000LL;
	} else if (unit == "gigabyte" || unit == "gigabytes" || unit == "gb" || unit == "g") {
		multiplier = 1000LL * 1000LL * 1000LL;
	} else if (unit == "terabyte" || unit == "terabytes" || unit == "tb" || unit == "t") {
		multiplier = 1000LL * 1000LL * 1000LL * 1000LL;
	} else if (unit == "kib") {
		multiplier = 1024LL;
	} else if (unit == "mib") {
		multiplier = 1024LL * 1024LL;
	} else if (unit == "gib") {
		multiplier = 1024LL * 1024LL * 1024LL;
	} else if (unit == "tib") {
		multiplier = 1024LL * 1024LL * 1024LL * 1024LL;
	} else {
		return StringUtil::Format("Unknown unit for memory: '%s' (expected: KB, MB, GB, TB for 1000^i units or KiB, "
		                          "MiB, GiB, TiB for 1024^i units)",
		                          unit);
	}

	// Make sure the result is not greater than `idx_t` max value
	constexpr double max_value = static_cast<double>(NumericLimits<idx_t>::Maximum());
	const double double_multiplier = static_cast<double>(multiplier);

	if (limit > (max_value / double_multiplier)) {
		return "Memory value out of range: value is too large";
	}

	result = LossyNumericCast<idx_t>(static_cast<double>(multiplier) * limit);
	return string();
}

idx_t StringUtil::ParseFormattedBytes(const string &arg) {
	idx_t result;
	const string error = TryParseFormattedBytes(arg, result);
	if (!error.empty()) {
		throw InvalidInputException(error);
	}
	return result;
}

string StringUtil::Upper(const string &str) {
	string copy(str);
	transform(copy.begin(), copy.end(), copy.begin(), [](unsigned char c) { return std::toupper(c); });
	return (copy);
}

string StringUtil::Lower(const string &str) {
	string copy(str);
	transform(copy.begin(), copy.end(), copy.begin(),
	          [](unsigned char c) { return StringUtil::CharacterToLower(static_cast<char>(c)); });
	return (copy);