summaryrefslogtreecommitdiffstats
path: root/o3d/utils
diff options
context:
space:
mode:
authorgspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-27 23:15:42 +0000
committergspencer@google.com <gspencer@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-27 23:15:42 +0000
commit05b47f7a8c5451f858dc220df0e3a97542edace6 (patch)
treea2273d619f0625c9d44d40842845ccce2eac1045 /o3d/utils
parent5cdc8bdb4c847cefe7f4542bd10c9880c2c557a0 (diff)
downloadchromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.zip
chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.gz
chromium_src-05b47f7a8c5451f858dc220df0e3a97542edace6.tar.bz2
This is the O3D source tree's initial commit to the Chromium tree. It
is not built or referenced at all by the chrome build yet, and doesn't yet build in it's new home. We'll change that shortly. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17035 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'o3d/utils')
-rw-r--r--o3d/utils/build.scons45
-rw-r--r--o3d/utils/cross/file_path_utils.cc161
-rw-r--r--o3d/utils/cross/file_path_utils.h72
-rw-r--r--o3d/utils/cross/file_path_utils_test.cc183
-rw-r--r--o3d/utils/cross/file_text_reader.cc185
-rw-r--r--o3d/utils/cross/file_text_reader.h73
-rw-r--r--o3d/utils/cross/file_text_reader_test.cc261
-rw-r--r--o3d/utils/cross/file_text_writer.cc68
-rw-r--r--o3d/utils/cross/file_text_writer.h70
-rw-r--r--o3d/utils/cross/json_writer.cc246
-rw-r--r--o3d/utils/cross/json_writer.h121
-rw-r--r--o3d/utils/cross/json_writer_test.cc212
-rw-r--r--o3d/utils/cross/string_reader.cc110
-rw-r--r--o3d/utils/cross/string_reader.h71
-rw-r--r--o3d/utils/cross/string_reader_test.cc200
-rw-r--r--o3d/utils/cross/string_writer.cc55
-rw-r--r--o3d/utils/cross/string_writer.h62
-rw-r--r--o3d/utils/cross/string_writer_test.cc120
-rw-r--r--o3d/utils/cross/structured_writer.h103
-rw-r--r--o3d/utils/cross/temporary_file.cc83
-rw-r--r--o3d/utils/cross/temporary_file.h86
-rw-r--r--o3d/utils/cross/temporary_file_test.cc113
-rw-r--r--o3d/utils/cross/text_reader.cc66
-rw-r--r--o3d/utils/cross/text_reader.h91
-rw-r--r--o3d/utils/cross/text_writer.cc104
-rw-r--r--o3d/utils/cross/text_writer.h95
26 files changed, 3056 insertions, 0 deletions
diff --git a/o3d/utils/build.scons b/o3d/utils/build.scons
new file mode 100644
index 0000000..f06781e
--- /dev/null
+++ b/o3d/utils/build.scons
@@ -0,0 +1,45 @@
+# Copyright 2009, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+Import('env')
+
+inputs = [
+ 'cross/file_path_utils.cc',
+ 'cross/file_text_reader.cc',
+ 'cross/file_text_writer.cc',
+ 'cross/json_writer.cc',
+ 'cross/string_reader.cc',
+ 'cross/string_writer.cc',
+ 'cross/temporary_file.cc',
+ 'cross/text_reader.cc',
+ 'cross/text_writer.cc',
+]
+
+lib = env.ComponentLibrary('o3dUtils', inputs)
diff --git a/o3d/utils/cross/file_path_utils.cc b/o3d/utils/cross/file_path_utils.cc
new file mode 100644
index 0000000..db4216e
--- /dev/null
+++ b/o3d/utils/cross/file_path_utils.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definitions for some convenience functions
+// used to make FilePaths more useful.
+
+#include "utils/cross/file_path_utils.h"
+#include "base/file_util.h"
+#include "base/string_util.h"
+#include "base/file_path.h"
+
+namespace o3d {
+std::wstring FilePathToWide(const FilePath& input) {
+#if defined(OS_WIN)
+ return input.value();
+#else
+ return UTF8ToWide(input.value());
+#endif
+}
+
+FilePath WideToFilePath(const std::wstring& input) {
+#if defined(OS_WIN)
+ return FilePath(input);
+#else
+ return FilePath(WideToUTF8(input));
+#endif
+}
+
+String FilePathToUTF8(const FilePath& input) {
+#if defined(OS_WIN)
+ return WideToUTF8(input.value());
+#else
+ return input.value();
+#endif
+}
+
+FilePath UTF8ToFilePath(const String& input) {
+#if defined(OS_WIN)
+ return FilePath(UTF8ToWide(input));
+#else
+ return FilePath(input);
+#endif
+}
+
+bool AbsolutePath(FilePath* absolute_path) {
+#if defined(OS_WIN)
+ return file_util::AbsolutePath(absolute_path);
+#else
+ // On the Posix implementation of file_util::AbsolutePath,
+ // realpath() is used, which only works if the path actually exists.
+ // So, we try using AbsolutePath, and if it doesn't work, we fake it
+ // by just prepending the current working direcory if it's not
+ // already absolute.
+ if (absolute_path->IsAbsolute()) {
+ return true;
+ } else {
+ FilePath new_absolute_path = FilePath(*absolute_path);
+ if (file_util::AbsolutePath(&new_absolute_path)) {
+ *absolute_path = new_absolute_path;
+ return true;
+ } else {
+ // OK, so we failed to make an absolute path above, and we know
+ // it's not an absolute path to begin with, so we just prepend
+ // the current working directory.
+ FilePath cwd_path;
+ if (!file_util::GetCurrentDirectory(&cwd_path)) {
+ return false;
+ }
+ *absolute_path = cwd_path.Append(*absolute_path);
+ return true;
+ }
+ }
+#endif
+}
+
+bool GetRelativePathIfPossible(const FilePath& base_dir,
+ const FilePath& candidate,
+ FilePath *result) {
+ FilePath parent = FilePath(base_dir.StripTrailingSeparators());
+ FilePath child = FilePath(candidate.StripTrailingSeparators());
+
+ // If we can't convert the child to an absolute path for some
+ // reason, then we just do nothing and return the candidate.
+ if (!child.IsAbsolute() && !AbsolutePath(&child)) {
+ *result = candidate;
+ return false;
+ }
+
+ // If we can't convert the parent to an absolute path for some
+ // reason, then we just do nothing and return the absolute path to
+ // the child.
+ if (!parent.IsAbsolute() && !AbsolutePath(&parent)) {
+ *result = child;
+ return false;
+ }
+
+ FilePath::StringType child_str = child.value();
+ FilePath::StringType parent_str = parent.value();
+
+ // If the child is too short, it can't be a child of parent, and if
+ // it doesn't have a separator in the right place, then it also
+ // can't be a child, so we return the absolute path to the child.
+ // file_util::AbsolutePath() normalizes '/' to '\' on Windows, so we
+ // only need to check kSeparators[0].
+ if (child_str.length() <= parent_str.length() ||
+ child_str[parent_str.length()] != FilePath::kSeparators[0]) {
+ *result = child;
+ return false;
+ }
+
+ if (
+#if defined(OS_WIN)
+ // file_util::AbsolutePath() does not flatten case on Windows,
+ // so we must do a case-insensitive compare.
+ StartsWith(child_str, parent_str, false)
+#else
+ StartsWithASCII(child_str, parent_str, true)
+#endif
+ ) {
+ // Add one to skip over the dir separator.
+ child_str = child_str.substr(parent_str.size() + 1);
+
+ // Now we know we can return the relative path.
+ *result = FilePath(child_str);
+ return true;
+ } else {
+ *result = FilePath(child_str);
+ return false;
+ }
+}
+
+} // end namespace o3d
diff --git a/o3d/utils/cross/file_path_utils.h b/o3d/utils/cross/file_path_utils.h
new file mode 100644
index 0000000..30de903
--- /dev/null
+++ b/o3d/utils/cross/file_path_utils.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration for some convenience functions
+// used to make FilePaths more useful.
+
+#ifndef O3D_UTILS_CROSS_FILE_PATH_UTILS_H_
+#define O3D_UTILS_CROSS_FILE_PATH_UTILS_H_
+
+#include <string>
+#include "core/cross/types.h"
+
+class FilePath;
+
+namespace o3d {
+// TODO: Go through the process to add these to FilePath
+// itself in the Chromium depot.
+
+std::wstring FilePathToWide(const FilePath& input);
+FilePath WideToFilePath(const std::wstring& input);
+String FilePathToUTF8(const FilePath& input);
+FilePath UTF8ToFilePath(const String& input);
+
+// On Windows, this is just the same as file_util::AbsolutePath.
+// On the Posix implementation of file_util::AbsolutePath,
+// realpath() is used, which only works if the path actually exists.
+// So, we try using AbsolutePath, and if it doesn't work, we fake it
+// by just prepending the cwd if it's not already an absolute path.
+bool AbsolutePath(FilePath* abs_path);
+
+// If the candidate is a child (a file or directory in a subdir of the
+// base directory or the base directory itself), then we figure out
+// the relative path to it. If not, then we just return the absolute
+// path to the candidate. Does not return any paths that would
+// require use of ".." to form a relative path. Returns true if the
+// path returned in "result" is a relative path.
+bool GetRelativePathIfPossible(const FilePath& base_dir,
+ const FilePath& candidate,
+ FilePath *result);
+
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_FILE_PATH_UTILS_H_
diff --git a/o3d/utils/cross/file_path_utils_test.cc b/o3d/utils/cross/file_path_utils_test.cc
new file mode 100644
index 0000000..e1447fc
--- /dev/null
+++ b/o3d/utils/cross/file_path_utils_test.cc
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of the file path utils.
+#include <stdio.h>
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/file_path_utils.h"
+
+namespace o3d {
+
+class FilePathUtilsTest : public testing::Test {
+};
+
+TEST_F(FilePathUtilsTest, ConvertFilePathToUTF8) {
+ std::string test_path("/this/is/a/path");
+ FilePath source_path(FILE_PATH_LITERAL("/this/is/a/path"));
+ EXPECT_EQ(test_path, FilePathToUTF8(source_path));
+}
+
+TEST_F(FilePathUtilsTest, ConvertFilePathToWide) {
+ std::wstring test_path(L"/this/is/a/path");
+ FilePath source_path(FILE_PATH_LITERAL("/this/is/a/path"));
+ EXPECT_EQ(test_path, FilePathToWide(source_path));
+}
+
+TEST_F(FilePathUtilsTest, ConvertWideToFilePath) {
+ std::wstring test_path(L"/this/is/a/path");
+ FilePath dest_path = WideToFilePath(test_path);
+ EXPECT_STREQ(FILE_PATH_LITERAL("/this/is/a/path"), dest_path.value().c_str());
+}
+
+TEST_F(FilePathUtilsTest, ConvertUTF8ToFilePath) {
+ std::string test_path("/this/is/a/path");
+ FilePath dest_path = UTF8ToFilePath(test_path);
+ EXPECT_STREQ(FILE_PATH_LITERAL("/this/is/a/path"), dest_path.value().c_str());
+}
+
+TEST_F(FilePathUtilsTest, AbsolutePathBasic) {
+ FilePath cwd;
+ file_util::GetCurrentDirectory(&cwd);
+#if defined(OS_WIN)
+ FilePath test_path(FILE_PATH_LITERAL("this\\is\\a\\path"));
+#else
+ FilePath test_path(FILE_PATH_LITERAL("this/is/a/path"));
+#endif
+ FilePath abs_path = test_path;
+ bool result = AbsolutePath(&abs_path);
+ FilePath expected_result = cwd;
+ expected_result = expected_result.Append(test_path);
+ EXPECT_STREQ(expected_result.value().c_str(), abs_path.value().c_str());
+}
+
+TEST_F(FilePathUtilsTest, AbsolutePathAlreadyAbsolute) {
+#if defined(OS_WIN)
+ FilePath test_path(FILE_PATH_LITERAL("c:\\this\\is\\a\\path"));
+#else
+ FilePath test_path(FILE_PATH_LITERAL("/this/is/a/path"));
+#endif
+ FilePath abs_path = test_path;
+ bool result = AbsolutePath(&abs_path);
+ EXPECT_STREQ(test_path.value().c_str(), abs_path.value().c_str());
+}
+
+#if defined(OS_WIN)
+TEST_F(FilePathUtilsTest, AbsolutePathAlreadyAbsoluteWindowsUnc) {
+ FilePath test_path(FILE_PATH_LITERAL("\\\\this\\is\\a\\path"));
+ FilePath abs_path = test_path;
+ bool result = AbsolutePath(&abs_path);
+ EXPECT_STREQ(test_path.value().c_str(), abs_path.value().c_str());
+}
+#endif
+
+TEST_F(FilePathUtilsTest, RelativePathsBasic) {
+#if defined(OS_WIN)
+ FilePath expected_result(FILE_PATH_LITERAL("under\\parent"));
+#else
+ FilePath expected_result(FILE_PATH_LITERAL("under/parent"));
+#endif
+ FilePath base_path(FILE_PATH_LITERAL("/this/is/a/path"));
+ FilePath child_path(FILE_PATH_LITERAL("/this/is/a/path/under/parent"));
+ FilePath result;
+ bool is_relative = GetRelativePathIfPossible(base_path, child_path, &result);
+ EXPECT_STREQ(expected_result.value().c_str(), result.value().c_str());
+ EXPECT_TRUE(is_relative);
+}
+
+#if defined(OS_WIN)
+TEST_F(FilePathUtilsTest, RelativePathsWindowsAbsolute) {
+ FilePath expected_result(FILE_PATH_LITERAL("under\\parent"));
+ FilePath base_path(FILE_PATH_LITERAL("c:\\this\\is\\a\\path"));
+ FilePath child_path(
+ FILE_PATH_LITERAL("c:\\this\\is\\a\\path\\under\\parent"));
+ FilePath result;
+ bool is_relative = GetRelativePathIfPossible(base_path, child_path, &result);
+ EXPECT_STREQ(expected_result.value().c_str(), result.value().c_str());
+ EXPECT_TRUE(is_relative);
+}
+
+TEST_F(FilePathUtilsTest, RelativePathsWindowsDifferentDrives) {
+ FilePath base_path(FILE_PATH_LITERAL("c:\\this\\is\\a\\path"));
+ FilePath child_path(
+ FILE_PATH_LITERAL("d:\\this\\is\\a\\path\\not\\under\\parent"));
+ FilePath result;
+ bool is_relative = GetRelativePathIfPossible(base_path, child_path, &result);
+ EXPECT_STREQ(child_path.value().c_str(), result.value().c_str());
+ EXPECT_FALSE(is_relative);
+}
+#endif
+
+TEST_F(FilePathUtilsTest, RelativePathsCaseDifferent) {
+ FilePath base_path(FILE_PATH_LITERAL("/This/Is/A/Path"));
+ FilePath child_path(FILE_PATH_LITERAL("/this/is/a/path/under/parent"));
+ FilePath result;
+ bool is_relative = GetRelativePathIfPossible(base_path, child_path, &result);
+#if defined(OS_WIN)
+ EXPECT_STREQ(FILE_PATH_LITERAL("under\\parent"), result.value().c_str());
+ EXPECT_TRUE(is_relative);
+#else
+ EXPECT_STREQ(child_path.value().c_str(), result.value().c_str());
+ EXPECT_FALSE(is_relative);
+#endif
+}
+
+TEST_F(FilePathUtilsTest, RelativePathsTrailingSlash) {
+#if defined(OS_WIN)
+ FilePath expected_result(FILE_PATH_LITERAL("under\\parent"));
+#else
+ FilePath expected_result(FILE_PATH_LITERAL("under/parent"));
+#endif
+ FilePath base_path(FILE_PATH_LITERAL("/this/is/a/path/"));
+ FilePath child_path(FILE_PATH_LITERAL("/this/is/a/path/under/parent"));
+ FilePath result;
+ bool is_relative = GetRelativePathIfPossible(base_path, child_path, &result);
+ EXPECT_STREQ(expected_result.value().c_str(), result.value().c_str());
+ EXPECT_TRUE(is_relative);
+}
+
+TEST_F(FilePathUtilsTest, RelativePathsRelativeInputs) {
+#if defined(OS_WIN)
+ FilePath expected_result(FILE_PATH_LITERAL("under\\parent"));
+#else
+ FilePath expected_result(FILE_PATH_LITERAL("under/parent"));
+#endif
+ FilePath base_path(FILE_PATH_LITERAL("this/is/a/path"));
+ FilePath child_path(FILE_PATH_LITERAL("this/is/a/path/under/parent"));
+ FilePath result;
+ bool is_relative = GetRelativePathIfPossible(base_path, child_path, &result);
+ EXPECT_STREQ(expected_result.value().c_str(), result.value().c_str());
+ EXPECT_TRUE(is_relative);
+}
+} // namespace o3d
diff --git a/o3d/utils/cross/file_text_reader.cc b/o3d/utils/cross/file_text_reader.cc
new file mode 100644
index 0000000..39e5057
--- /dev/null
+++ b/o3d/utils/cross/file_text_reader.cc
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class FileTextReader. The
+// tests are in string_reader_test.cc.
+
+#include "utils/cross/file_text_reader.h"
+
+#include <stdio.h>
+#include <sys/stat.h>
+#include "base/logging.h"
+#include "base/scoped_ptr.h"
+
+namespace o3d {
+
+FileTextReader::FileTextReader(FILE* input)
+ : TextReader(), input_(input) {
+ if (input_ == NULL) {
+ LOG(FATAL) << "Invalid NULL file pointer";
+ }
+ if (::ferror(input_) != 0) {
+ DLOG(FATAL) << "Invalid file pointer.";
+ }
+}
+
+FileTextReader::~FileTextReader() {
+}
+
+size_t FileTextReader::position() const {
+ if (input_) {
+ return ::ftell(input_);
+ } else {
+ return 0;
+ }
+}
+
+bool FileTextReader::IsAtEnd() const {
+ size_t position = ::ftell(input_);
+ if (::feof(input_) != 0) {
+ return true;
+ }
+ return GetFileSize() == position;
+}
+
+std::string FileTextReader::PeekString(std::string::size_type count) const {
+ if (IsAtEnd()) {
+ return std::string("");
+ }
+
+ // Find out where we are in the stream.
+ size_t original_pos = ::ftell(input_);
+
+ // We're just re-using code here -- the stream will not be affected
+ // because we will seek back to where we started.
+ std::string result = const_cast<FileTextReader*>(this)->ReadString(count);
+
+ // Go back to where we started in the stream.
+ ::fseek(input_, original_pos, SEEK_SET);
+ return result;
+}
+
+char FileTextReader::ReadChar() {
+ if (!IsAtEnd()) {
+ return ::fgetc(input_);
+ } else {
+ return 0;
+ }
+}
+
+std::string FileTextReader::ReadString(std::string::size_type count) {
+ if (count <= 0 || IsAtEnd()) {
+ return std::string("");
+ }
+
+ // Allocate a string to hold the data.
+ scoped_array<char> buffer(new char[count + 1]);
+
+ // Read it.
+ size_t count_read = ::fread(reinterpret_cast<void*>(buffer.get()),
+ sizeof(char),
+ count,
+ input_);
+
+ // Make sure it's null terminated.
+ (buffer.get())[count_read] = 0;
+ return std::string(buffer.get());
+}
+
+std::string FileTextReader::ReadLine() {
+ // Find out where we are in the stream.
+ int original_pos = ::ftell(input_);
+
+ // Find the occurance of the next eol character, regardless of what
+ // kind of terminator it is.
+ static const char linefeed = '\n';
+ static const char carriage_return = '\r';
+ int eol_pos = -1;
+ int eol_len = 1;
+ while (!IsAtEnd()) {
+ char eol = ::fgetc(input_);
+ if (eol == linefeed) {
+ eol_pos = ::ftell(input_);
+ break;
+ }
+ if (eol == carriage_return) {
+ eol_pos = ::ftell(input_);
+ if (IsAtEnd()) {
+ break;
+ }
+ eol = ::fgetc(input_);
+ if (eol == linefeed) {
+ eol_len = 2;
+ }
+ break;
+ }
+ }
+
+ // Go back to where we started in the stream.
+ ::fseek(input_, original_pos, SEEK_SET);
+
+ if (eol_pos > 0) {
+ int count = eol_pos - original_pos - 1;
+ std::string result = ReadString(count);
+ // Strip off one EOL marker (of the appropriate length).
+ ReadString(eol_len);
+ return result;
+ } else {
+ // If there are no end of line markers in this file, just send
+ // back the whole file.
+ return ReadToEnd();
+ }
+}
+
+std::string FileTextReader::ReadToEnd() {
+ size_t remaining_size = GetRemainingSize();
+ if (remaining_size > 0) {
+ return ReadString(remaining_size);
+ } else {
+ return std::string("");
+ }
+}
+
+size_t FileTextReader::GetFileSize() const {
+ struct stat file_info;
+ ::fstat(::fileno(input_), &file_info);
+
+ return file_info.st_size;
+}
+
+size_t FileTextReader::GetRemainingSize() const {
+ // Find out where we are in the stream.
+ int original_pos = ::ftell(input_);
+
+ return GetFileSize() - original_pos;
+}
+} // end namespace o3d
diff --git a/o3d/utils/cross/file_text_reader.h b/o3d/utils/cross/file_text_reader.h
new file mode 100644
index 0000000..307679d
--- /dev/null
+++ b/o3d/utils/cross/file_text_reader.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class FileTextReader.
+
+#ifndef O3D_UTILS_CROSS_FILE_TEXT_READER_H_
+#define O3D_UTILS_CROSS_FILE_TEXT_READER_H_
+
+#include <string>
+#include "utils/cross/text_reader.h"
+
+namespace o3d {
+
+// A FileTextReader reads a sequence of characters from an
+// in-memory string.
+class FileTextReader : public TextReader {
+ public:
+ // Prepare to read from the given input string.
+ explicit FileTextReader(FILE* input);
+ virtual ~FileTextReader();
+
+ virtual bool IsAtEnd() const;
+ virtual std::string PeekString(std::string::size_type count) const;
+ virtual char ReadChar();
+ virtual std::string ReadString(std::string::size_type count);
+ virtual std::string ReadLine();
+ virtual std::string ReadToEnd();
+
+ // Access to the original input file pointer, and the current
+ // position in that buffer.
+ const FILE* input() const { return input_; }
+ size_t position() const;
+
+ protected:
+ size_t GetFileSize() const;
+ size_t GetRemainingSize() const;
+
+ private:
+ FILE* input_;
+ DISALLOW_COPY_AND_ASSIGN(FileTextReader);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_FILE_TEXT_READER_H_
diff --git a/o3d/utils/cross/file_text_reader_test.cc b/o3d/utils/cross/file_text_reader_test.cc
new file mode 100644
index 0000000..b87e61d
--- /dev/null
+++ b/o3d/utils/cross/file_text_reader_test.cc
@@ -0,0 +1,261 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of class FileTextReader.
+#include <stdio.h>
+
+#include "base/basictypes.h"
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/file_text_reader.h"
+
+namespace o3d {
+
+namespace {
+struct FileInfo {
+ const char* file_name_;
+ const char* file_contents_;
+};
+
+static const FileInfo kFileInfo[] = {
+ "/test_file_string_one", "testing 1..2..3",
+ "/test_file_string_two", "4..5..6",
+ "/test_file_string_lf", "testing 1..2..3\n4..5..6\n",
+ "/test_file_string_cr", "testing 1..2..3\r4..5..6\r",
+ "/test_file_string_crlf", "testing 1..2..3\r\n4..5..6\r\n",
+ "/test_file_string_lfcr", "testing 1..2..3\n\r4..5..6\n\r",
+ "/test_file_string_lflf", "testing 1..2..3\n\n4..5..6\n\n",
+ "/test_file_string_short", "T",
+ "/test_file_string_empty", "",
+};
+
+static const int kNumFiles = arraysize(kFileInfo);
+} // end anonymous namespace
+
+class FileTextReaderTest : public testing::Test {
+ public:
+ FileTextReaderTest() {
+ test_string_one_ = kFileInfo[0].file_contents_;
+ test_string_two_ = kFileInfo[1].file_contents_;
+ test_string_lf_ = kFileInfo[2].file_contents_;
+ test_string_cr_ = kFileInfo[3].file_contents_;
+ test_string_crlf_ = kFileInfo[4].file_contents_;
+ test_string_lfcr_ = kFileInfo[5].file_contents_;
+ test_string_lflf_ = kFileInfo[6].file_contents_;
+ test_string_short_ = kFileInfo[7].file_contents_;
+ test_string_empty_ = kFileInfo[8].file_contents_;
+ }
+ virtual void SetUp() {
+ // This clears out the existing Temporary files and rewrites them.
+ std::string tmp_base(g_program_path->data());
+ for (int i = 0; i < kNumFiles; i++) {
+ std::string filename = tmp_base + kFileInfo[i].file_name_;
+ FILE* file_pointer = fopen(filename.c_str(), "wb+");
+ int contents_size = ::strlen(kFileInfo[i].file_contents_);
+ if (contents_size > 0) {
+ ::fwrite(kFileInfo[i].file_contents_, sizeof(char), contents_size,
+ file_pointer);
+ ::fseek(file_pointer, 0, SEEK_SET);
+ }
+ file_pointers_[i] = file_pointer;
+ }
+ }
+ virtual void TearDown() {
+ std::string tmp_base(g_program_path->data());
+ // Clear out the tmp files.
+ for (int i = 0; i < kNumFiles; i++) {
+ if (file_pointers_[i]) {
+ ::fclose(file_pointers_[i]);
+ }
+ ::unlink((tmp_base + kFileInfo[i].file_name_).c_str());
+ file_pointers_[i] = NULL;
+ }
+ }
+
+ FILE* file_pointers_[kNumFiles];
+ std::string test_string_one_;
+ std::string test_string_two_;
+ std::string test_string_lf_;
+ std::string test_string_cr_;
+ std::string test_string_crlf_;
+ std::string test_string_lfcr_;
+ std::string test_string_lflf_;
+ std::string test_string_short_;
+ std::string test_string_empty_;
+};
+
+TEST_F(FileTextReaderTest, StartAtBeginning) {
+ FileTextReader reader(file_pointers_[0]);
+ EXPECT_EQ(0, reader.position());
+ EXPECT_EQ(file_pointers_[0], reader.input());
+ EXPECT_EQ(false, reader.IsAtEnd());
+}
+
+TEST_F(FileTextReaderTest, TestPeekString) {
+ FileTextReader reader(file_pointers_[0]);
+ EXPECT_EQ(test_string_one_.substr(0, 6), reader.PeekString(6));
+ EXPECT_EQ(0, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+}
+
+TEST_F(FileTextReaderTest, ReadsSingleCharacter) {
+ FileTextReader reader(file_pointers_[0]);
+ EXPECT_EQ(test_string_one_.substr(0, 1)[0], reader.ReadChar());
+ EXPECT_EQ(1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_one_.substr(1, 2), reader.PeekString(2));
+ EXPECT_EQ(1, reader.position());
+}
+
+TEST_F(FileTextReaderTest, ReadsMultipleCharacters) {
+ FileTextReader reader(file_pointers_[0]);
+ EXPECT_EQ(test_string_one_.substr(0, 1)[0], reader.ReadChar());
+ EXPECT_EQ(test_string_one_.substr(1, 1)[0], reader.ReadChar());
+ EXPECT_EQ(2, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_one_.substr(2, 2), reader.PeekString(2));
+ EXPECT_EQ(2, reader.position());
+}
+
+TEST_F(FileTextReaderTest, ReadsFile) {
+ FileTextReader reader(file_pointers_[0]);
+ EXPECT_EQ(test_string_one_.substr(0, 7), reader.ReadString(7));
+ EXPECT_EQ(7, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_one_.substr(7, 2), reader.PeekString(2));
+ EXPECT_EQ(7, reader.position());
+}
+
+TEST_F(FileTextReaderTest, EmptyFile) {
+ FileTextReader reader(file_pointers_[8]);
+ EXPECT_EQ("", reader.PeekString(1));
+ EXPECT_EQ(0, reader.position());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(0, reader.ReadChar());
+ EXPECT_EQ(true, reader.IsAtEnd());
+}
+
+TEST_F(FileTextReaderTest, TinyFile) {
+ FileTextReader reader(file_pointers_[7]);
+ EXPECT_EQ(test_string_short_.substr(0, 1), reader.PeekString(1));
+ EXPECT_EQ(0, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_short_[0], reader.ReadChar());
+ EXPECT_EQ(true, reader.IsAtEnd());
+}
+
+TEST_F(FileTextReaderTest, ReadsToEnd) {
+ FileTextReader reader(file_pointers_[2]);
+ EXPECT_EQ(test_string_lf_, reader.ReadToEnd());
+ EXPECT_EQ(test_string_lf_.size(), reader.position());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ("", reader.ReadString(1));
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lf_.size(), reader.position());
+}
+
+
+TEST_F(FileTextReaderTest, ReadsLinefeedFile) {
+ FileTextReader reader(file_pointers_[2]);
+ std::string line = reader.ReadLine();
+ EXPECT_EQ(test_string_one_, line);
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lf_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lf_.size(), reader.position());
+}
+
+TEST_F(FileTextReaderTest, ReadsCarriageReturnFile) {
+ FileTextReader reader(file_pointers_[3]);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_cr_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_cr_.size(), reader.position());
+}
+
+
+TEST_F(FileTextReaderTest, ReadsCarriageReturnLinefeedFile) {
+ FileTextReader reader(file_pointers_[4]);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 2, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_crlf_.substr(test_string_one_.size() + 2, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 2, reader.position());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_crlf_.size(), reader.position());
+}
+
+TEST_F(FileTextReaderTest, ReadsLinefeedCarriageReturnFile) {
+ FileTextReader reader(file_pointers_[5]);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lfcr_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lfcr_.size(), reader.position());
+}
+
+TEST_F(FileTextReaderTest, ReadsLinefeedLinefeedFile) {
+ FileTextReader reader(file_pointers_[6]);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lflf_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lflf_.size(), reader.position());
+}
+
+} // namespace o3d
diff --git a/o3d/utils/cross/file_text_writer.cc b/o3d/utils/cross/file_text_writer.cc
new file mode 100644
index 0000000..de329c2
--- /dev/null
+++ b/o3d/utils/cross/file_text_writer.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class FileTextWriter.
+
+#include "utils/cross/file_text_writer.h"
+#include "base/logging.h"
+
+namespace o3d {
+FileTextWriter::FileTextWriter(FILE* file,
+ Encoding encoding,
+ NewLine new_line)
+ : TextWriter(new_line),
+ file_(file),
+ encoding_(encoding) {
+ DCHECK(file_);
+}
+
+FileTextWriter::~FileTextWriter() {
+ Close();
+}
+
+void FileTextWriter::WriteChar(char c) {
+ DCHECK(file_);
+ fputc(c, file_);
+}
+
+void FileTextWriter::WriteString(const std::string& s) {
+ DCHECK(file_);
+ fwrite(s.c_str(), 1, s.length(), file_);
+}
+
+void FileTextWriter::Close() {
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ }
+}
+} // namespace o3d
diff --git a/o3d/utils/cross/file_text_writer.h b/o3d/utils/cross/file_text_writer.h
new file mode 100644
index 0000000..7776e47
--- /dev/null
+++ b/o3d/utils/cross/file_text_writer.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class FileTextWriter.
+
+#ifndef O3D_UTILS_CROSS_FILE_TEXT_WRITER_H_
+#define O3D_UTILS_CROSS_FILE_TEXT_WRITER_H_
+
+#include <stdio.h>
+
+#include <string>
+
+#include "utils/cross/text_writer.h"
+
+namespace o3d {
+
+// A FileTextWriter writes a sequence of characters to a file.
+class FileTextWriter : public TextWriter {
+ public:
+ // TODO: decide how we're going to use Unicode: wstrings of wide
+ // chars or strings encoded as UTF8? Only support ASCII for now (although it
+ // doesn't check that all chars are in the ASCII range).
+ enum Encoding {
+ ASCII,
+ };
+
+ // Take ownership of the given file. Prepare to write characters to
+ // it using the specified character encoding and new line sequence.
+ FileTextWriter(FILE* file, Encoding encoding, NewLine new_line);
+ virtual ~FileTextWriter();
+ virtual void WriteChar(char c);
+ virtual void WriteString(const std::string& s);
+ virtual void Close();
+ private:
+ FILE* file_;
+ Encoding encoding_;
+ DISALLOW_COPY_AND_ASSIGN(FileTextWriter);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_FILE_TEXT_WRITER_H_
diff --git a/o3d/utils/cross/json_writer.cc b/o3d/utils/cross/json_writer.cc
new file mode 100644
index 0000000..784d728
--- /dev/null
+++ b/o3d/utils/cross/json_writer.cc
@@ -0,0 +1,246 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class JsonWriter.
+
+#include "utils/cross/json_writer.h"
+#include "base/logging.h"
+#include "base/string_util.h"
+
+using std::string;
+
+namespace o3d {
+JsonWriter::JsonWriter(TextWriter* writer, int indent_spaces)
+ : writer_(writer),
+ indent_spaces_(indent_spaces),
+ compacting_level_(0),
+ current_indentation_(0),
+ new_line_pending_(false),
+ comma_pending_(false) {
+ DCHECK(writer_);
+}
+
+JsonWriter::~JsonWriter() {
+ Close();
+}
+
+void JsonWriter::OpenObject() {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteChar('{');
+ IncreaseIndentation();
+ ScheduleNewLine();
+}
+
+void JsonWriter::CloseObject() {
+ DCHECK(writer_);
+ CancelComma();
+ DecreaseIndentation();
+ WritePending();
+ writer_->WriteChar('}');
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::OpenArray() {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteChar('[');
+ IncreaseIndentation();
+ ScheduleNewLine();
+}
+
+void JsonWriter::CloseArray() {
+ DCHECK(writer_);
+ CancelComma();
+ DecreaseIndentation();
+ WritePending();
+ writer_->WriteChar(']');
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::BeginCompacting() {
+ WritePending();
+ ++compacting_level_;
+}
+
+void JsonWriter::EndCompacting() {
+ DCHECK_GT(compacting_level_, 0);
+ --compacting_level_;
+}
+
+void JsonWriter::WritePropertyName(const string& name) {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteChar('\"');
+ WriteEscapedString(name);
+ writer_->WriteChar('\"');
+ if (compacting_level_ > 0) {
+ writer_->WriteChar(':');
+ } else {
+ writer_->WriteString(string(": "));
+ }
+}
+
+void JsonWriter::WriteBool(bool value) {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteBool(value);
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::WriteInt(int value) {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteInt(value);
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::WriteUnsignedInt(unsigned int value) {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteUnsignedInt(value);
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::WriteFloat(float value) {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteFloat(value);
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::WriteString(const string& value) {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteChar('\"');
+ WriteEscapedString(value);
+ writer_->WriteChar('\"');
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::WriteNull() {
+ DCHECK(writer_);
+ WritePending();
+ writer_->WriteString(string("null"));
+ ScheduleComma();
+ ScheduleNewLine();
+}
+
+void JsonWriter::Close() {
+ if (writer_) {
+ CancelComma();
+ WritePending();
+ writer_->Close();
+ writer_ = NULL;
+ }
+}
+
+void JsonWriter::IncreaseIndentation() {
+ ++current_indentation_;
+}
+
+void JsonWriter::DecreaseIndentation() {
+ DCHECK_GT(current_indentation_, 0);
+ --current_indentation_;
+}
+
+void JsonWriter::ScheduleNewLine() {
+ new_line_pending_ = true;
+}
+
+void JsonWriter::ScheduleComma() {
+ comma_pending_ = true;
+}
+
+void JsonWriter::CancelComma() {
+ comma_pending_ = false;
+}
+
+void JsonWriter::WritePending() {
+ if (comma_pending_) {
+ writer_->WriteChar(',');
+ comma_pending_ = false;
+ }
+
+ if (new_line_pending_) {
+ if (compacting_level_ == 0) {
+ writer_->WriteNewLine();
+ for (int i = 0; i < current_indentation_ * indent_spaces_; ++i) {
+ writer_->WriteChar(' ');
+ }
+ }
+ new_line_pending_ = false;
+ }
+}
+
+void JsonWriter::WriteEscapedString(const string& unescaped) {
+ for (int i = 0; i < unescaped.length(); ++i) {
+ char c = unescaped[i];
+ switch (c) {
+ case '\"':
+ writer_->WriteString("\\\"");
+ break;
+ case '\\':
+ writer_->WriteString("\\\\");
+ break;
+ case '\b':
+ writer_->WriteString("\\b");
+ break;
+ case '\f':
+ writer_->WriteString("\\f");
+ break;
+ case '\n':
+ writer_->WriteString("\\n");
+ break;
+ case '\r':
+ writer_->WriteString("\\r");
+ break;
+ case '\t':
+ writer_->WriteString("\\t");
+ break;
+ default:
+ if (c < ' ') {
+ writer_->WriteString(StringPrintf("\\u%04x", static_cast<int>(c)));
+ } else {
+ writer_->WriteChar(c);
+ }
+ }
+ }
+}
+} // namespace o3d
diff --git a/o3d/utils/cross/json_writer.h b/o3d/utils/cross/json_writer.h
new file mode 100644
index 0000000..b9a623d
--- /dev/null
+++ b/o3d/utils/cross/json_writer.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class JsonWriter.
+
+#ifndef O3D_UTILS_CROSS_JSON_WRITER_H_
+#define O3D_UTILS_CROSS_JSON_WRITER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "utils/cross/text_writer.h"
+#include "utils/cross/structured_writer.h"
+
+namespace o3d {
+
+// A JsonWriter is used to write data to a TextWriter using
+// the JSON format. See http://json.org.
+class JsonWriter : public StructuredWriter {
+ public:
+ // Construct a JsonWriter that writes to the specified TextWriter.
+ // Specify the number of spaces for each indentation level.
+ JsonWriter(TextWriter* writer, int indent_spaces);
+
+ // Flushes the remaining output and closes the underlying TextWriter.
+ virtual ~JsonWriter();
+
+ // Writes the opening brace of an JSON object literal.
+ virtual void OpenObject();
+
+ // Writes the closing brace of an JSON object literal.
+ virtual void CloseObject();
+
+ // Writes the opening bracket of a JSON array literal.
+ virtual void OpenArray();
+
+ // Writes the closing bracket of a JSON array literal.
+ virtual void CloseArray();
+
+ // Disables redundant white space until compacting is closed.
+ // Can be nested.
+ virtual void BeginCompacting();
+
+ // Disables previously opened compacting.
+ virtual void EndCompacting();
+
+ // Writes the name of a property surrounded by quotes. Follow
+ // with a call to one of the functions that writes a value.
+ virtual void WritePropertyName(const std::string& name);
+
+ // Writes a boolean literal.
+ virtual void WriteBool(bool value);
+
+ // Writes a number literal.
+ virtual void WriteInt(int value);
+
+ // Writes a number literal.
+ virtual void WriteUnsignedInt(unsigned int value);
+
+ // Writes a number literal.
+ virtual void WriteFloat(float value);
+
+ // Writes a string literal with JSON escape sequences for
+ // special characters.
+ virtual void WriteString(const std::string& value);
+
+ // Writes a null literal.
+ virtual void WriteNull();
+
+ // Flushes the remaining output and closes the underlying TextWriter.
+ virtual void Close();
+
+ private:
+ void IncreaseIndentation();
+ void DecreaseIndentation();
+ void ScheduleNewLine();
+ void ScheduleComma();
+ void CancelComma();
+ void WritePending();
+ void WriteEscapedString(const std::string& unescaped);
+
+ TextWriter* writer_;
+ int indent_spaces_;
+ int compacting_level_;
+ int current_indentation_;
+ bool new_line_pending_;
+ bool comma_pending_;
+ DISALLOW_COPY_AND_ASSIGN(JsonWriter);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_JSON_WRITER_H_
diff --git a/o3d/utils/cross/json_writer_test.cc b/o3d/utils/cross/json_writer_test.cc
new file mode 100644
index 0000000..ad00d8b
--- /dev/null
+++ b/o3d/utils/cross/json_writer_test.cc
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of class JsonWriter.
+
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/json_writer.h"
+#include "utils/cross/string_writer.h"
+
+namespace o3d {
+
+class JsonWriterTest : public testing::Test {
+ public:
+ JsonWriterTest()
+ : output_(StringWriter::CR_LF),
+ json_writer_(&output_, 2) {
+ }
+ protected:
+ StringWriter output_;
+ JsonWriter json_writer_;
+};
+
+TEST_F(JsonWriterTest, WritesEmptyObject) {
+ json_writer_.OpenObject();
+ json_writer_.CloseObject();
+ json_writer_.Close();
+ ASSERT_EQ(String("{\r\n}\r\n"), output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesNestedObjects) {
+ json_writer_.OpenObject();
+ json_writer_.OpenObject();
+ json_writer_.CloseObject();
+ json_writer_.OpenObject();
+ json_writer_.CloseObject();
+ json_writer_.CloseObject();
+ json_writer_.Close();
+ ASSERT_EQ(String("{\r\n {\r\n },\r\n {\r\n }\r\n}\r\n"),
+ output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesObjectProperty) {
+ json_writer_.OpenObject();
+ json_writer_.WritePropertyName(String("myProperty"));
+ json_writer_.WriteFloat(1.25f);
+ json_writer_.CloseObject();
+ json_writer_.Close();
+ ASSERT_EQ(String("{\r\n \"myProperty\": 1.25\r\n}\r\n"),
+ output_.ToString());
+}
+
+TEST_F(JsonWriterTest, EscapesSpecialCharsInObjectPropertyName) {
+ json_writer_.OpenObject();
+ json_writer_.WritePropertyName(String("\"\\\b\f\n\r\t\x01"));
+ json_writer_.WriteFloat(1.25f);
+ json_writer_.CloseObject();
+ json_writer_.Close();
+ ASSERT_EQ(
+ String("{\r\n \"\\\"\\\\\\b\\f\\n\\r\\t\\u0001\": 1.25\r\n}\r\n"),
+ output_.ToString());
+}
+TEST_F(JsonWriterTest, WritesCommaSeparatedObjectProperties) {
+ json_writer_.OpenObject();
+ json_writer_.WritePropertyName(String("myProperty1"));
+ json_writer_.WriteFloat(1.25f);
+ json_writer_.WritePropertyName(String("myProperty2"));
+ json_writer_.WriteFloat(2.5f);
+ json_writer_.CloseObject();
+ json_writer_.Close();
+ ASSERT_EQ(
+ String(
+ "{\r\n \"myProperty1\": 1.25,\r\n \"myProperty2\": 2.5\r\n}\r\n"),
+ output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesEmptyArray) {
+ json_writer_.OpenArray();
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n]\r\n"), output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesNestedArrays) {
+ json_writer_.OpenArray();
+ json_writer_.OpenArray();
+ json_writer_.CloseArray();
+ json_writer_.OpenArray();
+ json_writer_.CloseArray();
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n [\r\n ],\r\n [\r\n ]\r\n]\r\n"),
+ output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesArrayOfBools) {
+ json_writer_.OpenArray();
+ json_writer_.WriteBool(false);
+ json_writer_.WriteBool(true);
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n false,\r\n true\r\n]\r\n"),
+ output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesArrayOfInts) {
+ json_writer_.OpenArray();
+ json_writer_.WriteInt(1);
+ json_writer_.WriteInt(2);
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n 1,\r\n 2\r\n]\r\n"), output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesArrayOfUnsignedInts) {
+ json_writer_.OpenArray();
+ json_writer_.WriteUnsignedInt(1u);
+ json_writer_.WriteUnsignedInt(2u);
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n 1,\r\n 2\r\n]\r\n"), output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesArrayOfFloats) {
+ json_writer_.OpenArray();
+ json_writer_.WriteFloat(1);
+ json_writer_.WriteFloat(2);
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n 1,\r\n 2\r\n]\r\n"), output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesArrayOfStrings) {
+ json_writer_.OpenArray();
+ json_writer_.WriteString(String("abc"));
+ json_writer_.WriteString(String("def"));
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n \"abc\",\r\n \"def\"\r\n]\r\n"),
+ output_.ToString());
+}
+
+TEST_F(JsonWriterTest, EscapesSpecialCharsInString) {
+ json_writer_.WriteString(String("\"\\\b\f\n\r\t\x01"));
+ json_writer_.Close();
+ ASSERT_EQ(String("\"\\\"\\\\\\b\\f\\n\\r\\t\\u0001\"\r\n"),
+ output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesArrayOfNulls) {
+ json_writer_.OpenArray();
+ json_writer_.WriteNull();
+ json_writer_.WriteNull();
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n null,\r\n null\r\n]\r\n"), output_.ToString());
+}
+
+TEST_F(JsonWriterTest, WritesWithoutWhiteSpaceIfCompacted) {
+ json_writer_.BeginCompacting();
+ json_writer_.OpenObject();
+ json_writer_.WritePropertyName(String("foo"));
+ json_writer_.WriteNull();
+ json_writer_.WritePropertyName(String("bar"));
+ json_writer_.WriteNull();
+ json_writer_.CloseObject();
+ json_writer_.EndCompacting();
+ json_writer_.Close();
+ ASSERT_EQ(String("{\"foo\":null,\"bar\":null}\r\n"), output_.ToString());
+}
+
+TEST_F(JsonWriterTest, ShouldWritePendingWhiteSpaceBeforeCompactedElements) {
+ json_writer_.OpenArray();
+ json_writer_.BeginCompacting();
+ json_writer_.OpenObject();
+ json_writer_.WritePropertyName(String("foo"));
+ json_writer_.WriteNull();
+ json_writer_.CloseObject();
+ json_writer_.EndCompacting();
+ json_writer_.CloseArray();
+ json_writer_.Close();
+ ASSERT_EQ(String("[\r\n {\"foo\":null}\r\n]\r\n"), output_.ToString());
+}
+} // namespace o3d
diff --git a/o3d/utils/cross/string_reader.cc b/o3d/utils/cross/string_reader.cc
new file mode 100644
index 0000000..c62669d
--- /dev/null
+++ b/o3d/utils/cross/string_reader.cc
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class StringReader. The
+// tests are in string_reader_test.cc.
+
+#include <stdio.h>
+#include "utils/cross/string_reader.h"
+
+namespace o3d {
+
+StringReader::StringReader(const std::string& input)
+ : TextReader(), input_(input), position_(0) {
+}
+
+StringReader::~StringReader() {
+}
+
+bool StringReader::IsAtEnd() const {
+ return position_ == input_.size();
+}
+
+std::string StringReader::PeekString(
+ std::string::size_type count) const {
+ count = std::min(input_.size() - position_, count);
+ if (count > 0) {
+ return input_.substr(position_, count);
+ } else {
+ return "";
+ }
+}
+
+char StringReader::ReadChar() {
+ if (position_ <= input_.size() && input_.size() > 0) {
+ position_++;
+ return input_[position_ - 1];
+ } else {
+ return 0;
+ }
+}
+
+std::string StringReader::ReadString(std::string::size_type count) {
+ count = std::min(input_.size() - position_, count);
+ std::string result;
+ if (count > 0) {
+ result = input_.substr(position_, count);
+ position_ += count;
+ }
+ return result;
+}
+
+std::string StringReader::ReadLine() {
+ std::string::size_type possible_eol = input_.find_first_of("\r\n", position_);
+ if (possible_eol == std::string::npos) {
+ // There wasn't an end of line marker anywhere, so just return the
+ // whole string.
+ return ReadToEnd();
+ } else {
+ if ((input_.size() - position_) > 1) {
+ // See which end of line marker we have and strip it.
+ int eol_len = TestForEndOfLine(input_.substr(possible_eol, 2));
+ std::string result = input_.substr(position_, possible_eol - position_);
+ position_ = possible_eol + eol_len;
+ return result;
+ } else {
+ // If it's only one long, and it found a carriage return or a
+ // linefeed, then we just eat that character and return an
+ // empty string.
+ position_++;
+ return std::string("");
+ }
+ }
+ return std::string("");
+}
+
+std::string StringReader::ReadToEnd() {
+ std::string result = input_.substr(position_);
+ position_ = input_.size();
+ return result;
+}
+} // end namespace o3d
diff --git a/o3d/utils/cross/string_reader.h b/o3d/utils/cross/string_reader.h
new file mode 100644
index 0000000..aea6ea6
--- /dev/null
+++ b/o3d/utils/cross/string_reader.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class StringReader.
+
+#ifndef O3D_UTILS_CROSS_STRING_READER_H_
+#define O3D_UTILS_CROSS_STRING_READER_H_
+
+#include <string>
+
+#include "utils/cross/text_reader.h"
+
+namespace o3d {
+
+// A StringReader reads a sequence of characters from an
+// in-memory string.
+class StringReader : public TextReader {
+ public:
+ // Prepare to read from the given input string.
+ explicit StringReader(const std::string& input);
+ virtual ~StringReader();
+
+ virtual bool IsAtEnd() const;
+ virtual std::string PeekString(std::string::size_type count) const;
+ virtual char ReadChar();
+ virtual std::string ReadString(std::string::size_type count);
+ virtual std::string ReadLine();
+ virtual std::string ReadToEnd();
+
+ // Access to the original input buffer, and the current position in
+ // that buffer.
+ const std::string& input() const { return input_; }
+ std::string::size_type position() const { return position_; }
+
+ private:
+ std::string input_;
+ std::string::size_type position_;
+ DISALLOW_COPY_AND_ASSIGN(StringReader);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_STRING_READER_H_
diff --git a/o3d/utils/cross/string_reader_test.cc b/o3d/utils/cross/string_reader_test.cc
new file mode 100644
index 0000000..f2755be
--- /dev/null
+++ b/o3d/utils/cross/string_reader_test.cc
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of class StringReader.
+#include <stdio.h>
+
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/string_reader.h"
+
+namespace o3d {
+
+namespace {
+static const char* kTestStrings[] = {
+ "testing 1..2..3",
+ "4..5..6",
+ "testing 1..2..3\n4..5..6\n",
+ "testing 1..2..3\r4..5..6\r",
+ "testing 1..2..3\r\n4..5..6\r\n",
+ "testing 1..2..3\n\r4..5..6\n\r",
+ "testing 1..2..3\n\n4..5..6\n\n",
+};
+} // end anonymous namespace
+
+class StringReaderTest : public testing::Test {
+ public:
+ StringReaderTest() {
+ test_string_one_ = kTestStrings[0];
+ test_string_two_ = kTestStrings[1];
+ test_string_lf_ = kTestStrings[2];
+ test_string_cr_ = kTestStrings[3];
+ test_string_crlf_ = kTestStrings[4];
+ test_string_lfcr_ = kTestStrings[5];
+ test_string_lflf_ = kTestStrings[6];
+ }
+
+ std::string test_string_one_;
+ std::string test_string_two_;
+ std::string test_string_lf_;
+ std::string test_string_cr_;
+ std::string test_string_crlf_;
+ std::string test_string_lfcr_;
+ std::string test_string_lflf_;
+};
+
+TEST_F(StringReaderTest, StartAtBeginning) {
+ StringReader reader(test_string_one_);
+ EXPECT_EQ(0, reader.position());
+ EXPECT_EQ(test_string_one_, reader.input());
+}
+
+TEST_F(StringReaderTest, TestPeekString) {
+ StringReader reader(test_string_one_);
+ EXPECT_EQ(test_string_one_.substr(0, 6), reader.PeekString(6));
+ EXPECT_EQ(0, reader.position());
+ EXPECT_EQ(test_string_one_, reader.input());
+}
+
+TEST_F(StringReaderTest, ReadsSingleCharacter) {
+ StringReader reader(test_string_one_);
+ EXPECT_EQ(test_string_one_.substr(0, 1)[0], reader.ReadChar());
+ EXPECT_EQ(1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_one_.substr(1, 2), reader.PeekString(2));
+ EXPECT_EQ(1, reader.position());
+}
+
+TEST_F(StringReaderTest, ReadsMultipleCharacters) {
+ StringReader reader(test_string_one_);
+ EXPECT_EQ(test_string_one_.substr(0, 1)[0], reader.ReadChar());
+ EXPECT_EQ(test_string_one_.substr(1, 1)[0], reader.ReadChar());
+ EXPECT_EQ(2, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_one_.substr(2, 2), reader.PeekString(2));
+ EXPECT_EQ(2, reader.position());
+}
+
+TEST_F(StringReaderTest, ReadsString) {
+ StringReader reader(test_string_one_);
+ EXPECT_EQ(test_string_one_.substr(0, 7), reader.ReadString(7));
+ EXPECT_EQ(7, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_one_.substr(7, 2), reader.PeekString(2));
+ EXPECT_EQ(7, reader.position());
+}
+
+TEST_F(StringReaderTest, ReadsToEnd) {
+ StringReader reader(test_string_lf_);
+ EXPECT_EQ(test_string_lf_, reader.ReadToEnd());
+ EXPECT_EQ(test_string_lf_.size(), reader.position());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ("", reader.ReadString(1));
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lf_.size(), reader.position());
+}
+
+
+TEST_F(StringReaderTest, ReadsLinefeedString) {
+ StringReader reader(test_string_lf_);
+ std::string line = reader.ReadLine();
+ EXPECT_EQ(test_string_one_, line);
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lf_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lf_.size(), reader.position());
+}
+
+TEST_F(StringReaderTest, ReadsCarriageReturnString) {
+ StringReader reader(test_string_cr_);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_cr_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_cr_.size(), reader.position());
+}
+
+
+TEST_F(StringReaderTest, ReadsCarriageReturnLinefeedString) {
+ StringReader reader(test_string_crlf_);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 2, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_crlf_.substr(test_string_one_.size() + 2, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 2, reader.position());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_crlf_.size(), reader.position());
+}
+
+TEST_F(StringReaderTest, ReadsLinefeedCarriageReturnString) {
+ StringReader reader(test_string_lfcr_);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lfcr_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lfcr_.size(), reader.position());
+}
+
+TEST_F(StringReaderTest, ReadsLinefeedLinefeedString) {
+ StringReader reader(test_string_lflf_);
+ EXPECT_EQ(test_string_one_, reader.ReadLine());
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lflf_.substr(test_string_one_.size() + 1, 2),
+ reader.PeekString(2));
+ EXPECT_EQ(test_string_one_.size() + 1, reader.position());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ(test_string_two_, reader.ReadLine());
+ EXPECT_EQ(false, reader.IsAtEnd());
+ EXPECT_EQ("", reader.ReadLine());
+ EXPECT_EQ(true, reader.IsAtEnd());
+ EXPECT_EQ(test_string_lflf_.size(), reader.position());
+}
+} // namespace o3d
diff --git a/o3d/utils/cross/string_writer.cc b/o3d/utils/cross/string_writer.cc
new file mode 100644
index 0000000..ccedeeb
--- /dev/null
+++ b/o3d/utils/cross/string_writer.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class StringWriter.
+
+#include "utils/cross/string_writer.h"
+
+namespace o3d {
+
+StringWriter::StringWriter(NewLine new_line)
+ : TextWriter(new_line) {
+}
+
+void StringWriter::WriteChar(char c) {
+ string_ += c;
+}
+
+void StringWriter::WriteString(const std::string& s) {
+ string_ += s;
+}
+
+std::string StringWriter::ToString() const {
+ return string_;
+}
+
+} // namespace o3d
diff --git a/o3d/utils/cross/string_writer.h b/o3d/utils/cross/string_writer.h
new file mode 100644
index 0000000..823f15f
--- /dev/null
+++ b/o3d/utils/cross/string_writer.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class StringWriter.
+
+#ifndef O3D_UTILS_CROSS_STRING_WRITER_H_
+#define O3D_UTILS_CROSS_STRING_WRITER_H_
+
+#include <string>
+
+#include "utils/cross/text_writer.h"
+
+namespace o3d {
+
+// A StringWriter writes a sequence of characters to an
+// in-memory string.
+class StringWriter : public TextWriter {
+ public:
+ // Prepare to produce a string using the given new line
+ // sequence.
+ explicit StringWriter(NewLine new_line);
+ virtual void WriteChar(char c);
+ virtual void WriteString(const std::string& s);
+
+ // Retrieve the string that has been produced so far.
+ std::string ToString() const;
+ private:
+ std::string string_;
+ DISALLOW_COPY_AND_ASSIGN(StringWriter);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_STRING_WRITER_H_
diff --git a/o3d/utils/cross/string_writer_test.cc b/o3d/utils/cross/string_writer_test.cc
new file mode 100644
index 0000000..488bad0
--- /dev/null
+++ b/o3d/utils/cross/string_writer_test.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of class StringWriter.
+
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/string_writer.h"
+
+namespace o3d {
+
+class StringWriterTest : public testing::Test {
+};
+
+TEST_F(StringWriterTest, EmptyByDefault) {
+ StringWriter writer(StringWriter::CR);
+ EXPECT_EQ(String(), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesSingleCharacter) {
+ StringWriter writer(StringWriter::CR);
+ writer.WriteChar('y');
+ EXPECT_EQ(String("y"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesMultipleCharacters) {
+ StringWriter writer(StringWriter::CR);
+ writer.WriteChar('y');
+ writer.WriteChar('z');
+ EXPECT_EQ(String("yz"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesString) {
+ StringWriter writer(StringWriter::CR);
+ writer.WriteString(String("hello"));
+ EXPECT_EQ(String("hello"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesCarriageReturnNewLine) {
+ StringWriter writer(StringWriter::CR);
+ writer.WriteNewLine();
+ EXPECT_EQ(String("\r"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesCarriageReturnLineFeedNewLine) {
+ StringWriter writer(StringWriter::CR_LF);
+ writer.WriteNewLine();
+ EXPECT_EQ(String("\r\n"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesLineFeedNewLine) {
+ StringWriter writer(StringWriter::LF);
+ writer.WriteNewLine();
+ EXPECT_EQ(String("\n"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesFalse) {
+ StringWriter writer(StringWriter::LF);
+ writer.WriteBool(false);
+ EXPECT_EQ(String("false"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesTrue) {
+ StringWriter writer(StringWriter::LF);
+ writer.WriteBool(true);
+ EXPECT_EQ(String("true"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesInt) {
+ StringWriter writer(StringWriter::LF);
+ writer.WriteInt(-123);
+ EXPECT_EQ(String("-123"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesUnsignedInt) {
+ StringWriter writer(StringWriter::LF);
+ writer.WriteInt(123u);
+ ASSERT_EQ(String("123"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesFloat) {
+ StringWriter writer(StringWriter::LF);
+ writer.WriteFloat(1.25f);
+ EXPECT_EQ(String("1.25"), writer.ToString());
+}
+
+TEST_F(StringWriterTest, WritesPrintfFormatted) {
+ StringWriter writer(StringWriter::LF);
+ writer.WriteFormatted("%s: %d", "age", 31);
+ EXPECT_EQ(String("age: 31"), writer.ToString());
+}
+} // namespace o3d
diff --git a/o3d/utils/cross/structured_writer.h b/o3d/utils/cross/structured_writer.h
new file mode 100644
index 0000000..e25f615
--- /dev/null
+++ b/o3d/utils/cross/structured_writer.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class StructuredWriter.
+
+#ifndef O3D_UTILS_CROSS_STRUCTURED_WRITER_H_
+#define O3D_UTILS_CROSS_STRUCTURED_WRITER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace o3d {
+
+// Interface of classes that can write structured data consisting of
+// a hierarchy of objects (with named properties) and arrays of typed
+// values.
+class StructuredWriter {
+ public:
+ StructuredWriter() {}
+ virtual ~StructuredWriter() {}
+
+ // Opens an object block. An object block contains property / value
+ // pairs.
+ virtual void OpenObject() = 0;
+
+ // Closes an object block.
+ virtual void CloseObject() = 0;
+
+ // Opens an array block. An array block contains zero or more values.
+ virtual void OpenArray() = 0;
+
+ // Closes an array block.
+ virtual void CloseArray() = 0;
+
+ // Hints to the writer that it should not add additional formatting
+ // to make the output more readable. These can be nested.
+ virtual void BeginCompacting() = 0;
+
+ // Ends the hint that additional formatting is not necessary.
+ virtual void EndCompacting() = 0;
+
+ // Writes the name of a property. This should be immediately by a
+ // value.
+ virtual void WritePropertyName(const std::string& name) = 0;
+
+ // Writes a boolean value.
+ virtual void WriteBool(bool value) = 0;
+
+ // Writes an integer value.
+ virtual void WriteInt(int value) = 0;
+
+ // Writes an unsigned integer value.
+ virtual void WriteUnsignedInt(unsigned int value) = 0;
+
+ // Writes a float value.
+ virtual void WriteFloat(float value) = 0;
+
+ // Writes a string value.
+ virtual void WriteString(const std::string& value) = 0;
+
+ // Writes a null value.
+ virtual void WriteNull() = 0;
+
+ // Flushes any unwritten content and closes the writer. No further
+ // writes are allowed.
+ virtual void Close() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(StructuredWriter);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_STRUCTURED_WRITER_H_
diff --git a/o3d/utils/cross/temporary_file.cc b/o3d/utils/cross/temporary_file.cc
new file mode 100644
index 0000000..afb4b61
--- /dev/null
+++ b/o3d/utils/cross/temporary_file.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class TemporaryFile.
+
+#include "utils/cross/temporary_file.h"
+
+#include "base/file_path.h"
+#include "base/file_util.h"
+
+namespace o3d {
+
+namespace {
+void DeletePath(const FilePath& path) {
+ if (!path.empty()) {
+ file_util::Delete(path, false);
+ }
+}
+} // end anonymous namespace
+
+TemporaryFile::TemporaryFile() {
+ // file_path_ is initialized to be empty.
+}
+
+TemporaryFile::TemporaryFile(const FilePath& file_to_manage)
+ : file_path_(file_to_manage) {
+}
+
+bool TemporaryFile::Create(TemporaryFile* temporary_file) {
+ FilePath temporary_path;
+ if (file_util::CreateTemporaryFileName(&temporary_path)) {
+ temporary_file->Reset(temporary_path);
+ } else {
+ return false;
+ }
+ return true;
+}
+
+TemporaryFile::~TemporaryFile() {
+ DeletePath(file_path_);
+}
+
+FilePath TemporaryFile::Release() {
+ FilePath old_path = file_path_;
+ file_path_ = FilePath();
+ return old_path;
+}
+
+void TemporaryFile::Reset(const FilePath& file_path) {
+ DeletePath(file_path_);
+ file_path_ = file_path;
+}
+
+} // end namespace o3d
diff --git a/o3d/utils/cross/temporary_file.h b/o3d/utils/cross/temporary_file.h
new file mode 100644
index 0000000..f3cf383
--- /dev/null
+++ b/o3d/utils/cross/temporary_file.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file declares a simple manager class that manages a temporary
+// file.
+
+#ifndef O3D_UTILS_CROSS_TEMPORARY_FILE_H_
+#define O3D_UTILS_CROSS_TEMPORARY_FILE_H_
+
+#include "base/file_path.h"
+
+namespace o3d {
+
+// TemporaryFile is a simple manager class that manages a temporary
+// file. It accepts the path to the temporary file when it is
+// created, and deletes the temporary file when it goes out of scope.
+// It is up to the creator to verify that the program has the rights
+// to delete the file given to it.
+class TemporaryFile {
+ public:
+ // Creates an empty TemporaryFile object. Must call "reset" to have
+ // it manage a file.
+ TemporaryFile();
+
+ // Manages the given file path as a temporary file.
+ explicit TemporaryFile(const FilePath& file_to_manage);
+ ~TemporaryFile();
+
+ // Returns the currently managed path.
+ const FilePath& path() const {
+ return file_path_;
+ }
+
+ // Releases the managed path so that it will NOT be deleted when
+ // this object goes out of scope. The path that was being managed
+ // is returned.
+ FilePath Release();
+
+ // Resets the path being managed to the supplied path. If this
+ // object was managing a file before, then that file will be
+ // immediately deleted.
+ void Reset(const FilePath& file_path);
+
+ // Creates an empty temporary file in the system's default temporary
+ // directory and resets the given TemporaryFile object to manage
+ // that file. Returns true if it was successful in creating the
+ // file.
+ static bool Create(TemporaryFile* temp_file);
+
+ private:
+ FilePath file_path_;
+
+ DISALLOW_COPY_AND_ASSIGN(TemporaryFile);
+};
+
+} // end namespace o3d
+#endif // O3D_UTILS_CROSS_TEMPORARY_FILE_H_
diff --git a/o3d/utils/cross/temporary_file_test.cc b/o3d/utils/cross/temporary_file_test.cc
new file mode 100644
index 0000000..bdbe492
--- /dev/null
+++ b/o3d/utils/cross/temporary_file_test.cc
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the tests of class TemporaryFile.
+
+#include <stdio.h>
+
+#include "base/file_util.h"
+#include "tests/common/win/testing_common.h"
+#include "utils/cross/temporary_file.h"
+
+namespace o3d {
+
+class TemporaryFileTest : public testing::Test {
+};
+
+TEST_F(TemporaryFileTest, BasicConstruction) {
+ TemporaryFile temporary_file;
+ EXPECT_TRUE(temporary_file.path().empty());
+}
+
+TEST_F(TemporaryFileTest, BasicFunction) {
+ FilePath path;
+ file_util::CreateTemporaryFileName(&path);
+ EXPECT_TRUE(file_util::PathExists(path));
+ {
+ TemporaryFile temporary_file(path);
+ EXPECT_TRUE(file_util::PathExists(path));
+ EXPECT_EQ(path.value(), temporary_file.path().value());
+ EXPECT_TRUE(file_util::PathExists(temporary_file.path()));
+ }
+ EXPECT_FALSE(file_util::PathExists(path));
+}
+
+TEST_F(TemporaryFileTest, Reset) {
+ FilePath path;
+ FilePath path1;
+ file_util::CreateTemporaryFileName(&path);
+ file_util::CreateTemporaryFileName(&path1);
+ EXPECT_TRUE(file_util::PathExists(path));
+ EXPECT_TRUE(file_util::PathExists(path1));
+ {
+ TemporaryFile temporary_file(path1);
+ EXPECT_EQ(path1.value(), temporary_file.path().value());
+ EXPECT_TRUE(file_util::PathExists(path1));
+ EXPECT_TRUE(file_util::PathExists(temporary_file.path()));
+ temporary_file.Reset(path);
+ EXPECT_TRUE(file_util::PathExists(path));
+ EXPECT_EQ(path.value(), temporary_file.path().value());
+ EXPECT_FALSE(file_util::PathExists(path1));
+ EXPECT_TRUE(file_util::PathExists(path));
+ EXPECT_TRUE(file_util::PathExists(temporary_file.path()));
+ }
+ EXPECT_FALSE(file_util::PathExists(path));
+ EXPECT_FALSE(file_util::PathExists(path1));
+}
+
+TEST_F(TemporaryFileTest, Release) {
+ FilePath path;
+ file_util::CreateTemporaryFileName(&path);
+ EXPECT_TRUE(file_util::PathExists(path));
+ {
+ TemporaryFile temporary_file(path);
+ EXPECT_TRUE(file_util::PathExists(path));
+ EXPECT_TRUE(file_util::PathExists(temporary_file.path()));
+ temporary_file.Release();
+ }
+ EXPECT_TRUE(file_util::PathExists(path));
+}
+
+TEST_F(TemporaryFileTest, Create) {
+ FilePath test_path;
+ {
+ TemporaryFile temporary_file;
+ TemporaryFile::Create(&temporary_file);
+ EXPECT_FALSE(temporary_file.path().empty());
+ EXPECT_TRUE(file_util::PathExists(temporary_file.path()));
+ EXPECT_TRUE(file_util::PathIsWritable(temporary_file.path()));
+ test_path = temporary_file.path();
+ }
+ EXPECT_FALSE(file_util::PathExists(test_path));
+}
+
+} // namespace o3d
diff --git a/o3d/utils/cross/text_reader.cc b/o3d/utils/cross/text_reader.cc
new file mode 100644
index 0000000..dccbffa
--- /dev/null
+++ b/o3d/utils/cross/text_reader.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class TextReader. The
+// tests are in string_reader_test.cc.
+
+#include "utils/cross/text_reader.h"
+
+namespace o3d {
+namespace {
+static const char kLinefeed = '\n';
+static const char kCarriageReturn = '\r';
+}
+
+TextReader::TextReader() {
+}
+
+TextReader::~TextReader() {
+}
+
+int TextReader::TestForEndOfLine(const std::string& eol) {
+ if (eol.size() == 0) {
+ return 0;
+ }
+ if (eol[0] == kLinefeed) {
+ return 1;
+ }
+ if (eol[0] == kCarriageReturn) {
+ if (eol.size() > 1 && eol[1] == kLinefeed) {
+ return 2;
+ } else {
+ return 1;
+ }
+ }
+ return 0;
+}
+} // end namespace o3d
diff --git a/o3d/utils/cross/text_reader.h b/o3d/utils/cross/text_reader.h
new file mode 100644
index 0000000..470b666
--- /dev/null
+++ b/o3d/utils/cross/text_reader.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class TextReader.
+
+#ifndef O3D_UTILS_CROSS_TEXT_READER_H_
+#define O3D_UTILS_CROSS_TEXT_READER_H_
+
+#include <string>
+#include "base/basictypes.h"
+
+namespace o3d {
+
+// TextReader is the abstract base class of classes
+// that read a sequence of characters to an underlying
+// medium.
+class TextReader {
+ public:
+ // Construct a new TextReader.
+ TextReader();
+ virtual ~TextReader();
+
+ // Returns true if at the end of the input.
+ virtual bool IsAtEnd() const = 0;
+
+ // Read ahead up to count characters and return them as a string,
+ // but don't modify the input's current position. Returns the empty
+ // string if at the end of the input.
+ virtual std::string PeekString(std::string::size_type count) const = 0;
+
+ // Read a single character.
+ virtual char ReadChar() = 0;
+
+ // Read a number of characters as a string. If the input isn't that
+ // long, the string may be shorter than the given number of
+ // characters. Returns an empty string if it is already at the end
+ // of the input or if there is an error.
+ virtual std::string ReadString(std::string::size_type count) = 0;
+
+ // Read a line of text, terminated by any kind of line terminator
+ // (LF/CRLF/CR). Returns the empty string if at end of input, or if
+ // there is an error.
+ virtual std::string ReadLine() = 0;
+
+ // Read the remaining file into a string, linefeeds and all.
+ // Returns the empty string if already at the end of the file or
+ // there is an error.
+ virtual std::string ReadToEnd() = 0;
+
+ protected:
+ // Returns length of EOL marker (one or two characters) if the given
+ // character string starts with an end of line marker. Returns zero
+ // if there is no EOL marker at the BEGINNING of the string.
+ static int TestForEndOfLine(const std::string& eol);
+
+ private:
+
+ DISALLOW_COPY_AND_ASSIGN(TextReader);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_TEXT_READER_H_
diff --git a/o3d/utils/cross/text_writer.cc b/o3d/utils/cross/text_writer.cc
new file mode 100644
index 0000000..01dca8d
--- /dev/null
+++ b/o3d/utils/cross/text_writer.cc
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the definition of class TextWriter. The
+// tests are in string_writer_test.cc.
+
+#include <stdarg.h>
+
+#include "utils/cross/text_writer.h"
+#include "base/string_util.h"
+
+using std::string;
+
+namespace o3d {
+TextWriter::TextWriter(NewLine new_line)
+ : new_line_(new_line) {
+}
+
+TextWriter::~TextWriter() {
+}
+
+void TextWriter::WriteString(const string& s) {
+ for (size_t i = 0; i != s.length(); ++i) {
+ WriteChar(s[i]);
+ }
+}
+
+void TextWriter::WriteBool(bool value) {
+ if (value) {
+ WriteString(string("true"));
+ } else {
+ WriteString(string("false"));
+ }
+}
+
+void TextWriter::WriteInt(int value) {
+ WriteString(StringPrintf("%d", value));
+}
+
+void TextWriter::WriteUnsignedInt(unsigned int value) {
+ WriteString(StringPrintf("%u", value));
+}
+
+void TextWriter::WriteFloat(float value) {
+ WriteString(StringPrintf("%g", value));
+}
+
+void TextWriter::WriteFormatted(const char* format, ...) {
+ va_list args;
+ va_start(args, format);
+ string formatted;
+ StringAppendV(&formatted, format, args);
+ va_end(args);
+
+ WriteString(formatted);
+}
+
+void TextWriter::WriteNewLine() {
+ switch (new_line_) {
+ case CR:
+ WriteChar('\r');
+ break;
+ case CR_LF:
+ WriteChar('\r');
+ WriteChar('\n');
+ break;
+ case LF:
+ WriteChar('\n');
+ break;
+ }
+}
+
+void TextWriter::Close() {
+}
+} // namespace o3d
diff --git a/o3d/utils/cross/text_writer.h b/o3d/utils/cross/text_writer.h
new file mode 100644
index 0000000..59fab88
--- /dev/null
+++ b/o3d/utils/cross/text_writer.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2009, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+// This file contains the declaration of class TextWriter.
+
+#ifndef O3D_UTILS_CROSS_TEXT_WRITER_H_
+#define O3D_UTILS_CROSS_TEXT_WRITER_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+
+namespace o3d {
+
+// TextWriter is the abstract base class of classes
+// that write a sequence of characters to an underlying
+// medium.
+class TextWriter {
+ public:
+ enum NewLine {
+ LF,
+ CR_LF,
+ CR,
+ };
+
+ // Construct a new TextWriter using the given newline
+ // sequence.
+ explicit TextWriter(NewLine new_line);
+ virtual ~TextWriter();
+
+ // Write a single character.
+ virtual void WriteChar(char c) = 0;
+
+ // Write a string of characters.
+ virtual void WriteString(const std::string& s);
+
+ // Write "true" or "false".
+ void WriteBool(bool value);
+
+ // Write a signed integer.
+ void WriteInt(int value);
+
+ // Write an unsigned integer.
+ void WriteUnsignedInt(unsigned int value);
+
+ // Write a floating point number.
+ void WriteFloat(float value);
+
+ // Write a printf formatted string.
+ void WriteFormatted(const char* format, ...);
+
+ // Write a newline.
+ void WriteNewLine();
+
+ // Close the writer.
+ virtual void Close();
+
+ NewLine new_line() const { return new_line_; }
+
+ private:
+ NewLine new_line_;
+ DISALLOW_COPY_AND_ASSIGN(TextWriter);
+};
+} // namespace o3d
+
+#endif // O3D_UTILS_CROSS_TEXT_WRITER_H_