1 //
2 // Copyright 2016 Pixar
3 //
4 // Licensed under the Apache License, Version 2.0 (the "Apache License")
5 // with the following modification; you may not use this file except in
6 // compliance with the Apache License and the following modification to it:
7 // Section 6. Trademarks. is deleted and replaced with:
8 //
9 // 6. Trademarks. This License does not grant permission to use the trade
10 // names, trademarks, service marks, or product names of the Licensor
11 // and its affiliates, except as required to comply with Section 4(c) of
12 // the License and to reproduce the content of the NOTICE file.
13 //
14 // You may obtain a copy of the Apache License at
15 //
16 // http://www.apache.org/licenses/LICENSE-2.0
17 //
18 // Unless required by applicable law or agreed to in writing, software
19 // distributed under the Apache License with the above modification is
20 // distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21 // KIND, either express or implied. See the Apache License for the specific
22 // language governing permissions and limitations under the Apache License.
23 //
24
25 #include "pxr/imaging/hio/dictionary.h"
26
27 #include "pxr/base/js/converter.h"
28 #include "pxr/base/js/json.h"
29 #include "pxr/base/tf/debug.h"
30
31 PXR_NAMESPACE_OPEN_SCOPE
32
33
34 using namespace std;
35
36
37 TF_DEBUG_CODES(
38
39 HIO_DEBUG_DICTIONARY
40
41 );
42
43
TF_REGISTRY_FUNCTION(TfDebug)44 TF_REGISTRY_FUNCTION(TfDebug)
45 {
46 TF_DEBUG_ENVIRONMENT_SYMBOL(HIO_DEBUG_DICTIONARY,
47 "glslfx dictionary parsing");
48 }
49
50 static VtDictionary
_Hio_GetDictionaryFromJSON(const string & input,string * errorStr)51 _Hio_GetDictionaryFromJSON(
52 const string &input,
53 string *errorStr )
54 {
55 if (input.empty())
56 {
57 const char *errorMsg = "Cannot create VtDictionary from empty string";
58 TF_DEBUG(HIO_DEBUG_DICTIONARY).Msg("%s", errorMsg);
59
60 if( errorStr ) {
61 *errorStr = errorMsg;
62 }
63 return VtDictionary();
64 }
65
66 // Note Js library doesn't allow comments. Strip comments as we do
67 // for plugInfo files.
68 //
69 // XXX: This may not be worth the cost.
70 //
71 std::vector<std::string> filtered = TfStringSplit(input, "\n");
72 for (auto & line : filtered) {
73 // Clear comment lines but keep them to maintain line numbers for errors
74 if (line.find('#') < line.find_first_not_of(" \t#"))
75 line.clear();
76 }
77
78 JsParseError error;
79 JsValue jsdict = JsParseString(TfStringJoin(filtered, "\n"), &error);
80
81 if (jsdict.IsNull()) {
82 if (errorStr || TfDebug::IsEnabled(HIO_DEBUG_DICTIONARY)) {
83 std::string errorMessageStr = TfStringPrintf(
84 "Failed to extract dictionary from input (line %d, col %d): %s",
85 error.line, error.column, error.reason.c_str());
86 if (errorStr) {
87 *errorStr = errorMessageStr;
88 }
89 TF_DEBUG(HIO_DEBUG_DICTIONARY).Msg("%s", errorMessageStr.c_str());
90 }
91 return VtDictionary();
92 }
93
94 if (!jsdict.IsObject()) {
95 if (errorStr || TfDebug::IsEnabled(HIO_DEBUG_DICTIONARY)) {
96 std::string errorMessageStr = TfStringPrintf(
97 "Input string did not evaluate to a JSON dictionary:\n%s\n",
98 input.c_str());
99 if (errorStr) {
100 *errorStr = errorMessageStr;
101 }
102 TF_DEBUG(HIO_DEBUG_DICTIONARY).Msg("%s", errorMessageStr.c_str());
103 }
104 return VtDictionary();
105 }
106
107 const VtValue vtdict =
108 JsValueTypeConverter<VtValue, VtDictionary, /*UseInt64*/false>::Convert(jsdict);
109 return vtdict.IsHolding<VtDictionary>() ?
110 vtdict.UncheckedGet<VtDictionary>() : VtDictionary();
111 }
112
113
114 VtDictionary
Hio_GetDictionaryFromInput(const string & input,const string & filename,string * errorStr)115 Hio_GetDictionaryFromInput(
116 const string &input,
117 const string &filename,
118 string *errorStr )
119 {
120 std::string jsError;
121 VtDictionary ret = _Hio_GetDictionaryFromJSON(input, &jsError);
122
123 if (jsError.empty()) {
124 // JSON succeeded, great, we're done.
125 return ret;
126 }
127
128 // If the file has errors, report the errors from JSON as that is the new
129 // format that we're expected to conform to.
130 if (errorStr) {
131 *errorStr = jsError;
132 }
133 return VtDictionary();
134 }
135
136 PXR_NAMESPACE_CLOSE_SCOPE
137
138