Temporarily switch the numeric locale formatting to 'classic' while we process the signaling message.

This is to avoid running into problems with jsoncpp and parts of libjingle
where we use STL and CRT routines that refer to the global locale for formatting.
If the current locale is e.g. Spanish, then numbers will be formatted as "12,34"
and not "12.34" as some parts (not all) of jsoncpp expect.

Code I noticed where we might run into this is here (but it's likely that there are
more places):

third_party\libjingle\source\talk\p2p\base\candidate.h (preference_str)
third_party_mods\libjingle\source\talk\app\webrtc\webrtc_json.cc
third_party\jsoncpp\src\lib_json\*writer*
third_party\jsoncpp\src\lib_json\*reader*

BUG=69
TEST=Verify that the signaling messages always contain numbers formatted as "1.23" and never "1,23" even though the regional settings on the machine specify otherwise (e.g. try setting it to Spanish).
Review URL: http://webrtc-codereview.appspot.com/140007

git-svn-id: http://webrtc.googlecode.com/svn/trunk@564 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
tommi@webrtc.org 2011-09-08 17:46:46 +00:00
parent 06e2c11703
commit 73f98aebc6

View File

@ -28,6 +28,8 @@
#include "talk/app/webrtc/webrtc_json.h"
#include <stdio.h>
#include <locale>
#include <string>
#include "talk/base/json.h"
@ -36,6 +38,41 @@
#include "talk/session/phone/mediasessionclient.h"
#include "talk/session/phone/codec.h"
namespace {
// Before [de]serializing, we need to work around a bug in jsoncpp where
// locale sensitive string conversion functions are used (e.g. sprintf,
// sscanf and stl). The problem is that depending on what the current
// locale is, numbers might be formatted differently than the jsoncpp code
// otherwise expects. E.g. sprintf might format a number as "1,234" and
// the parser assumes that it would be "1.234".
class AutoSwitchToClassicLocale {
public:
AutoSwitchToClassicLocale() {
const char* locale_name = setlocale(LC_NUMERIC, NULL);
if (locale_name)
saved_locale_ = locale_name;
// Switch the CRT to "C".
setlocale(LC_NUMERIC, "C");
// Switch STL to classic.
cxx_locale_ = std::locale::global(std::locale::classic());
}
~AutoSwitchToClassicLocale() {
// Switch the locale back to what it was before.
std::locale::global(cxx_locale_);
setlocale(LC_NUMERIC, saved_locale_.c_str());
}
private:
std::string saved_locale_;
std::locale cxx_locale_;
};
}
namespace webrtc {
static const int kIceComponent = 1;
static const int kIceFoundation = 1;
@ -110,6 +147,9 @@ bool GetJSONSignalingMessage(
const cricket::SessionDescription* sdp,
const std::vector<cricket::Candidate>& candidates,
std::string* signaling_message) {
// See documentation for AutoSwitchToClassicLocale.
AutoSwitchToClassicLocale auto_switch;
const cricket::ContentInfo* audio_content = GetFirstAudioContent(sdp);
const cricket::ContentInfo* video_content = GetFirstVideoContent(sdp);
@ -129,8 +169,9 @@ bool GetJSONSignalingMessage(
Json::Value signal;
Append(&signal, "media", media);
// now serialize
// Now serialize.
*signaling_message = Serialize(signal);
return true;
}
@ -258,6 +299,10 @@ bool ParseJSONSignalingMessage(const std::string& signaling_message,
cricket::SessionDescription*& sdp,
std::vector<cricket::Candidate>* candidates) {
ASSERT(!sdp); // expect this to be NULL
// See documentation for AutoSwitchToClassicLocale.
AutoSwitchToClassicLocale auto_switch;
// first deserialize message
Json::Value value;
if (!Deserialize(signaling_message, &value)) {
@ -440,16 +485,16 @@ void Append(Json::Value* object, const std::string& key, char * value) {
void Append(Json::Value* object, const std::string& key, double value) {
(*object)[key] = Json::Value(value);
}
void Append(Json::Value* object, const std::string& key, float value) {
(*object)[key] = Json::Value(value);
}
void Append(Json::Value* object, const std::string& key, int value) {
(*object)[key] = Json::Value(value);
}
void Append(Json::Value* object, const std::string& key,
const std::string& value) {
(*object)[key] = Json::Value(value);
}
void Append(Json::Value* object, const std::string& key, uint32 value) {
(*object)[key] = Json::Value(value);
}