Merge "edify: Rename parse_string to ParseString and let it take std::string."
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index fc29493..b1f5607 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -553,7 +553,7 @@
 static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
                           const std::string& target_filename,
                           const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data) {
-  if (patch->type != VAL_BLOB) {
+  if (patch->type != Value::Type::BLOB) {
     LOG(ERROR) << "patch is not a blob";
     return 1;
   }
diff --git a/applypatch/applypatch_modes.cpp b/applypatch/applypatch_modes.cpp
index 6437e1b..ec95325 100644
--- a/applypatch/applypatch_modes.cpp
+++ b/applypatch/applypatch_modes.cpp
@@ -81,52 +81,51 @@
 }
 
 static int PatchMode(int argc, const char** argv) {
-    FileContents bonusFc;
-    Value bonus(VAL_INVALID, "");
-
-    if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
-        if (LoadFileContents(argv[2], &bonusFc) != 0) {
-          LOG(ERROR) << "Failed to load bonus file " << argv[2];
-          return 1;
-        }
-        bonus.type = VAL_BLOB;
-        bonus.data = std::string(bonusFc.data.cbegin(), bonusFc.data.cend());
-        argc -= 2;
-        argv += 2;
-    }
-
-    if (argc < 4) {
-        return 2;
-    }
-
-    size_t target_size;
-    if (!android::base::ParseUint(argv[4], &target_size) || target_size == 0) {
-      LOG(ERROR) << "Failed to parse \"" << argv[4] << "\" as byte count";
+  std::unique_ptr<Value> bonus;
+  if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
+    FileContents bonus_fc;
+    if (LoadFileContents(argv[2], &bonus_fc) != 0) {
+      LOG(ERROR) << "Failed to load bonus file " << argv[2];
       return 1;
     }
+    bonus = std::make_unique<Value>(Value::Type::BLOB,
+                                    std::string(bonus_fc.data.cbegin(), bonus_fc.data.cend()));
+    argc -= 2;
+    argv += 2;
+  }
 
-    // If no <src-sha1>:<patch> is provided, it is in flash mode.
-    if (argc == 5) {
-        if (bonus.type != VAL_INVALID) {
-          LOG(ERROR) << "bonus file not supported in flash mode";
-          return 1;
-        }
-        return FlashMode(argv[1], argv[2], argv[3], target_size);
-    }
+  if (argc < 4) {
+    return 2;
+  }
 
-    std::vector<std::string> sha1s;
-    std::vector<FileContents> files;
-    if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) {
-      LOG(ERROR) << "Failed to parse patch args";
+  size_t target_size;
+  if (!android::base::ParseUint(argv[4], &target_size) || target_size == 0) {
+    LOG(ERROR) << "Failed to parse \"" << argv[4] << "\" as byte count";
+    return 1;
+  }
+
+  // If no <src-sha1>:<patch> is provided, it is in flash mode.
+  if (argc == 5) {
+    if (bonus) {
+      LOG(ERROR) << "bonus file not supported in flash mode";
       return 1;
     }
+    return FlashMode(argv[1], argv[2], argv[3], target_size);
+  }
 
-    std::vector<std::unique_ptr<Value>> patches;
-    for (size_t i = 0; i < files.size(); ++i) {
-        patches.push_back(std::make_unique<Value>(
-                VAL_BLOB, std::string(files[i].data.cbegin(), files[i].data.cend())));
-    }
-    return applypatch(argv[1], argv[2], argv[3], target_size, sha1s, patches, &bonus);
+  std::vector<std::string> sha1s;
+  std::vector<FileContents> files;
+  if (!ParsePatchArgs(argc - 5, argv + 5, &sha1s, &files)) {
+    LOG(ERROR) << "Failed to parse patch args";
+    return 1;
+  }
+
+  std::vector<std::unique_ptr<Value>> patches;
+  for (const auto& file : files) {
+    patches.push_back(std::make_unique<Value>(Value::Type::BLOB,
+                                              std::string(file.data.cbegin(), file.data.cend())));
+  }
+  return applypatch(argv[1], argv[2], argv[3], target_size, sha1s, patches, bonus.get());
 }
 
 // This program (applypatch) applies binary patches to files in a way that
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 2f8f485..da75692 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -151,7 +151,8 @@
 
 int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const unsigned char* patch_data,
                     size_t patch_size, SinkFn sink) {
-  Value patch(VAL_BLOB, std::string(reinterpret_cast<const char*>(patch_data), patch_size));
+  Value patch(Value::Type::BLOB,
+              std::string(reinterpret_cast<const char*>(patch_data), patch_size));
   return ApplyImagePatch(old_data, old_size, patch, sink, nullptr);
 }
 
