PM: Add BoxedValue::ToString() method.

This will be used to dump variables in the EvaluationContext.

BUG=chromium:355724
TEST=New unit test + Unit tests pass.

Change-Id: I82a3fb5d2636fd124dfbf63bf130fcd3c5726bcd
Reviewed-on: https://chromium-review.googlesource.com/197524
Reviewed-by: Alex Deymo <deymo@chromium.org>
Commit-Queue: David Zeuthen <zeuthen@chromium.org>
Tested-by: David Zeuthen <zeuthen@chromium.org>
diff --git a/policy_manager/boxed_value.cc b/policy_manager/boxed_value.cc
new file mode 100644
index 0000000..0cf7ed2
--- /dev/null
+++ b/policy_manager/boxed_value.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <set>
+#include <string>
+
+#include <base/strings/string_number_conversions.h>
+#include <base/time/time.h>
+
+#include "update_engine/policy_manager/boxed_value.h"
+#include "update_engine/policy_manager/shill_provider.h"
+#include "update_engine/policy_manager/updater_provider.h"
+#include "update_engine/utils.h"
+
+using std::set;
+using std::string;
+
+namespace chromeos_policy_manager {
+
+// Template instantiation for common types; used in BoxedValue::ToString().
+// Keep in sync with boxed_value_unitttest.cc.
+
+template<>
+string BoxedValue::ValuePrinter<string>(const void *value) {
+  const string* val = reinterpret_cast<const string*>(value);
+  return *val;
+}
+
+template<>
+string BoxedValue::ValuePrinter<unsigned int>(const void *value) {
+  const unsigned int* val = reinterpret_cast<const unsigned int*>(value);
+  return base::UintToString(*val);
+}
+
+template<>
+string BoxedValue::ValuePrinter<unsigned long>(const void *value) {
+  const unsigned long* val = reinterpret_cast<const unsigned long*>(value);
+  return base::Uint64ToString(static_cast<uint64>(*val));
+}
+
+template<>
+string BoxedValue::ValuePrinter<unsigned long long>(const void *value) {
+  const unsigned long long* val =
+      reinterpret_cast<const unsigned long long*>(value);
+  return base::Uint64ToString(static_cast<uint64>(*val));
+}
+
+template<>
+string BoxedValue::ValuePrinter<int>(const void *value) {
+  const int* val = reinterpret_cast<const int*>(value);
+  return base::IntToString(*val);
+}
+
+template<>
+string BoxedValue::ValuePrinter<bool>(const void *value) {
+  const bool* val = reinterpret_cast<const bool*>(value);
+  return *val ? "true" : "false";
+}
+
+template<>
+string BoxedValue::ValuePrinter<double>(const void *value) {
+  const double* val = reinterpret_cast<const double*>(value);
+  return base::DoubleToString(*val);
+}
+
+template<>
+string BoxedValue::ValuePrinter<base::Time>(const void *value) {
+  const base::Time* val = reinterpret_cast<const base::Time*>(value);
+  return chromeos_update_engine::utils::ToString(*val);
+}
+
+template<>
+string BoxedValue::ValuePrinter<base::TimeDelta>(const void *value) {
+  const base::TimeDelta* val = reinterpret_cast<const base::TimeDelta*>(value);
+  return chromeos_update_engine::utils::FormatTimeDelta(*val);
+}
+
+static std::string ConnectionTypeToString(ConnectionType type) {
+  switch (type) {
+    case ConnectionType::kEthernet:
+      return "Ethernet";
+    case ConnectionType::kWifi:
+      return "Wifi";
+    case ConnectionType::kWimax:
+      return "Wimax";
+    case ConnectionType::kBluetooth:
+      return "Bluetooth";
+    case ConnectionType::kCellular:
+      return "Cellular";
+    case ConnectionType::kUnknown:
+      return "Unknown";
+  }
+  NOTREACHED();
+  return "Unknown";
+}
+
+template<>
+string BoxedValue::ValuePrinter<ConnectionType>(const void *value) {
+  const ConnectionType* val = reinterpret_cast<const ConnectionType*>(value);
+  return ConnectionTypeToString(*val);
+}
+
+template<>
+string BoxedValue::ValuePrinter<set<ConnectionType>>(const void *value) {
+  string ret = "";
+  const set<ConnectionType>* val =
+      reinterpret_cast<const set<ConnectionType>*>(value);
+  for (auto& it : *val) {
+    ConnectionType type = it;
+    if (ret.size() > 0)
+      ret += ",";
+    ret += ConnectionTypeToString(type);
+  }
+  return ret;
+}
+
+template<>
+string BoxedValue::ValuePrinter<ConnectionTethering>(const void *value) {
+  const ConnectionTethering* val =
+      reinterpret_cast<const ConnectionTethering*>(value);
+  switch (*val) {
+    case ConnectionTethering::kNotDetected:
+      return "Not Detected";
+    case ConnectionTethering::kSuspected:
+      return "Suspected";
+    case ConnectionTethering::kConfirmed:
+      return "Confirmed";
+    case ConnectionTethering::kUnknown:
+      return "Unknown";
+  }
+  NOTREACHED();
+  return "Unknown";
+}
+
+template<>
+string BoxedValue::ValuePrinter<Stage>(const void *value) {
+  const Stage* val = reinterpret_cast<const Stage*>(value);
+  switch (*val) {
+   case Stage::kIdle:
+      return "Idle";
+    case Stage::kCheckingForUpdate:
+      return "Checking For Update";
+    case Stage::kUpdateAvailable:
+      return "Update Available";
+    case Stage::kDownloading:
+      return "Downloading";
+    case Stage::kVerifying:
+      return "Verifying";
+    case Stage::kFinalizing:
+      return "Finalizing";
+    case Stage::kUpdatedNeedReboot:
+      return "Updated, Need Reboot";
+    case Stage::kReportingErrorEvent:
+      return "Reporting Error Event";
+    case Stage::kAttemptingRollback:
+      return "Attempting Rollback";
+  }
+  NOTREACHED();
+  return "Unknown";
+}
+
+}  // namespace chromeos_policy_manager