summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync/notifier/base/string.cc
diff options
context:
space:
mode:
authornick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-10 06:05:27 +0000
committernick@chromium.org <nick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-10 06:05:27 +0000
commit5852edc1b6eab234b9e048c41dd0d664ae7fc747 (patch)
tree9e5d8eb4833b76cdb11e66fc3607689e0f5e0122 /chrome/browser/sync/notifier/base/string.cc
parentf6059e37f8b8ac335ce18a189a13e702974a1c7e (diff)
downloadchromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.zip
chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.tar.gz
chromium_src-5852edc1b6eab234b9e048c41dd0d664ae7fc747.tar.bz2
Initial commit of sync engine code to browser/sync.
The code is not built on any platform yet. That will arrive as a subsequent checkin. This is an implementation of the interface exposed earlier through syncapi.h. It is the client side of a sync protocol that lets users sync their browser data (currently, just bookmarks) with their Google Account. Table of contents: browser/sync/ protocol - The protocol definition, and other definitions necessary to connect to the service. syncable/ - defines a data model for syncable objects, and provides a sqlite-based backing store for this model. engine/ - includes the core sync logic, including commiting changes to the server, downloading changes from the server, resolving conflicts, other parts of the sync algorithm. engine/net - parts of the sync engine focused on the business of talking to the server. Some of this is binds a generic "server connection" interface to a concrete implementation provided by Chromium. notifier - the part of the syncer focused on the business of sending and receiving xmpp notifications. Notifications are used instead of polling to achieve very low latency change propagation. util - not necessarily sync specific utility code. Much of this is scaffolding which should either be replaced by, or merged with, the utility code in base/. BUG=none TEST=this code includes its own suite of unit tests. Review URL: http://codereview.chromium.org/194065 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25850 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync/notifier/base/string.cc')
-rw-r--r--chrome/browser/sync/notifier/base/string.cc403
1 files changed, 403 insertions, 0 deletions
diff --git a/chrome/browser/sync/notifier/base/string.cc b/chrome/browser/sync/notifier/base/string.cc
new file mode 100644
index 0000000..c3ef54d
--- /dev/null
+++ b/chrome/browser/sync/notifier/base/string.cc
@@ -0,0 +1,403 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifdef OS_MACOSX
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+#include <float.h>
+#include <string.h>
+
+#include "base/format_macros.h"
+#include "base/string_util.h"
+#include "chrome/browser/sync/notifier/base/string.h"
+#include "talk/base/common.h"
+#include "talk/base/logging.h"
+#include "talk/base/stringencode.h"
+
+using base::snprintf;
+
+namespace notifier {
+
+std::string HtmlEncode(const std::string& src) {
+ size_t max_length = src.length() * 6 + 1;
+ std::string dest;
+ dest.resize(max_length);
+ size_t new_size = talk_base::html_encode(&dest[0], max_length,
+ src.data(), src.length());
+ dest.resize(new_size);
+ return dest;
+}
+
+std::string HtmlDecode(const std::string& src) {
+ size_t max_length = src.length() + 1;
+ std::string dest;
+ dest.resize(max_length);
+ size_t new_size = talk_base::html_decode(&dest[0], max_length,
+ src.data(), src.length());
+ dest.resize(new_size);
+ return dest;
+}
+
+std::string UrlEncode(const std::string& src) {
+ size_t max_length = src.length() * 6 + 1;
+ std::string dest;
+ dest.resize(max_length);
+ size_t new_size = talk_base::url_encode(&dest[0], max_length,
+ src.data(), src.length());
+ dest.resize(new_size);
+ return dest;
+}
+
+std::string UrlDecode(const std::string& src) {
+ size_t max_length = src.length() + 1;
+ std::string dest;
+ dest.resize(max_length);
+ size_t new_size = talk_base::url_decode(&dest[0], max_length,
+ src.data(), src.length());
+ dest.resize(new_size);
+ return dest;
+}
+
+int CharToHexValue(char hex) {
+ if (hex >= '0' && hex <= '9') {
+ return hex - '0';
+ } else if (hex >= 'A' && hex <= 'F') {
+ return hex - 'A' + 10;
+ } else if (hex >= 'a' && hex <= 'f') {
+ return hex - 'a' + 10;
+ } else {
+ return -1;
+ }
+}
+
+// Template function to convert a string to an int/int64
+// If strict is true, check for the validity and overflow
+template<typename T>
+bool ParseStringToIntTemplate(const char* str,
+ T* value,
+ bool strict,
+ T min_value) {
+ ASSERT(str);
+ ASSERT(value);
+
+ // Skip spaces
+ while (*str == ' ') {
+ ++str;
+ }
+
+ // Process sign
+ int c = static_cast<int>(*str++); // current char
+ int possible_sign = c; // save sign indication
+ if (c == '-' || c == '+') {
+ c = static_cast<int>(*str++);
+ }
+
+ // Process numbers
+ T total = 0;
+ while (c && (c = CharToDigit(static_cast<char>(c))) != -1) {
+ // Check for overflow
+ if (strict && (total < min_value / 10 ||
+ (total == min_value / 10 &&
+ c > ((-(min_value + 10)) % 10)))) {
+ return false;
+ }
+
+ // Accumulate digit
+ // Note that we accumulate in the negative direction so that we will not
+ // blow away with the largest negative number
+ total = 10 * total - c;
+
+ // Get next char
+ c = static_cast<int>(*str++);
+ }
+
+ // Fail if encountering non-numeric character
+ if (strict && c == -1) {
+ return false;
+ }
+
+ // Negate the number if needed
+ if (possible_sign == '-') {
+ *value = total;
+ } else {
+ // Check for overflow
+ if (strict && total == min_value) {
+ return false;
+ }
+
+ *value = -total;
+ }
+
+ return true;
+}
+
+// Convert a string to an int
+// If strict is true, check for the validity and overflow
+bool ParseStringToInt(const char* str, int* value, bool strict) {
+ return ParseStringToIntTemplate<int>(str, value, strict, kint32min);
+}
+
+// Convert a string to an int
+// This version does not check for the validity and overflow
+int StringToInt(const char* str) {
+ int value = 0;
+ ParseStringToInt(str, &value, false);
+ return value;
+}
+
+// Convert a string to an unsigned int.
+// If strict is true, check for the validity and overflow
+bool ParseStringToUint(const char* str, uint32* value, bool strict) {
+ ASSERT(str);
+ ASSERT(value);
+
+ int64 int64_value;
+ if (!ParseStringToInt64(str, &int64_value, strict)) {
+ return false;
+ }
+ if (int64_value < 0 || int64_value > kuint32max) {
+ return false;
+ }
+
+ *value = static_cast<uint32>(int64_value);
+ return true;
+}
+
+// Convert a string to an int
+// This version does not check for the validity and overflow
+uint32 StringToUint(const char* str) {
+ uint32 value = 0;
+ ParseStringToUint(str, &value, false);
+ return value;
+}
+
+// Convert a string to an int64
+// If strict is true, check for the validity and overflow
+bool ParseStringToInt64(const char* str, int64* value, bool strict) {
+ return ParseStringToIntTemplate<int64>(str, value, strict, kint64min);
+}
+
+// Convert a string to an int64
+// This version does not check for the validity and overflow
+int64 StringToInt64(const char* str) {
+ int64 value = 0;
+ ParseStringToInt64(str, &value, false);
+ return value;
+}
+
+// Convert a string to a double
+// If strict is true, check for the validity and overflow
+bool ParseStringToDouble(const char* str, double* value, bool strict) {
+ ASSERT(str);
+ ASSERT(value);
+
+ // Skip spaces
+ while (*str == ' ') {
+ ++str;
+ }
+
+ // Process sign
+ int c = static_cast<int>(*str++); // current char
+ int sign = c; // save sign indication
+ if (c == '-' || c == '+') {
+ c = static_cast<int>(*str++);
+ }
+
+ // Process numbers before "."
+ double total = 0.0;
+ while (c && (c != '.') && (c = CharToDigit(static_cast<char>(c))) != -1) {
+ // Check for overflow
+ if (strict && total >= DBL_MAX / 10) {
+ return false;
+ }
+
+ // Accumulate digit
+ total = 10.0 * total + c;
+
+ // Get next char
+ c = static_cast<int>(*str++);
+ }
+
+ // Process "."
+ if (c == '.') {
+ c = static_cast<int>(*str++);
+ } else {
+ // Fail if encountering non-numeric character
+ if (strict && c == -1) {
+ return false;
+ }
+ }
+
+ // Process numbers after "."
+ double power = 1.0;
+ while ((c = CharToDigit(static_cast<char>(c))) != -1) {
+ // Check for overflow
+ if (strict && total >= DBL_MAX / 10) {
+ return false;
+ }
+
+ // Accumulate digit
+ total = 10.0 * total + c;
+ power *= 10.0;
+
+ // Get next char
+ c = static_cast<int>(*str++);
+ }
+
+ // Get the final number
+ *value = total / power;
+ if (sign == '-') {
+ *value = -(*value);
+ }
+
+ return true;
+}
+
+// Convert a string to a double
+// This version does not check for the validity and overflow
+double StringToDouble(const char* str) {
+ double value = 0;
+ ParseStringToDouble(str, &value, false);
+ return value;
+}
+
+// Convert a float to a string
+std::string FloatToString(float f) {
+ char buf[80];
+ snprintf(buf, sizeof(buf), "%f", f);
+ return std::string(buf);
+}
+
+std::string DoubleToString(double d) {
+ char buf[160];
+ snprintf(buf, sizeof(buf), "%.17g", d);
+ return std::string(buf);
+}
+
+std::string UIntToString(uint32 i) {
+ char buf[80];
+ snprintf(buf, sizeof(buf), "%lu", i);
+ return std::string(buf);
+}
+
+// Convert an int to a string
+std::string IntToString(int i) {
+ char buf[80];
+ snprintf(buf, sizeof(buf), "%d", i);
+ return std::string(buf);
+}
+
+// Convert an int64 to a string
+std::string Int64ToString(int64 i64) {
+ char buf[80];
+ snprintf(buf, sizeof(buf), "%" PRId64 "d", i64);
+ return std::string(buf);
+}
+
+std::string UInt64ToString(uint64 i64) {
+ char buf[80];
+ snprintf(buf, sizeof(buf), "%" PRId64 "u", i64);
+ return std::string(buf);
+}
+
+std::string Int64ToHexString(int64 i64) {
+ char buf[80];
+ snprintf(buf, sizeof(buf), "%" PRId64 "x", i64);
+ return std::string(buf);
+}
+
+// Parse a single "delim" delimited string from "*source"
+// Modify *source to point after the delimiter.
+// If no delimiter is present after the string, set *source to NULL.
+//
+// Mainly a stringified wrapper around strpbrk()
+std::string SplitOneStringToken(const char** source, const char* delim) {
+ ASSERT(source);
+ ASSERT(delim);
+
+ if (!*source) {
+ return std::string();
+ }
+ const char* begin = *source;
+ *source = strpbrk(*source, delim);
+ if (*source) {
+ return std::string(begin, (*source)++);
+ } else {
+ return std::string(begin);
+ }
+}
+
+std::string LowerWithUnderToPascalCase(const char* lower_with_under) {
+ ASSERT(lower_with_under);
+
+ std::string pascal_case;
+ bool make_upper = true;
+ for (; *lower_with_under != '\0'; lower_with_under++) {
+ char current_char = *lower_with_under;
+ if (current_char == '_') {
+ ASSERT(!make_upper);
+ make_upper = true;
+ continue;
+ }
+ if (make_upper) {
+ current_char = toupper(current_char);
+ make_upper = false;
+ }
+ pascal_case.append(1, current_char);
+ }
+ return pascal_case;
+}
+
+std::string PascalCaseToLowerWithUnder(const char* pascal_case) {
+ ASSERT(pascal_case);
+
+ std::string lower_with_under;
+ bool previous_was_upper = true;
+ for(; *pascal_case != '\0'; pascal_case++) {
+ char current_char = *pascal_case;
+ if (isupper(current_char)) {
+ // DNSName should be dns_name
+ if ((islower(pascal_case[1]) && !lower_with_under.empty()) ||
+ !previous_was_upper) {
+ lower_with_under.append(1, '_');
+ }
+ current_char = tolower(current_char);
+ } else if (previous_was_upper) {
+ previous_was_upper = false;
+ }
+ lower_with_under.append(1, current_char);
+ }
+ return lower_with_under;
+}
+void StringReplace(std::string* s,
+ const char* old_sub,
+ const char* new_sub,
+ bool replace_all) {
+ ASSERT(s);
+
+ // If old_sub is empty, nothing to do
+ if (!old_sub || !*old_sub) {
+ return;
+ }
+
+ int old_sub_size = strlen(old_sub);
+ std::string res;
+ std::string::size_type start_pos = 0;
+
+ do {
+ std::string::size_type pos = s->find(old_sub, start_pos);
+ if (pos == std::string::npos) {
+ break;
+ }
+ res.append(*s, start_pos, pos - start_pos);
+ res.append(new_sub);
+ start_pos = pos + old_sub_size; // start searching again after the "old"
+ } while (replace_all);
+ res.append(*s, start_pos, s->length() - start_pos);
+
+ *s = res;
+}
+
+} // namespace notifier