@@ -246,11 +247,10 @@
       // Decompress the source data; the chunk header tells us exactly
       // how big we expect it to be when decompressed.
 
-      // Note: expanded_len will include the bonus data size if
-      // the patch was constructed with bonus data.  The
-      // deflation will come up 'bonus_size' bytes short; these
-      // must be appended from the bonus_data value.
-      size_t bonus_size = (i == 1 && bonus_data != NULL) ? bonus_data->data.size() : 0;
+      // Note: expanded_len will include the bonus data size if the patch was constructed with
+      // bonus data. The deflation will come up 'bonus_size' bytes short; these must be appended
+      // from the bonus_data value.
+      size_t bonus_size = (i == 1 && bonus_data != nullptr) ? bonus_data->data.size() : 0;
 
       std::vector<unsigned char> expanded_source(expanded_len);
 
@@ -288,7 +288,7 @@
         inflateEnd(&strm);
 
         if (bonus_size) {
-          memcpy(expanded_source.data() + (expanded_len - bonus_size), &bonus_data->data[0],
+          memcpy(expanded_source.data() + (expanded_len - bonus_size), bonus_data->data.data(),
                  bonus_size);
         }
       }
diff --git a/edify/expr.cpp b/edify/expr.cpp
index 6823b73..c090eb2 100644
--- a/edify/expr.cpp
+++ b/edify/expr.cpp
@@ -51,9 +51,9 @@
     if (!v) {
         return false;
     }
-    if (v->type != VAL_STRING) {
-        ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
-        return false;
+    if (v->type != Value::Type::STRING) {
+      ErrorAbort(state, kArgsParsingFailure, "expecting string, got value type %d", v->type);
+      return false;
     }
 
     *result = v->data;
@@ -68,7 +68,7 @@
     if (str == nullptr) {
         return nullptr;
     }
-    return new Value(VAL_STRING, str);
+    return new Value(Value::Type::STRING, str);
 }
 
 Value* StringValue(const std::string& str) {
diff --git a/edify/include/edify/expr.h b/edify/include/edify/expr.h
index b922a9b..5cbd5e1 100644
--- a/edify/include/edify/expr.h
+++ b/edify/include/edify/expr.h
@@ -53,19 +53,16 @@
   bool is_retry = false;
 };
 
-enum ValueType {
-    VAL_INVALID = -1,
-    VAL_STRING = 1,
-    VAL_BLOB = 2,
-};
-
 struct Value {
-    ValueType type;
-    std::string data;
+  enum class Type {
+    STRING = 1,
+    BLOB = 2,
+  };
 
-    Value(ValueType type, const std::string& str) :
-        type(type),
-        data(str) {}
+  Value(Type type, const std::string& str) : type(type), data(str) {}
+
+  Type type;
+  std::string data;
 };
 
 struct Expr;
diff --git a/tests/component/updater_test.cpp b/tests/component/updater_test.cpp
index 81ea3b6..91e5cc1 100644
--- a/tests/component/updater_test.cpp
+++ b/tests/component/updater_test.cpp
@@ -149,11 +149,11 @@
     return nullptr;
   }
 
-  if (args[0]->type != VAL_BLOB) {
+  if (args[0]->type != Value::Type::BLOB) {
     return ErrorAbort(state, kArgsParsingFailure, "%s() expects a BLOB argument", name);
   }
 
-  args[0]->type = VAL_STRING;
+  args[0]->type = Value::Type::STRING;
   return args[0].release();
 }
 
