Commit 1265dbe6 by Jordan Bayles Committed by Commit Bot

Update JsonCpp usage

This patch updates usages of the JsonCpp library, including the following changes: 1. Removed unused version variable from the DEPS file. 2. Removed deprecated writer and reader usages, in favor of the new builder pattern inside JsonCpp. 3. Modernized usage of the Json::Value types, including some rewrites to avoid unnecessary heap allocations, and using the new foreach iterators. Bug: chromium:983223 Change-Id: If26abc8be677d905183a23498fbb81256854525c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2265093Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Geoff Lang <geofflang@chromium.org>
parent 8804d35c
...@@ -35,6 +35,17 @@ vars = { ...@@ -35,6 +35,17 @@ vars = {
# Note: this dep cannot be auto-rolled b/c of nesting. # Note: this dep cannot be auto-rolled b/c of nesting.
'jsoncpp_revision': '645250b6690785be60ab6780ce4b58698d884d11', 'jsoncpp_revision': '645250b6690785be60ab6780ce4b58698d884d11',
# Current revision of Chrome's third_party jsoncpp directory. This repository
# is mirrored as a separate repository, with separate git hashes that
# don't match the external JsonCpp repository or Chrome. Mirrored patches
# will have a different git hash associated with them.
# To roll, first get the new hash for chromium_jsoncpp_revision from the
# mirror of third_party/jsoncpp located here:
# https://chromium.googlesource.com/chromium/src/third_party/jsoncpp/
# Then get the new hash for jsoncpp_revision from the root Chrome DEPS file:
# https://source.chromium.org/chromium/chromium/src/+/master:DEPS
'chromium_jsoncpp_revision': 'ec647b85b61f525a1a74e4da7477b0c5371c50f4',
# Current revision of patched-yasm. # Current revision of patched-yasm.
# Note: this dep cannot be auto-rolled b/c of nesting. # Note: this dep cannot be auto-rolled b/c of nesting.
'patched_yasm_revision': '720b70524a4424b15fc57e82263568c8ba0496ad', 'patched_yasm_revision': '720b70524a4424b15fc57e82263568c8ba0496ad',
...@@ -136,7 +147,7 @@ deps = { ...@@ -136,7 +147,7 @@ deps = {
}, },
'third_party/jsoncpp': { 'third_party/jsoncpp': {
'url': '{chromium_git}/chromium/src/third_party/jsoncpp@ec647b85b61f525a1a74e4da7477b0c5371c50f4', 'url': '{chromium_git}/chromium/src/third_party/jsoncpp@{chromium_jsoncpp_revision}',
'condition': 'not build_with_chromium', 'condition': 'not build_with_chromium',
}, },
......
...@@ -17,7 +17,12 @@ ...@@ -17,7 +17,12 @@
# include <unistd.h> # include <unistd.h>
#endif #endif
#include <fstream> #include <fstream>
#include <ios>
#include <list> #include <list>
#include <memory>
#include <sstream>
#include <utility>
#include <vector>
#include "../gpu_info_util/SystemInfo.h" #include "../gpu_info_util/SystemInfo.h"
namespace angle namespace angle
...@@ -124,9 +129,19 @@ constexpr char kJsonVerPatch[] = "VerPatch"; ...@@ -124,9 +129,19 @@ constexpr char kJsonVerPatch[] = "VerPatch";
class StringPart class StringPart
{ {
public: public:
StringPart() : mPart(""), mWildcard(true) {} StringPart() = default;
StringPart(const std::string part) : mPart(part), mWildcard(false) {} explicit StringPart(const std::string part) : mPart(part), mWildcard(false) {}
~StringPart() {} ~StringPart() = default;
static StringPart FromJson(const Json::Value &parent, const char *key)
{
if (parent.isMember(key) && parent[key].isString())
{
return StringPart(parent[key].asString());
}
return {};
}
bool match(const StringPart &toCheck) const bool match(const StringPart &toCheck) const
{ {
return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart)); return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart));
...@@ -134,7 +149,7 @@ class StringPart ...@@ -134,7 +149,7 @@ class StringPart
public: public:
std::string mPart; std::string mPart;
bool mWildcard; bool mWildcard = true;
}; };
// This encapsulates a 32-bit unsigned integer. The default constructor (not given a number) // This encapsulates a 32-bit unsigned integer. The default constructor (not given a number)
...@@ -142,17 +157,27 @@ class StringPart ...@@ -142,17 +157,27 @@ class StringPart
class IntegerPart class IntegerPart
{ {
public: public:
IntegerPart() : mPart(0), mWildcard(true) {} IntegerPart() = default;
IntegerPart(uint32_t part) : mPart(part), mWildcard(false) {} explicit IntegerPart(uint32_t part) : mPart(part), mWildcard(false) {}
~IntegerPart() {} ~IntegerPart() = default;
static IntegerPart FromJson(const Json::Value &parent, const char *key)
{
if (parent.isMember(key) && parent[key].isInt())
{
return IntegerPart(parent[key].asInt());
}
return {};
}
bool match(const IntegerPart &toCheck) const bool match(const IntegerPart &toCheck) const
{ {
return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart)); return (mWildcard || toCheck.mWildcard || (toCheck.mPart == mPart));
} }
public: public:
uint32_t mPart; uint32_t mPart = 0;
bool mWildcard; bool mWildcard = true;
}; };
// This encapsulates a list of other classes, each of which will have a match() and logItem() // This encapsulates a list of other classes, each of which will have a match() and logItem()
...@@ -162,59 +187,61 @@ template <class T> ...@@ -162,59 +187,61 @@ template <class T>
class ListOf class ListOf
{ {
public: public:
ListOf(const std::string listType) : mWildcard(true), mListType(listType) {} explicit ListOf(const std::string listType) : mWildcard(true), mListType(listType) {}
~ListOf() { mList.clear(); } ~ListOf() { mList.clear(); }
void addItem(const T &toAdd) void addItem(T &&toAdd)
{ {
mList.push_back(toAdd); mList.push_back(std::move(toAdd));
mWildcard = false; mWildcard = false;
} }
bool match(const T &toCheck) const bool match(const T &toCheck) const
{ {
VERBOSE("\t\t Within ListOf<%s> match: wildcards are %s and %s,\n", mListType.c_str(), VERBOSE("\t\t Matching ListOf<%s> against item:\n", mListType.c_str());
mWildcard ? "true" : "false", toCheck.mWildcard ? "true" : "false");
if (mWildcard || toCheck.mWildcard) if (mWildcard || toCheck.mWildcard)
{ {
VERBOSE("\t\t\t Successful match due to wildcard.\n");
return true; return true;
} }
for (const T &it : mList) for (const T &it : mList)
{ {
VERBOSE("\t\t Within ListOf<%s> match: calling match on sub-item is %s,\n",
mListType.c_str(), it.match(toCheck) ? "true" : "false");
if (it.match(toCheck)) if (it.match(toCheck))
{ {
VERBOSE("\t\t\t Successful match due to list item match.\n");
return true; return true;
} }
} }
VERBOSE("\t\t\t Failed to match.\n");
return false; return false;
} }
bool match(const ListOf<T> &toCheck) const bool match(const ListOf<T> &toCheck) const
{ {
VERBOSE("\t\t Within ListOf<%s> match: wildcards are %s and %s,\n", mListType.c_str(), VERBOSE("\t\t Matching ListOf<%s>:\n", mListType.c_str());
mWildcard ? "true" : "false", toCheck.mWildcard ? "true" : "false");
if (mWildcard || toCheck.mWildcard) if (mWildcard || toCheck.mWildcard)
{ {
VERBOSE("\t\t\t Successful match due to wildcard.\n");
return true; return true;
} }
// If we make it to here, both this and toCheck have at least one item in their mList // If we make it to here, both this and toCheck have at least one item in their mList.
for (const T &it : toCheck.mList) for (const T &it : toCheck.mList)
{ {
if (match(it)) if (match(it))
{ {
VERBOSE("\t\t\t Successful match due to list item match.\n");
return true; return true;
} }
} }
VERBOSE("\t\t\t Failed to match list.\n");
return false; return false;
} }
void logListOf(const std::string prefix, const std::string name) const void logListOf(const std::string prefix, const std::string name) const
{ {
if (mWildcard) if (mWildcard)
{ {
VERBOSE("%sListOf%s is wildcarded to always match", prefix.c_str(), name.c_str()); VERBOSE("%sListOf%s is wildcarded to always match\n", prefix.c_str(), name.c_str());
} }
else else
{ {
VERBOSE("%sListOf%s has %d item(s):", prefix.c_str(), name.c_str(), VERBOSE("%sListOf%s has %d item(s):\n", prefix.c_str(), name.c_str(),
static_cast<int>(mList.size())); static_cast<int>(mList.size()));
for (auto &it : mList) for (auto &it : mList)
{ {
...@@ -238,122 +265,88 @@ class Version ...@@ -238,122 +265,88 @@ class Version
{ {
public: public:
Version(uint32_t major, uint32_t minor, uint32_t subminor, uint32_t patch) Version(uint32_t major, uint32_t minor, uint32_t subminor, uint32_t patch)
: mMajor(major), mMinor(minor), mSubminor(subminor), mPatch(patch), mWildcard(false) : mMajor(major), mMinor(minor), mSubminor(subminor), mPatch(patch)
{}
Version(uint32_t major, uint32_t minor, uint32_t subminor)
: mMajor(major), mMinor(minor), mSubminor(subminor), mWildcard(false)
{} {}
Version(uint32_t major, uint32_t minor) : mMajor(major), mMinor(minor), mWildcard(false) {}
Version(uint32_t major) : mMajor(major), mWildcard(false) {}
Version() : mWildcard(true) {}
Version(const Version &toCopy)
: mMajor(toCopy.mMajor),
mMinor(toCopy.mMinor),
mSubminor(toCopy.mSubminor),
mPatch(toCopy.mPatch),
mWildcard(toCopy.mWildcard)
{}
~Version() {}
static Version *CreateVersionFromJson(const Json::Value &jObject) Version() = default;
{ Version(const Version &) = default;
Version *version = nullptr; Version(Version &&) = default;
// A major version must be provided before a minor, and so on: Version &operator=(const Version &) = default;
if (jObject.isMember(kJsonVerMajor) && jObject[kJsonVerMajor].isInt()) Version &operator=(Version &&) = default;
{ ~Version() = default;
int major = jObject[kJsonVerMajor].asInt();
if (jObject.isMember(kJsonVerMinor) && jObject[kJsonVerMinor].isInt()) static Version FromJson(const Json::Value &jObject)
{
int minor = jObject[kJsonVerMinor].asInt();
if (jObject.isMember(kJsonVerSubMinor) && jObject[kJsonVerSubMinor].isInt())
{
int subMinor = jObject[kJsonVerSubMinor].asInt();
if (jObject.isMember(kJsonVerPatch) && jObject[kJsonVerPatch].isInt())
{ {
int patch = jObject[kJsonVerPatch].asInt(); Version version;
version = new Version(major, minor, subMinor, patch); version.mMajor = IntegerPart::FromJson(jObject, kJsonVerMajor);
} if (version.mMajor.mWildcard)
else
{ {
version = new Version(major, minor, subMinor); return version;
}
} }
else // Revision fields are only checked if their parent version field
// is set.
version.mMinor = IntegerPart::FromJson(jObject, kJsonVerMinor);
if (version.mMinor.mWildcard)
{ {
version = new Version(major, minor); return version;
}
} }
else
version.mSubminor = IntegerPart::FromJson(jObject, kJsonVerSubMinor);
if (version.mSubminor.mWildcard)
{ {
version = new Version(major); return version;
}
} }
version.mPatch = IntegerPart::FromJson(jObject, kJsonVerPatch);
return version; return version;
} }
bool match(const Version &toCheck) const bool match(const Version &toCheck) const
{ {
VERBOSE("\t\t\t Within Version %d,%d,%d,%d match(%d,%d,%d,%d): wildcards are %s and %s,\n", VERBOSE("\t\t\t Matching Version %s against %s\n", getString().c_str(),
mMajor.mPart, mMinor.mPart, mSubminor.mPart, mPatch.mPart, toCheck.mMajor.mPart, toCheck.getString().c_str());
toCheck.mMinor.mPart, toCheck.mSubminor.mPart, toCheck.mPatch.mPart, return (isWildcard() || toCheck.isWildcard() ||
mWildcard ? "true" : "false", toCheck.mWildcard ? "true" : "false");
if (!(mWildcard || toCheck.mWildcard))
{
VERBOSE("\t\t\t mMajor match is %s, mMinor is %s, mSubminor is %s, mPatch is %s\n",
mMajor.match(toCheck.mMajor) ? "true" : "false",
mMinor.match(toCheck.mMinor) ? "true" : "false",
mSubminor.match(toCheck.mSubminor) ? "true" : "false",
mPatch.match(toCheck.mPatch) ? "true" : "false");
}
return (mWildcard || toCheck.mWildcard ||
(mMajor.match(toCheck.mMajor) && mMinor.match(toCheck.mMinor) && (mMajor.match(toCheck.mMajor) && mMinor.match(toCheck.mMinor) &&
mSubminor.match(toCheck.mSubminor) && mPatch.match(toCheck.mPatch))); mSubminor.match(toCheck.mSubminor) && mPatch.match(toCheck.mPatch)));
} }
std::string getString() const std::string getString() const
{ {
if (mWildcard) if (mMajor.mWildcard)
{ {
return "*"; return "*";
} }
else
{ std::ostringstream ss;
char ret[100]; ss << mMajor.mPart;
// Must at least have a major version: // Must at least have a major version:
if (!mMinor.mWildcard) if (!mMinor.mWildcard)
{ {
ss << "." << mMinor.mPart;
if (!mSubminor.mWildcard) if (!mSubminor.mWildcard)
{ {
ss << "." << mSubminor.mPart;
if (!mPatch.mWildcard) if (!mPatch.mWildcard)
{ {
snprintf(ret, 100, "%d.%d.%d.%d", mMajor.mPart, mMinor.mPart, ss << "." << mPatch.mPart;
mSubminor.mPart, mPatch.mPart);
}
else
{
snprintf(ret, 100, "%d.%d.%d.*", mMajor.mPart, mMinor.mPart,
mSubminor.mPart);
} }
} }
else
{
snprintf(ret, 100, "%d.%d.*", mMajor.mPart, mMinor.mPart);
} }
} if (mPatch.mWildcard)
else
{ {
snprintf(ret, 100, "%d.*", mMajor.mPart); ss << ".*";
}
std::string retString = ret;
return retString;
} }
return ss.str();
} }
bool isWildcard() const { return mMajor.mWildcard; }
public: public:
IntegerPart mMajor; IntegerPart mMajor;
IntegerPart mMinor; IntegerPart mMinor;
IntegerPart mSubminor; IntegerPart mSubminor;
IntegerPart mPatch; IntegerPart mPatch;
bool mWildcard;
}; };
// This encapsulates an application, and potentially the application's Version. The default // This encapsulates an application, and potentially the application's Version. The default
...@@ -363,32 +356,23 @@ class Version ...@@ -363,32 +356,23 @@ class Version
class Application class Application
{ {
public: public:
Application(const std::string name, const Version &version) Application(StringPart name, Version version = {})
: mName(name), mVersion(version), mWildcard(false) : mName(name), mVersion(version), mWildcard(false)
{} {}
Application(const std::string name) : mName(name), mVersion(), mWildcard(false) {} Application() = default;
Application() : mName(), mVersion(), mWildcard(true) {} ~Application() = default;
~Application() {}
static Application *CreateApplicationFromJson(const Json::Value &jObject) static bool FromJson(const Json::Value &jObject, Application *out)
{ {
Application *application = nullptr;
// If an application is listed, the application's name is required: // If an application is listed, the application's name is required:
std::string appName = jObject[kJsonAppName].asString(); auto name = StringPart::FromJson(jObject, kJsonAppName);
if (name.mWildcard)
// The application's version is optional:
Version *version = Version::CreateVersionFromJson(jObject);
if (version)
{
application = new Application(appName, *version);
delete version;
}
else
{ {
application = new Application(appName); return false;
} }
return application; auto version = Version::FromJson(jObject);
*out = Application{std::move(name), std::move(version)};
return true;
} }
bool match(const Application &toCheck) const bool match(const Application &toCheck) const
...@@ -400,23 +384,23 @@ class Application ...@@ -400,23 +384,23 @@ class Application
{ {
if (mWildcard) if (mWildcard)
{ {
VERBOSE(" Wildcard (i.e. will match all applications)"); VERBOSE(" Wildcard (i.e. will match all applications)\n");
} }
else if (!mVersion.mWildcard) else if (!mVersion.isWildcard())
{ {
VERBOSE(" Application \"%s\" (version: %s)", mName.mPart.c_str(), VERBOSE(" Application \"%s\" (version: %s)\n", mName.mPart.c_str(),
mVersion.getString().c_str()); mVersion.getString().c_str());
} }
else else
{ {
VERBOSE(" Application \"%s\"", mName.mPart.c_str()); VERBOSE(" Application \"%s\"\n", mName.mPart.c_str());
} }
} }
public: public:
StringPart mName; StringPart mName;
Version mVersion; Version mVersion;
bool mWildcard; bool mWildcard = true;
}; };
// This encapsulates a GPU and its driver. The default constructor (not given any values) assumes // This encapsulates a GPU and its driver. The default constructor (not given any values) assumes
...@@ -425,101 +409,67 @@ class Application ...@@ -425,101 +409,67 @@ class Application
class GPU class GPU
{ {
public: public:
GPU(const std::string vendor, uint32_t deviceId, const Version &version) GPU(StringPart vendor, IntegerPart deviceId, Version version)
: mVendor(vendor), mDeviceId(IntegerPart(deviceId)), mVersion(version), mWildcard(false) : mVendor(std::move(vendor)),
mDeviceId(std::move(deviceId)),
mVersion(version),
mWildcard(false)
{} {}
GPU(const std::string vendor, uint32_t deviceId) GPU(std::string vendor, uint32_t deviceId, Version version)
: mVendor(vendor), mDeviceId(IntegerPart(deviceId)), mVersion(), mWildcard(false) : GPU(StringPart(std::move(vendor)), IntegerPart(deviceId), std::move(version))
{} {}
GPU(const std::string vendor) : mVendor(vendor), mDeviceId(), mVersion(), mWildcard(false) {} GPU() = default;
GPU() : mVendor(), mDeviceId(), mVersion(), mWildcard(true) {} ~GPU() = default;
bool match(const GPU &toCheck) const bool match(const GPU &toCheck) const
{ {
VERBOSE("\t\t Within GPU match: wildcards are %s and %s,\n", mWildcard ? "true" : "false", VERBOSE("\t\t Matching %s \n\t\t against %s\n", toString().c_str(),
toCheck.mWildcard ? "true" : "false"); toCheck.toString().c_str());
VERBOSE("\t\t mVendor = \"%s\" and toCheck.mVendor = \"%s\"\n", mVendor.mPart.c_str(),
toCheck.mVendor.mPart.c_str());
VERBOSE("\t\t mDeviceId = %d and toCheck.mDeviceId = %d\n", mDeviceId.mPart,
toCheck.mDeviceId.mPart);
VERBOSE("\t\t mVendor match is %s, mDeviceId is %s, mVersion is %s\n",
toCheck.mVendor.match(mVendor) ? "true" : "false",
toCheck.mDeviceId.match(mDeviceId) ? "true" : "false",
toCheck.mVersion.match(mVersion) ? "true" : "false");
return (mWildcard || toCheck.mWildcard || return (mWildcard || toCheck.mWildcard ||
(toCheck.mVendor.match(mVendor) && toCheck.mDeviceId.match(mDeviceId) && (toCheck.mVendor.match(mVendor) && toCheck.mDeviceId.match(mDeviceId) &&
toCheck.mVersion.match(mVersion))); toCheck.mVersion.match(mVersion)));
} }
~GPU() {}
static GPU *CreateGpuFromJson(const Json::Value &jObject) // Returns true if out is set to a valid GPU instance.
static bool CreateGpuFromJson(const Json::Value &jObject, GPU *out)
{ {
GPU *gpu = nullptr;
// If a GPU is listed, the vendor name is required: // If a GPU is listed, the vendor name is required:
if (jObject.isMember(kJsonVendor) && jObject[kJsonVendor].isString()) auto vendor = StringPart::FromJson(jObject, kJsonVendor);
if (vendor.mWildcard)
{ {
std::string vendor = jObject[kJsonVendor].asString(); WARN("Asked to parse a GPU, but no vendor found.\n");
// If a version is given, the deviceId is required: return false;
if (jObject.isMember(kJsonDeviceId) && jObject[kJsonDeviceId].isUInt())
{
uint32_t deviceId = jObject[kJsonDeviceId].asUInt();
Version *version = Version::CreateVersionFromJson(jObject);
if (version)
{
gpu = new GPU(vendor, deviceId, *version);
delete version;
}
else
{
gpu = new GPU(vendor, deviceId);
}
}
else
{
gpu = new GPU(vendor);
}
}
else
{
WARN("Asked to parse a GPU, but no vendor found");
} }
return gpu; auto deviceId = IntegerPart::FromJson(jObject, kJsonDeviceId);
auto version = Version::FromJson(jObject);
*out = GPU{std::move(vendor), std::move(deviceId), std::move(version)};
return true;
} }
void logItem() const std::string toString() const
{ {
if (mWildcard) if (mWildcard)
{ {
VERBOSE(" Wildcard (i.e. will match all GPUs)"); return std::string("Wildcard (i.e. will match all GPUs)");
} }
else
{ std::ostringstream ss;
ss << "GPU vendor: " << mVendor.mPart;
if (!mDeviceId.mWildcard) if (!mDeviceId.mWildcard)
{ {
if (!mVersion.mWildcard) ss << ", deviceId: " << std::hex << mDeviceId.mPart;
{
VERBOSE("\t GPU vendor: %s, deviceId: 0x%x, version: %s",
mVendor.mPart.c_str(), mDeviceId.mPart, mVersion.getString().c_str());
}
else
{
VERBOSE("\t GPU vendor: %s, deviceId: 0x%x", mVendor.mPart.c_str(),
mDeviceId.mPart);
}
}
else
{
VERBOSE("\t GPU vendor: %s", mVendor.mPart.c_str());
}
} }
ss << ", version: " << mVersion.getString();
return ss.str();
} }
void logItem() const { VERBOSE("\t %s\n", toString().c_str()); }
public: public:
StringPart mVendor; StringPart mVendor;
IntegerPart mDeviceId; IntegerPart mDeviceId;
Version mVersion; Version mVersion;
bool mWildcard; bool mWildcard = true;
}; };
// This encapsulates a device, and potentially the device's model and/or a list of GPUs/drivers // This encapsulates a device, and potentially the device's model and/or a list of GPUs/drivers
...@@ -529,58 +479,51 @@ class GPU ...@@ -529,58 +479,51 @@ class GPU
class Device class Device
{ {
public: public:
Device(const std::string manufacturer, const std::string model) Device(StringPart manufacturer, StringPart model)
: mManufacturer(manufacturer), mModel(model), mGpuList("GPU"), mWildcard(false) : mManufacturer(std::move(manufacturer)),
mModel(std::move(model)),
mGpuList("GPU"),
mWildcard(false)
{} {}
Device(const std::string manufacturer) Device() : mGpuList("GPU") {}
: mManufacturer(manufacturer), mModel(), mGpuList("GPU"), mWildcard(false) ~Device() = default;
{}
Device() : mManufacturer(), mModel(), mGpuList("GPU"), mWildcard(true) {}
~Device() {}
static Device *CreateDeviceFromJson(const Json::Value &jObject) static Device FromJson(const Json::Value &jObject)
{
Device *device = nullptr;
if (jObject.isMember(kJsonManufacturer) && jObject[kJsonManufacturer].isString())
{ {
std::string manufacturerName = jObject[kJsonManufacturer].asString(); auto manufacturer = StringPart::FromJson(jObject, kJsonManufacturer);
// We don't let a model be specified without also specifying an Manufacturer: if (!manufacturer.mWildcard)
if (jObject.isMember(kJsonModel) && jObject[kJsonModel].isString())
{ {
std::string model = jObject[kJsonModel].asString(); // We don't let a model be specified without also specifying a manufacturer:
device = new Device(manufacturerName, model); auto model = StringPart::FromJson(jObject, kJsonModel);
} return Device(std::move(manufacturer), std::move(model));
else
{
device = new Device(manufacturerName);
}
} }
else
{
// This case is not treated as an error because a rule may wish to only call out one or // This case is not treated as an error because a rule may wish to only call out one or
// more GPUs, but not any specific Manufacturer (e.g. for any manufacturer's device // more GPUs, but not any specific manufacturer (e.g. for any manufacturer's device
// that uses a GPU from Vendor-A, with DeviceID-Foo, and with driver version 1.2.3.4): // that uses a GPU from Vendor-A, with DeviceID-Foo, and with driver version 1.2.3.4):
device = new Device(); return Device();
}
return device;
} }
void addGPU(const GPU &gpu) { mGpuList.addItem(gpu); } void addGPU(GPU &&gpu) { mGpuList.addItem(std::move(gpu)); }
bool match(const Device &toCheck) const bool match(const Device &toCheck) const
{ {
VERBOSE("\t Within Device match: wildcards are %s and %s,\n", mWildcard ? "true" : "false", // GPU lists must always match, even when wildcards are used.
toCheck.mWildcard ? "true" : "false"); VERBOSE("\t Checking ListOf<GPU>:\n");
if (!(mWildcard || toCheck.mWildcard)) if (!mGpuList.match(toCheck.mGpuList))
{
VERBOSE("\t Failed to match due to mismatched GPU list.\n");
return false;
}
if (mWildcard || toCheck.mWildcard)
{
VERBOSE("\t Matching due to wildcard.\n");
return true;
}
if (toCheck.mManufacturer.match(mManufacturer) && toCheck.mModel.match(mModel))
{ {
VERBOSE("\t Manufacturer match is %s, model is %s\n", VERBOSE("\t Matching due to manufacturer and model match.\n");
toCheck.mManufacturer.match(mManufacturer) ? "true" : "false", return true;
toCheck.mModel.match(mModel) ? "true" : "false");
} }
VERBOSE("\t Need to check ListOf<GPU>\n"); return false;
return ((mWildcard || toCheck.mWildcard ||
// The wildcards can override the Manufacturer/Model check, but not the GPU check
(toCheck.mManufacturer.match(mManufacturer) && toCheck.mModel.match(mModel))) &&
mGpuList.match(toCheck.mGpuList));
} }
void logItem() const void logItem() const
{ {
...@@ -588,14 +531,14 @@ class Device ...@@ -588,14 +531,14 @@ class Device
{ {
if (mGpuList.mWildcard) if (mGpuList.mWildcard)
{ {
VERBOSE(" Wildcard (i.e. will match all devices)"); VERBOSE(" Wildcard (i.e. will match all devices)\n");
return; return;
} }
else else
{ {
VERBOSE( VERBOSE(
" Device with any manufacturer and model" " Device with any manufacturer and model"
", and with the following GPUs:"); ", and with the following GPUs:\n");
} }
} }
else else
...@@ -604,14 +547,14 @@ class Device ...@@ -604,14 +547,14 @@ class Device
{ {
VERBOSE( VERBOSE(
" Device manufacturer: \"%s\" and model \"%s\"" " Device manufacturer: \"%s\" and model \"%s\""
", and with the following GPUs:", ", and with the following GPUs:\n",
mManufacturer.mPart.c_str(), mModel.mPart.c_str()); mManufacturer.mPart.c_str(), mModel.mPart.c_str());
} }
else else
{ {
VERBOSE( VERBOSE(
" Device manufacturer: \"%s\"" " Device manufacturer: \"%s\""
", and with the following GPUs:", ", and with the following GPUs:\n",
mManufacturer.mPart.c_str()); mManufacturer.mPart.c_str());
} }
} }
...@@ -622,7 +565,7 @@ class Device ...@@ -622,7 +565,7 @@ class Device
StringPart mManufacturer; StringPart mManufacturer;
StringPart mModel; StringPart mModel;
ListOf<GPU> mGpuList; ListOf<GPU> mGpuList;
bool mWildcard; bool mWildcard = true;
}; };
// This encapsulates a particular scenario to check against the rules. A Scenario is similar to a // This encapsulates a particular scenario to check against the rules. A Scenario is similar to a
...@@ -633,15 +576,16 @@ class Scenario ...@@ -633,15 +576,16 @@ class Scenario
{ {
public: public:
Scenario(const char *appName, const char *deviceMfr, const char *deviceModel) Scenario(const char *appName, const char *deviceMfr, const char *deviceModel)
: mApplication(Application(appName)), mDevice(Device(deviceMfr, deviceModel)) : mApplication(Application(StringPart(appName))),
mDevice(Device(StringPart(deviceMfr), StringPart(deviceModel)))
{} {}
~Scenario() {} ~Scenario() = default;
void logScenario() void logScenario()
{ {
VERBOSE(" Scenario to compare against the rules"); VERBOSE(" Scenario to compare against the rules:\n");
VERBOSE(" Application:"); VERBOSE(" Application:\n");
mApplication.logItem(); mApplication.logItem();
VERBOSE(" Device:"); VERBOSE(" Device:\n");
mDevice.logItem(); mDevice.logItem();
} }
...@@ -662,20 +606,29 @@ class Rule ...@@ -662,20 +606,29 @@ class Rule
mDevList("Device"), mDevList("Device"),
mUseANGLE(useANGLE) mUseANGLE(useANGLE)
{} {}
~Rule() {} ~Rule() = default;
void addApp(const Application &app) { mAppList.addItem(app); } void addApp(Application &&app) { mAppList.addItem(std::move(app)); }
void addDevice(const Device &dev) { mDevList.addItem(dev); } void addDevice(Device &&dev) { mDevList.addItem(std::move(dev)); }
bool match(const Scenario &toCheck) const bool match(const Scenario &toCheck) const
{ {
VERBOSE(" Within \"%s\" Rule: application match is %s and device match is %s\n", VERBOSE(" Matching rule \"%s\" against scenario:\n", mDescription.c_str());
mDescription.c_str(), mAppList.match(toCheck.mApplication) ? "true" : "false", if (!mAppList.match(toCheck.mApplication))
mDevList.match(toCheck.mDevice) ? "true" : "false"); {
return (mAppList.match(toCheck.mApplication) && mDevList.match(toCheck.mDevice)); VERBOSE("\tFailed to match rule due to mismatched application.\n");
return false;
}
if (!mDevList.match(toCheck.mDevice))
{
VERBOSE("\tFailed to match rule due to mismatched device.\n");
return false;
}
VERBOSE("\tSuccessfully matched rule.");
return true;
} }
bool getUseANGLE() const { return mUseANGLE; } bool getUseANGLE() const { return mUseANGLE; }
void logRule() const void logRule() const
{ {
VERBOSE(" Rule: \"%s\" %s ANGLE", mDescription.c_str(), VERBOSE(" Rule: \"%s\" %s ANGLE\n", mDescription.c_str(),
mUseANGLE ? "enables" : "disables"); mUseANGLE ? "enables" : "disables");
mAppList.logListOf(" ", "Applications"); mAppList.logListOf(" ", "Applications");
mDevList.logListOf(" ", "Devices"); mDevList.logListOf(" ", "Devices");
...@@ -701,90 +654,93 @@ class RuleList ...@@ -701,90 +654,93 @@ class RuleList
RuleList *rules = new RuleList; RuleList *rules = new RuleList;
// Open the file and start parsing it: // Open the file and start parsing it:
Json::Reader jReader; Json::CharReaderBuilder builder;
// Json::CharReaderBuilder::strictMode(&builder.settings_);
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::Value jTopLevelObject; Json::Value jTopLevelObject;
jReader.parse(jsonFileContents, jTopLevelObject); std::string errorMessage;
Json::Value jRules = jTopLevelObject[kJsonRules]; const bool succeeded = reader->parse(&*jsonFileContents.begin(), &*jsonFileContents.end(),
for (unsigned int ruleIndex = 0; ruleIndex < jRules.size(); ruleIndex++) &jTopLevelObject, &errorMessage);
if (!succeeded)
{
VERBOSE("Failed to parse rules from json file. Error: %s\n", errorMessage.c_str());
return nullptr;
}
for (const auto &jRule : jTopLevelObject[kJsonRules])
{ {
Json::Value jRule = jRules[ruleIndex];
std::string ruleDescription = jRule[kJsonRule].asString(); std::string ruleDescription = jRule[kJsonRule].asString();
bool useANGLE = jRule[kJsonUseANGLE].asBool(); bool useANGLE = jRule[kJsonUseANGLE].asBool();
Rule *newRule = new Rule(ruleDescription, useANGLE); Rule newRule(std::move(ruleDescription), useANGLE);
Json::Value jApps = jRule[kJsonApplications]; for (const auto &jApp : jRule[kJsonApplications])
for (unsigned int appIndex = 0; appIndex < jApps.size(); appIndex++)
{ {
Json::Value jApp = jApps[appIndex]; Application app;
Application *newApp = Application::CreateApplicationFromJson(jApp); if (Application::FromJson(jApp, &app))
newRule->addApp(*newApp); {
delete newApp; newRule.addApp(std::move(app));
}
} }
Json::Value jDevs = jRule[kJsonDevices]; for (const auto &jDev : jRule[kJsonDevices])
for (unsigned int deviceIndex = 0; deviceIndex < jDevs.size(); deviceIndex++)
{ {
Json::Value jDev = jDevs[deviceIndex]; Device newDev = Device::FromJson(jDev);
Device *newDev = Device::CreateDeviceFromJson(jDev); for (const auto &jGPU : jDev[kJsonGPUs])
Json::Value jGPUs = jDev[kJsonGPUs];
for (unsigned int gpuIndex = 0; gpuIndex < jGPUs.size(); gpuIndex++)
{ {
Json::Value jGPU = jGPUs[gpuIndex]; GPU newGPU;
GPU *newGPU = GPU::CreateGpuFromJson(jGPU); if (GPU::CreateGpuFromJson(jGPU, &newGPU))
if (newGPU)
{ {
newDev->addGPU(*newGPU); newDev.addGPU(std::move(newGPU));
delete newGPU;
} }
} }
newRule->addDevice(*newDev); newRule.addDevice(std::move(newDev));
delete newDev;
} }
rules->addRule(*newRule); rules->addRule(std::move(newRule));
delete newRule;
} }
// Make sure there is at least one, default rule. If not, add it here: // Make sure there is at least one, default rule. If not, add it here:
if (rules->mRuleList.size() == 0) if (rules->mRuleList.empty())
{ {
Rule defaultRule("Default Rule", false); Rule defaultRule("Default Rule", false);
rules->addRule(defaultRule); rules->addRule(std::move(defaultRule));
} }
return rules; return rules;
} }
void addRule(const Rule &rule) { mRuleList.push_back(rule); } void addRule(Rule &&rule) { mRuleList.push_back(std::move(rule)); }
bool getUseANGLE(const Scenario &toCheck) bool getUseANGLE(const Scenario &toCheck)
{ {
// Initialize useANGLE to the system-wide default (that should be set in the default // Initialize useANGLE to the system-wide default (that should be set in the default
// rule, but just in case, set it here too): // rule, but just in case, set it here too):
bool useANGLE = false; bool useANGLE = false;
VERBOSE("Checking scenario against %d ANGLE-for-Android rules:", VERBOSE("Checking scenario against %d ANGLE-for-Android rules:\n",
static_cast<int>(mRuleList.size())); static_cast<int>(mRuleList.size()));
for (const Rule &rule : mRuleList) for (const Rule &rule : mRuleList)
{ {
VERBOSE(" Checking Rule: \"%s\" (to see whether there's a match)", VERBOSE(" Checking Rule: \"%s\" (to see whether there's a match)\n",
rule.mDescription.c_str()); rule.mDescription.c_str());
if (rule.match(toCheck)) if (rule.match(toCheck))
{ {
VERBOSE(" -> Rule matches. Setting useANGLE to %s", VERBOSE(" -> Rule matches. Updating useANGLE to %s.\n",
rule.getUseANGLE() ? "true" : "false"); rule.getUseANGLE() ? "true" : "false");
// The ANGLE rules are ordered from least to greatest specificity, meaning that
// the last rule with a match should dictate whether or not ANGLE should be
// recommended for use.
useANGLE = rule.getUseANGLE(); useANGLE = rule.getUseANGLE();
} }
else else
{ {
VERBOSE(" -> Rule doesn't match."); VERBOSE(" -> Rule doesn't match.\n");
} }
} }
return useANGLE; return useANGLE;
} }
void logRules() void logRules()
{ {
VERBOSE("Showing %d ANGLE-for-Android rules:", static_cast<int>(mRuleList.size())); VERBOSE("Showing %d ANGLE-for-Android rules:\n", static_cast<int>(mRuleList.size()));
for (const Rule &rule : mRuleList) for (const Rule &rule : mRuleList)
{ {
rule.logRule(); rule.logRule();
...@@ -831,6 +787,11 @@ ANGLE_EXPORT bool ANGLEAndroidParseRulesString(const char *rulesString, ...@@ -831,6 +787,11 @@ ANGLE_EXPORT bool ANGLEAndroidParseRulesString(const char *rulesString,
std::string rulesFileContents = rulesString; std::string rulesFileContents = rulesString;
RuleList *rules = RuleList::ReadRulesFromJsonString(rulesFileContents); RuleList *rules = RuleList::ReadRulesFromJsonString(rulesFileContents);
if (!rules)
{
return false;
}
rules->logRules(); rules->logRules();
*rulesHandle = rules; *rulesHandle = rules;
...@@ -894,12 +855,13 @@ ANGLE_EXPORT bool ANGLEShouldBeUsedForApplication(const RulesHandle rulesHandle, ...@@ -894,12 +855,13 @@ ANGLE_EXPORT bool ANGLEShouldBeUsedForApplication(const RulesHandle rulesHandle,
systemInfo->gpus[0].detailedDriverVersion.minor, systemInfo->gpus[0].detailedDriverVersion.minor,
systemInfo->gpus[0].detailedDriverVersion.subMinor, systemInfo->gpus[0].detailedDriverVersion.subMinor,
systemInfo->gpus[0].detailedDriverVersion.patch); systemInfo->gpus[0].detailedDriverVersion.patch);
GPU gpuDriver(systemInfo->gpus[0].driverVendor, systemInfo->gpus[0].deviceId, gpuDriverVersion); GPU gpuDriver(systemInfo->gpus[0].driverVendor, systemInfo->gpus[0].deviceId,
scenario.mDevice.addGPU(gpuDriver); std::move(gpuDriverVersion));
scenario.mDevice.addGPU(std::move(gpuDriver));
scenario.logScenario(); scenario.logScenario();
bool rtn = rules->getUseANGLE(scenario); bool rtn = rules->getUseANGLE(std::move(scenario));
VERBOSE("Application \"%s\" should %s ANGLE", appName, rtn ? "use" : "NOT use"); VERBOSE("Application \"%s\" should %s ANGLE.\n", appName, rtn ? "use" : "NOT use");
return rtn; return rtn;
} }
......
...@@ -131,7 +131,7 @@ TEST_F(FeatureSupportUtilTest, TestRuleProcessing) ...@@ -131,7 +131,7 @@ TEST_F(FeatureSupportUtilTest, TestRuleProcessing)
{ {
"Vendor" : "GPUVendorA", "Vendor" : "GPUVendorA",
"DeviceId" : 234, "DeviceId" : 234,
"VerMajor" : 1, "VerMinor" : 2, "VerSubMinor" : 3, "VerPatch" : 4} "VerMajor" : 1, "VerMinor" : 2, "VerSubMinor" : 3, "VerPatch" : 4
} }
] ]
} }
......
...@@ -128,20 +128,16 @@ void DumpTraceEventsToJSONFile(const std::vector<TraceEvent> &traceEvents, ...@@ -128,20 +128,16 @@ void DumpTraceEventsToJSONFile(const std::vector<TraceEvent> &traceEvents,
{ {
Json::Value value(Json::objectValue); Json::Value value(Json::objectValue);
std::stringstream phaseName; const auto microseconds = static_cast<Json::LargestInt>(traceEvent.timestamp) * 1000 * 1000;
phaseName << traceEvent.phase;
const auto microseconds =
static_cast<Json::LargestInt>(traceEvent.timestamp * 1000.0 * 1000.0);
value["name"] = traceEvent.name; value["name"] = traceEvent.name;
value["cat"] = traceEvent.categoryName; value["cat"] = traceEvent.categoryName;
value["ph"] = phaseName.str(); value["ph"] = std::string(1, traceEvent.phase);
value["ts"] = microseconds; value["ts"] = microseconds;
value["pid"] = strcmp(traceEvent.categoryName, "gpu.angle.gpu") == 0 ? "GPU" : "ANGLE"; value["pid"] = strcmp(traceEvent.categoryName, "gpu.angle.gpu") == 0 ? "GPU" : "ANGLE";
value["tid"] = 1; value["tid"] = 1;
eventsValue.append(value); eventsValue.append(std::move(value));
} }
Json::Value root(Json::objectValue); Json::Value root(Json::objectValue);
...@@ -150,8 +146,10 @@ void DumpTraceEventsToJSONFile(const std::vector<TraceEvent> &traceEvents, ...@@ -150,8 +146,10 @@ void DumpTraceEventsToJSONFile(const std::vector<TraceEvent> &traceEvents,
std::ofstream outFile; std::ofstream outFile;
outFile.open(outputFileName); outFile.open(outputFileName);
Json::StyledWriter styledWrite; Json::StreamWriterBuilder factory;
outFile << styledWrite.write(root); std::unique_ptr<Json::StreamWriter> const writer(factory.newStreamWriter());
std::ostringstream stream;
writer->write(root, &outFile);
outFile.close(); outFile.close();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment