skia2/dm/DMJsonWriter.cpp
Ben Wagner f15f78c905 [debugger] Handle '\0' and such in json strings.
This allows mskps produced with Chromium to be displayed in the
debugger. Previously, the debugger would produce invalid json if any
string contained characters which needed to be escaped. The debugger
also treated all strings like NULL terminated strings, but json is
Unicode based and code point U+0000 is a perfectly good code point.

Change-Id: I28150bad666b02be9f1e4af4078a4ca1e65bf000
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/549098
Commit-Queue: Ben Wagner <bungeman@google.com>
Reviewed-by: Herb Derby <herb@google.com>
2022-06-11 17:49:01 +00:00

146 lines
4.7 KiB
C++

/*
* Copyright 2014 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "dm/DMJsonWriter.h"
#include "include/core/SkData.h"
#include "include/core/SkStream.h"
#include "include/private/SkMutex.h"
#include "include/private/SkTArray.h"
#include "src/core/SkOSFile.h"
#include "src/utils/SkJSON.h"
#include "src/utils/SkJSONWriter.h"
#include "src/utils/SkOSPath.h"
#include "tools/ProcStats.h"
namespace DM {
SkTArray<JsonWriter::BitmapResult> gBitmapResults;
static SkMutex& bitmap_result_mutex() {
static SkMutex& mutex = *(new SkMutex);
return mutex;
}
void JsonWriter::AddBitmapResult(const BitmapResult& result) {
SkAutoMutexExclusive lock(bitmap_result_mutex());
gBitmapResults.push_back(result);
}
void JsonWriter::DumpJson(const char* dir,
CommandLineFlags::StringArray key,
CommandLineFlags::StringArray properties) {
if (0 == strcmp(dir, "")) {
return;
}
SkString path = SkOSPath::Join(dir, "dm.json");
sk_mkdir(dir);
SkFILEWStream stream(path.c_str());
SkJSONWriter writer(&stream, SkJSONWriter::Mode::kPretty);
writer.beginObject(); // root
for (int i = 1; i < properties.count(); i += 2) {
writer.appendCString(properties[i-1], properties[i]);
}
writer.beginObject("key");
for (int i = 1; i < key.count(); i += 2) {
writer.appendCString(key[i-1], key[i]);
}
writer.endObject();
int maxResidentSetSizeMB = sk_tools::getMaxResidentSetSizeMB();
if (maxResidentSetSizeMB != -1) {
writer.appendS32("max_rss_MB", maxResidentSetSizeMB);
}
{
SkAutoMutexExclusive lock(bitmap_result_mutex());
writer.beginArray("results");
for (int i = 0; i < gBitmapResults.count(); i++) {
writer.beginObject();
writer.beginObject("key");
writer.appendString("name" , gBitmapResults[i].name);
writer.appendString("config" , gBitmapResults[i].config);
writer.appendString("source_type", gBitmapResults[i].sourceType);
// Source options only need to be part of the key if they exist.
// Source type by source type, we either always set options or never set options.
if (!gBitmapResults[i].sourceOptions.isEmpty()) {
writer.appendString("source_options", gBitmapResults[i].sourceOptions);
}
writer.endObject(); // key
writer.beginObject("options");
writer.appendString("ext" , gBitmapResults[i].ext);
writer.appendString("gamut", gBitmapResults[i].gamut);
writer.appendString("transfer_fn", gBitmapResults[i].transferFn);
writer.appendString("color_type", gBitmapResults[i].colorType);
writer.appendString("alpha_type", gBitmapResults[i].alphaType);
writer.appendString("color_depth", gBitmapResults[i].colorDepth);
writer.endObject(); // options
writer.appendString("md5", gBitmapResults[i].md5);
writer.endObject(); // 1 result
}
writer.endArray(); // results
}
writer.endObject(); // root
writer.flush();
stream.flush();
}
using namespace skjson;
bool JsonWriter::ReadJson(const char* path, void(*callback)(BitmapResult)) {
sk_sp<SkData> json(SkData::MakeFromFileName(path));
if (!json) {
return false;
}
DOM dom((const char*)json->data(), json->size());
const ObjectValue* root = dom.root();
if (!root) {
return false;
}
const ArrayValue* results = (*root)["results"];
if (!results) {
return false;
}
BitmapResult br;
for (const ObjectValue* r : *results) {
const ObjectValue& key = (*r)["key"].as<ObjectValue>();
const ObjectValue& options = (*r)["options"].as<ObjectValue>();
br.name = key["name"].as<StringValue>().begin();
br.config = key["config"].as<StringValue>().begin();
br.sourceType = key["source_type"].as<StringValue>().begin();
br.ext = options["ext"].as<StringValue>().begin();
br.gamut = options["gamut"].as<StringValue>().begin();
br.transferFn = options["transfer_fn"].as<StringValue>().begin();
br.colorType = options["color_type"].as<StringValue>().begin();
br.alphaType = options["alpha_type"].as<StringValue>().begin();
br.colorDepth = options["color_depth"].as<StringValue>().begin();
br.md5 = (*r)["md5"].as<StringValue>().begin();
if (const StringValue* so = key["source_options"]) {
br.sourceOptions = so->begin();
}
callback(br);
}
return true;
}
} // namespace DM