diff --git a/updater/blockimg.cpp b/updater/blockimg.cpp
index fc71385..6a6236b 100644
--- a/updater/blockimg.cpp
+++ b/updater/blockimg.cpp
@@ -1403,7 +1403,8 @@
     if (status == 0) {
       LOG(INFO) << "patching " << blocks << " blocks to " << tgt.blocks();
       Value patch_value(
-          VAL_BLOB, std::string(reinterpret_cast<const char*>(params.patch_start + offset), len));
+          Value::Type::BLOB,
+          std::string(reinterpret_cast<const char*>(params.patch_start + offset), len));
 
       RangeSinkWriter writer(params.fd, tgt);
       if (params.cmdname[0] == 'i') {  // imgdiff
@@ -1531,19 +1532,19 @@
   const std::unique_ptr<Value>& new_data_fn = args[2];
   const std::unique_ptr<Value>& patch_data_fn = args[3];
 
-  if (blockdev_filename->type != VAL_STRING) {
+  if (blockdev_filename->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", name);
     return StringValue("");
   }
-  if (transfer_list_value->type != VAL_BLOB) {
+  if (transfer_list_value->type != Value::Type::BLOB) {
     ErrorAbort(state, kArgsParsingFailure, "transfer_list argument to %s must be blob", name);
     return StringValue("");
   }
-  if (new_data_fn->type != VAL_STRING) {
+  if (new_data_fn->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "new_data_fn argument to %s must be string", name);
     return StringValue("");
   }
-  if (patch_data_fn->type != VAL_STRING) {
+  if (patch_data_fn->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "patch_data_fn argument to %s must be string", name);
     return StringValue("");
   }
@@ -1944,11 +1945,11 @@
   const std::unique_ptr<Value>& blockdev_filename = args[0];
   const std::unique_ptr<Value>& ranges = args[1];
 
-  if (blockdev_filename->type != VAL_STRING) {
+  if (blockdev_filename->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "blockdev_filename argument to %s must be string", name);
     return StringValue("");
   }
-  if (ranges->type != VAL_STRING) {
+  if (ranges->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
     return StringValue("");
   }
@@ -2010,7 +2011,7 @@
 
   const std::unique_ptr<Value>& arg_filename = args[0];
 
-  if (arg_filename->type != VAL_STRING) {
+  if (arg_filename->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
     return StringValue("");
   }
@@ -2065,11 +2066,11 @@
   const std::unique_ptr<Value>& filename = args[0];
   const std::unique_ptr<Value>& ranges = args[1];
 
-  if (filename->type != VAL_STRING) {
+  if (filename->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "filename argument to %s must be string", name);
     return StringValue("");
   }
-  if (ranges->type != VAL_STRING) {
+  if (ranges->type != Value::Type::STRING) {
     ErrorAbort(state, kArgsParsingFailure, "ranges argument to %s must be string", name);
     return StringValue("");
   }
diff --git a/updater/install.cpp b/updater/install.cpp
index 9d108e0..02a6fe7 100644
--- a/updater/install.cpp
+++ b/updater/install.cpp
@@ -191,7 +191,7 @@
                         zip_path.c_str(), buffer.size(), ErrorCodeString(ret));
     }
 
-    return new Value(VAL_BLOB, buffer);
+    return new Value(Value::Type::BLOB, buffer);
   }
 }
 
@@ -238,10 +238,10 @@
   }
 
   for (int i = 0; i < patchcount; ++i) {
-    if (arg_values[i * 2]->type != VAL_STRING) {
+    if (arg_values[i * 2]->type != Value::Type::STRING) {
       return ErrorAbort(state, kArgsParsingFailure, "%s(): sha-1 #%d is not string", name, i * 2);
     }
-    if (arg_values[i * 2 + 1]->type != VAL_BLOB) {
+    if (arg_values[i * 2 + 1]->type != Value::Type::BLOB) {
       return ErrorAbort(state, kArgsParsingFailure, "%s(): patch #%d is not blob", name, i * 2 + 1);
     }
   }
@@ -741,8 +741,8 @@
   return StringValue(std::to_string(status));
 }
 
-// Read a local file and return its contents (the Value* returned
-// is actually a FileContents*).
+// read_file(filename)
+//   Reads a local file 'filename' and returns its contents as a Value string.
 Value* ReadFileFn(const char* name, State* state, const std::vector<std::unique_ptr<Expr>>& argv) {
   if (argv.size() != 1) {
     return ErrorAbort(state, kArgsParsingFailure, "%s() expects 1 arg, got %zu", name, argv.size());
@@ -750,18 +750,18 @@
 
   std::vector<std::string> args;
   if (!ReadArgs(state, argv, &args)) {
-    return ErrorAbort(state, kArgsParsingFailure, "%s() Failed to parse the argument(s)", name);
+    return ErrorAbort(state, kArgsParsingFailure, "%s(): Failed to parse the argument(s)", name);
   }
   const std::string& filename = args[0];
 
-  Value* v = new Value(VAL_INVALID, "");
-
   FileContents fc;
   if (LoadFileContents(filename.c_str(), &fc) == 0) {
-    v->type = VAL_BLOB;
-    v->data = std::string(fc.data.begin(), fc.data.end());
+    return new Value(Value::Type::BLOB, std::string(fc.data.cbegin(), fc.data.cend()));
   }
-  return v;
+
+  // Leave it to caller to handle the failure.
+  LOG(ERROR) << name << ": Failed to read " << filename;
+  return StringValue("");
 }
 
 // write_value(value, filename)