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.h b/policy_manager/boxed_value.h
index 0d44c3c..4e26292 100644
--- a/policy_manager/boxed_value.h
+++ b/policy_manager/boxed_value.h
@@ -5,6 +5,8 @@
 #ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_BOXED_VALUE_H_
 #define CHROMEOS_PLATFORM_UPDATE_ENGINE_POLICY_MANAGER_BOXED_VALUE_H_
 
+#include <string>
+
 #include <base/basictypes.h>
 
 namespace chromeos_policy_manager {
@@ -41,13 +43,14 @@
   // Creates an empty BoxedValue. Since the pointer can't be assigned from other
   // BoxedValues or pointers, this is only useful in places where a default
   // constructor is required, such as std::map::operator[].
-  BoxedValue() : value_(NULL), deleter_(NULL) {}
+  BoxedValue() : value_(NULL), deleter_(NULL), printer_(NULL) {}
 
   // Creates a BoxedValue for the passed pointer |value|. The BoxedValue keeps
   // the ownership of this pointer and can't be released.
   template<typename T>
   explicit BoxedValue(const T* value)
-      : value_(static_cast<const void*>(value)), deleter_(ValueDeleter<T>) {}
+    : value_(static_cast<const void*>(value)), deleter_(ValueDeleter<T>),
+      printer_(ValuePrinter<T>) {}
 
   // The move constructor takes ownership of the pointer since the semantics of
   // it allows to render the passed BoxedValue undefined. You need to use the
@@ -55,9 +58,11 @@
   // like in:
   //   BoxedValue new_box(std::move(other_box));
   BoxedValue(BoxedValue&& other)
-      : value_(other.value_), deleter_(other.deleter_) {
+      : value_(other.value_), deleter_(other.deleter_),
+        printer_(other.printer_) {
     other.value_ = NULL;
     other.deleter_ = NULL;
+    other.printer_ = NULL;
   }
 
   // Deletes the |value| passed on construction using the delete for the passed
@@ -69,12 +74,25 @@
 
   const void* value() const { return value_; }
 
+  std::string ToString() const {
+    if (!printer_)
+      return "(no printer)";
+    if (!value_)
+      return "(no value)";
+    return printer_(value_);
+  }
+
   // Static method to call the destructor of the right type.
   template<typename T>
   static void ValueDeleter(const void* value) {
     delete reinterpret_cast<const T*>(value);
   }
 
+  // Static method to print a type. See boxed_value.cc for common
+  // instantiations.
+  template<typename T>
+  static std::string ValuePrinter(const void* value);
+
  private:
   // A pointer to the cached value.
   const void* value_;
@@ -82,6 +100,9 @@
   // A function that calls delete for the right type of value_.
   void (*deleter_)(const void*);
 
+  // A function that converts value_ to a string.
+  std::string (*printer_)(const void*);
+
   DISALLOW_COPY_AND_ASSIGN(BoxedValue);
 };