From 05626c3371395d76b1f2e6b7fcbe64ef12f7d974 Mon Sep 17 00:00:00 2001 From: Yuri Chebotarev Date: Fri, 28 May 2010 20:13:18 +0300 Subject: EXT-7013 FIX time formatting function didn't work for some parameters for Japanise (like weekdays). reviewed by Vadim Savchuk https://codereview.productengine.com/secondlife/r/457/ --HG-- branch : product-engine --- indra/llcommon/llstring.cpp | 103 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index b5a73ec1d1..8197e3e642 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -676,6 +676,17 @@ long LLStringOps::sLocalTimeOffset = 0; bool LLStringOps::sPacificDaylightTime = 0; std::map LLStringOps::datetimeToCodes; +std::vector LLStringOps::sWeekDayList; +std::vector LLStringOps::sWeekDayShortList; +std::vector LLStringOps::sMonthList; +std::vector LLStringOps::sMonthShortList; + + +std::string LLStringOps::sDayFormat; +std::string LLStringOps::sAM; +std::string LLStringOps::sPM; + + S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { #if LL_WINDOWS @@ -724,6 +735,50 @@ void LLStringOps::setupDatetimeInfo (bool daylight) datetimeToCodes["timezone"] = "%Z"; // PST } +void tokenizeStringToArray(const std::string& data, std::vector& output) +{ + output.clear(); + size_t length = data.size(); + + // tokenize it and put it in the array + std::string cur_word; + for(size_t i = 0; i < length; ++i) + { + if(data[i] == ':') + { + output.push_back(cur_word); + cur_word.clear(); + } + else + { + cur_word.append(1, data[i]); + } + } + output.push_back(cur_word); +} + +void LLStringOps::setupWeekDaysNames(const std::string& data) +{ + tokenizeStringToArray(data,sWeekDayList); +} +void LLStringOps::setupWeekDaysShortNames(const std::string& data) +{ + tokenizeStringToArray(data,sWeekDayShortList); +} +void LLStringOps::setupMonthNames(const std::string& data) +{ + tokenizeStringToArray(data,sMonthList); +} +void LLStringOps::setupMonthShortNames(const std::string& data) +{ + tokenizeStringToArray(data,sMonthShortList); +} +void LLStringOps::setupDayFormat(const std::string& data) +{ + sDayFormat = data; +} + + std::string LLStringOps::getDatetimeCode (std::string key) { std::map::iterator iter; @@ -998,7 +1053,53 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, } return true; } - replacement = datetime.toHTTPDateString(code); + + //EXT-7013 + //few codes are not suppotred by strtime function (example - weekdays for Japanise) + //so use predefined ones + + //if sWeekDayList is not empty than current locale doesn't support + //weekday name. + time_t loc_seconds = (time_t) secFromEpoch; + if(LLStringOps::sWeekDayList.size() == 7 && code == "%A") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sWeekDayList[gmt->tm_wday]; + } + else if(LLStringOps::sWeekDayShortList.size() == 7 && code == "%a") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sWeekDayShortList[gmt->tm_wday]; + } + else if(LLStringOps::sMonthList.size() == 12 && code == "%B") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = LLStringOps::sWeekDayList[gmt->tm_mon]; + } + else if( !LLStringOps::sDayFormat.empty() && code == "%d" ) + { + struct tm * gmt = gmtime (&loc_seconds); + LLStringUtil::format_map_t args; + args["[MDAY]"] = llformat ("%d", gmt->tm_mday); + replacement = LLStringOps::sDayFormat; + LLStringUtil::format(replacement, args); + } + else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" ) + { + struct tm * gmt = gmtime (&loc_seconds); + if(gmt->tm_hour<12) + { + replacement = LLStringOps::sAM; + } + else + { + replacement = LLStringOps::sPM; + } + } + else + { + replacement = datetime.toHTTPDateString(code); + } // *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format // to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738). -- cgit v1.2.3 From 279f58051d0e387807ae8ad18c9004d2205f4479 Mon Sep 17 00:00:00 2001 From: Sergei Litovchuk Date: Sat, 29 May 2010 19:36:55 +0300 Subject: FIXED Linux build. Added forward specialization of LLStringUtil::format before use in LLStringUtil::formatDatetime. --HG-- branch : product-engine --- indra/llcommon/llstring.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 8197e3e642..f14d947734 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -874,6 +874,10 @@ namespace LLStringFn //////////////////////////////////////////////////////////// +// Forward specialization of LLStringUtil::format before use in LLStringUtil::formatDatetime. +template<> +S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions); + //static template<> void LLStringUtil::getTokens(const std::string& instr, std::vector& tokens, const std::string& delims) -- cgit v1.2.3 From 4c31f60bba890e5c320c4bc6fd0ca1c5ce741830 Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Tue, 22 Jun 2010 18:33:39 +0100 Subject: EXT-7926 FIXED Fixed crash opening About for non-English locales. Calling std::locale("fr_FR.UTF-8") crashes on Linux and Mac. Or rather, it throws an exception when it doesn't know the locale and we didn't handle the exception. I now catch the exception and output an error rather than crash. Note, this happened because of change 703f3bcf7069, which made us actually pass a real locale string instead of just "C". So, we were never actually supporting a locale for LLStringUtil::formatNumber(). There is therefore an open task of making formatNumber() actually respect the locale. I'll report a separate JIRA to capture that task. --- indra/llcommon/llstring.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f14d947734..f5eb552d99 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -994,7 +994,14 @@ void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) convertToS32 (decimals, intDecimals); if (!sLocale.empty()) { - strStream.imbue (std::locale(sLocale.c_str())); + // imbue() throws if the locale is unknown! (EXT-7926) + try + { + strStream.imbue(std::locale(sLocale.c_str())); + } catch (const std::exception &e) + { + LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL; + } } if (!intDecimals) -- cgit v1.2.3 From ccad528d5fb5889e9826ca045de5e7315be5942e Mon Sep 17 00:00:00 2001 From: Lynx Linden Date: Tue, 22 Jun 2010 18:55:04 +0100 Subject: EXT-7926 FIXED Minor typo correction. --- indra/llcommon/llstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index f5eb552d99..ffdac5d411 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -994,7 +994,7 @@ void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) convertToS32 (decimals, intDecimals); if (!sLocale.empty()) { - // imbue() throws if the locale is unknown! (EXT-7926) + // std::locale() throws if the locale is unknown! (EXT-7926) try { strStream.imbue(std::locale(sLocale.c_str())); -- cgit v1.2.3 From dfc20a824944d372c6978ca7b89289ec542554a9 Mon Sep 17 00:00:00 2001 From: Nat Goodspeed Date: Tue, 22 Jun 2010 14:59:34 -0400 Subject: EXT-7926: Remove unreferenced catch-clause variable (MSVC error). --- indra/llcommon/llstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index ffdac5d411..1561bda201 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -998,7 +998,7 @@ void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) try { strStream.imbue(std::locale(sLocale.c_str())); - } catch (const std::exception &e) + } catch (const std::exception &) { LL_WARNS_ONCE("Locale") << "Cannot set locale to " << sLocale << LL_ENDL; } -- cgit v1.2.3 From 3c4f82b2984c0cf70b2bc61190495cf9cf1a6aad Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Fri, 23 Jul 2010 10:26:28 +0300 Subject: EXT-8318 ADDITIONAL FIXED ensure that thousands separator is in utf8 format (on Windows) before converting it to LLWString. Problem on Windows: ================== LLPanelMainInventory::updateItemcountText() formats number using viewer locale. non-break space is detected as unknown symbols while converting utf8str_to_wstring when formatted text is set to LLTextBox. FIX: === Added converting of string to multi-byte string and then to utf8 string while formatting on Windows. created opposite to "ll_convert_wide_to_string" function "ll_convert_string_to_wide" and helper function to call both of them. It is used now to convert result of formatted string while formatting integer number in locale. Fix affects Windows only. Reviewed by Richard Nelson at https://codereview.productengine.com/secondlife/r/775/ --HG-- branch : product-engine --- indra/llcommon/llstring.cpp | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 1561bda201..804c00fd60 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -633,14 +633,14 @@ namespace snprintf_hack } } -std::string ll_convert_wide_to_string(const wchar_t* in) +std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) { std::string out; if(in) { int len_in = wcslen(in); int len_out = WideCharToMultiByte( - CP_ACP, + code_page, 0, in, len_in, @@ -655,7 +655,7 @@ std::string ll_convert_wide_to_string(const wchar_t* in) if(pout) { WideCharToMultiByte( - CP_ACP, + code_page, 0, in, len_in, @@ -669,6 +669,31 @@ std::string ll_convert_wide_to_string(const wchar_t* in) } return out; } + +wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page) +{ + int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0); + + // reserve place to NULL terminator + wchar_t* w_out = new wchar_t[output_str_len + 1]; + + memset(w_out, 0, output_str_len + 1); + MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len); + + //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858. + w_out[output_str_len] = 0; + + return w_out; +} + +std::string ll_convert_string_to_utf8_string(const std::string& in) +{ + wchar_t* w_mesg = ll_convert_string_to_wide(in, CP_ACP); + std::string out_utf8 = ll_convert_wide_to_string(w_mesg, CP_UTF8); + delete[] w_mesg; + + return out_utf8; +} #endif // LL_WINDOWS long LLStringOps::sPacificTimeOffset = 0; -- cgit v1.2.3 From 3ec027b3161422822858b94e2743b963296f6250 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Fri, 23 Jul 2010 12:53:37 +0300 Subject: EXT-8318 ADDITIONAL FIXED avoid an extra copy of std::string Reviewed by Richard Nelson at https://codereview.productengine.com/secondlife/r/775/ --HG-- branch : product-engine --- indra/llcommon/llstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 804c00fd60..852a57af85 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -689,7 +689,7 @@ wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page std::string ll_convert_string_to_utf8_string(const std::string& in) { wchar_t* w_mesg = ll_convert_string_to_wide(in, CP_ACP); - std::string out_utf8 = ll_convert_wide_to_string(w_mesg, CP_UTF8); + std::string out_utf8(ll_convert_wide_to_string(w_mesg, CP_UTF8)); delete[] w_mesg; return out_utf8; -- cgit v1.2.3 From 8e461d902ed12b6a054cb92a19835d7af2a31474 Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 26 Jul 2010 11:44:50 +0300 Subject: EXT-8318 FIX IMPROVED Code is refactored - avoid using of a separate call of the MultiByteToWideChar to get length of output string. Assumprion is: wide char buffer requires not more than input string length plus one for a null terminator. Reviewed by Richard Nelson at https://codereview.productengine.com/secondlife/r/775/ --HG-- branch : product-engine --- indra/llcommon/llstring.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 852a57af85..671b0a108c 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -672,16 +672,23 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page) { - int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0); + // From review: + // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input, + // plus one for a null terminator, and be guaranteed to not overflow. + + // Normally, I'd call that sort of thing premature optimization, + // but we *are* seeing string operations taking a bunch of time, especially when constructing widgets. +// int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0); // reserve place to NULL terminator + int output_str_len = in.length(); wchar_t* w_out = new wchar_t[output_str_len + 1]; memset(w_out, 0, output_str_len + 1); - MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len); + int real_output_str_len = MultiByteToWideChar (code_page, 0, in.c_str(), in.length(), w_out, output_str_len); //looks like MultiByteToWideChar didn't add null terminator to converted string, see EXT-4858. - w_out[output_str_len] = 0; + w_out[real_output_str_len] = 0; return w_out; } -- cgit v1.2.3 From 002bbd885b1e22db12229c3a8ffb6c4fdbfdfc5c Mon Sep 17 00:00:00 2001 From: Mike Antipov Date: Mon, 26 Jul 2010 13:04:28 +0300 Subject: EXT-8318 FIX IMPROVED converted EOLs --HG-- branch : product-engine --- indra/llcommon/llstring.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 671b0a108c..2693c0e22b 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -673,9 +673,9 @@ std::string ll_convert_wide_to_string(const wchar_t* in, unsigned int code_page) wchar_t* ll_convert_string_to_wide(const std::string& in, unsigned int code_page) { // From review: - // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input, - // plus one for a null terminator, and be guaranteed to not overflow. - + // We can preallocate a wide char buffer that is the same length (in wchar_t elements) as the utf8 input, + // plus one for a null terminator, and be guaranteed to not overflow. + // Normally, I'd call that sort of thing premature optimization, // but we *are* seeing string operations taking a bunch of time, especially when constructing widgets. // int output_str_len = MultiByteToWideChar(code_page, 0, in.c_str(), in.length(), NULL, 0); -- cgit v1.2.3 From 46334b6310ca76fea0f712b2e9dd1084af387f25 Mon Sep 17 00:00:00 2001 From: Vadim Savchuk Date: Thu, 5 Aug 2010 15:57:19 +0300 Subject: EXT-8309 FIXED Incorrect French date format in place profile and status bar. Changes: - Added support for formatting day of the month without leading zero ("sday"). - Changed date format in place profile (landmark info) and in the top status bar according to bug reporter's request. Technical details: Actually implementation of strftime() in Linux and Windows supports stripping the leading zero (with "%-d" and "%#d" respectively). But that's not supported in MacOSX, so I had to reimplement it. Reviewed by Sergey Litovchuk at https://codereview.productengine.com/secondlife/r/842/ --HG-- branch : product-engine --- indra/llcommon/llstring.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 2693c0e22b..faf7aa51f1 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -758,6 +758,7 @@ void LLStringOps::setupDatetimeInfo (bool daylight) datetimeToCodes["month"] = "%B"; // August datetimeToCodes["mthnum"] = "%m"; // 08 datetimeToCodes["day"] = "%d"; // 31 + datetimeToCodes["sday"] = "%-d"; // 9 datetimeToCodes["hour24"] = "%H"; // 14 datetimeToCodes["hour"] = "%H"; // 14 datetimeToCodes["hour12"] = "%I"; // 02 @@ -1127,6 +1128,11 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token, replacement = LLStringOps::sDayFormat; LLStringUtil::format(replacement, args); } + else if (code == "%-d") + { + struct tm * gmt = gmtime (&loc_seconds); + replacement = llformat ("%d", gmt->tm_mday); // day of the month without leading zero + } else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" ) { struct tm * gmt = gmtime (&loc_seconds); -- cgit v1.2.3 From 06b0d72efa96b6a0ed665f7cd46f358c48929e7b Mon Sep 17 00:00:00 2001 From: Oz Linden Date: Fri, 13 Aug 2010 07:24:57 -0400 Subject: Change license from GPL to LGPL (version 2.1) --- indra/llcommon/llstring.cpp | 36 +++++++++++++++--------------------- 1 file changed, 15 insertions(+), 21 deletions(-) (limited to 'indra/llcommon/llstring.cpp') diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index faf7aa51f1..33b55d843c 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -2,31 +2,25 @@ * @file llstring.cpp * @brief String utility functions and the std::string class. * - * $LicenseInfo:firstyear=2001&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * $LicenseInfo:firstyear=2001&license=viewerlgpl$ * Second Life Viewer Source Code - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed by you and Linden Lab. Terms of - * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * Copyright (C) 2010, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. * - * There are special exceptions to the terms and conditions of the GPL as - * it is applied to this Source Code. View the full text of the exception - * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at - * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. * - * By copying, modifying or distributing this software, you acknowledge - * that you have read and understood your obligations described above, - * and agree to abide by those obligations. + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO - * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA * $/LicenseInfo$ */ -- cgit v1.2.3