forked from PixarAnimationStudios/OpenUSD
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathfileFormat.h
345 lines (291 loc) · 13.6 KB
/
fileFormat.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
//
// Copyright 2016 Pixar
//
// Licensed under the Apache License, Version 2.0 (the "Apache License")
// with the following modification; you may not use this file except in
// compliance with the Apache License and the following modification to it:
// Section 6. Trademarks. is deleted and replaced with:
//
// 6. Trademarks. This License does not grant permission to use the trade
// names, trademarks, service marks, or product names of the Licensor
// and its affiliates, except as required to comply with Section 4(c) of
// the License and to reproduce the content of the NOTICE file.
//
// You may obtain a copy of the Apache License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the Apache License with the above modification is
// distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the Apache License for the specific
// language governing permissions and limitations under the Apache License.
//
#ifndef SDF_FILE_FORMAT_H
#define SDF_FILE_FORMAT_H
/// \file sdf/fileFormat.h
#include "pxr/usd/sdf/declareHandles.h"
#include "pxr/base/tf/declarePtrs.h"
#include "pxr/base/tf/refBase.h"
#include "pxr/base/tf/staticTokens.h"
#include "pxr/base/tf/token.h"
#include "pxr/base/tf/type.h"
#include "pxr/base/tf/weakBase.h"
#include <boost/noncopyable.hpp>
#include <map>
#include <string>
#include <vector>
class ArAssetInfo;
SDF_DECLARE_HANDLES(SdfLayer);
SDF_DECLARE_HANDLES(SdfSpec);
TF_DECLARE_WEAK_AND_REF_PTRS(SdfAbstractData);
TF_DECLARE_WEAK_AND_REF_PTRS(SdfLayerBase);
TF_DECLARE_WEAK_AND_REF_PTRS(SdfFileFormat);
#define SDF_FILE_FORMAT_TOKENS \
((TargetArg, "target"))
TF_DECLARE_PUBLIC_TOKENS(SdfFileFormatTokens, SDF_FILE_FORMAT_TOKENS);
/// \class SdfFileFormat
///
/// Base class for file format implementations.
///
class SdfFileFormat : public TfRefBase, public TfWeakBase, boost::noncopyable
{
public:
/// Returns the format identifier.
const TfToken& GetFormatId() const;
/// Returns the target for this file format.
const TfToken& GetTarget() const;
/// Returns the cookie to be used when writing files with this format.
const std::string& GetFileCookie() const;
/// Returns the current version of this file format.
const TfToken& GetVersionString() const;
/// Returns true if this file format is the primary format for the
/// extensions it handles.
bool IsPrimaryFormatForExtensions() const;
/// Returns a list of extensions that this format supports.
const std::vector<std::string>& GetFileExtensions() const;
/// Returns the primary file extension for this format. This is the
/// extension that is reported for layers using this file format.
const std::string& GetPrimaryFileExtension() const;
/// Returns true if \p extension matches one of the extensions returned by
/// GetFileExtensions.
bool IsSupportedExtension(const std::string& extension) const;
/// Type for specifying additional file format-specific arguments
/// to the various API below.
typedef std::map<std::string, std::string> FileFormatArguments;
/// Returns the FileFormatArguments that correspond to the default behavior
/// of this file format when no FileFormatArguments are passed to NewLayer
/// or InitData.
virtual FileFormatArguments GetDefaultFileFormatArguments() const;
/// This method allows the file format to bind to whatever data container is
/// appropriate.
///
/// Returns a shared pointer to an SdfAbstractData implementation.
virtual SdfAbstractDataRefPtr InitData(const FileFormatArguments& args) const;
/// Instantiate a layer.
SdfLayerBaseRefPtr NewLayer(const SdfFileFormatConstPtr &fileFormat,
const std::string &identifier,
const std::string &realPath,
const ArAssetInfo& assetInfo,
const FileFormatArguments &args) const;
/// Instantiate a layer of the SdfLayerBase subclass T. Issue an error and
/// return null if the created layer does not have dynamic type T.
template <class T>
TfRefPtr<T> NewLayer(const SdfFileFormatConstPtr &fileFormat,
const std::string &identifier,
const std::string &realPath,
const ArAssetInfo &assetInfo,
const FileFormatArguments &args) const {
SdfLayerBaseRefPtr l =
NewLayer(fileFormat, identifier, realPath, assetInfo, args);
if (TfRefPtr<T> ret = TfDynamic_cast<TfRefPtr<T> >(l))
return ret;
_IssueNewLayerFailError(l, typeid(T), identifier, realPath);
return TfRefPtr<T>();
}
/// Return true if this file format prefers to skip reloading anonymous
/// layers.
bool ShouldSkipAnonymousReload() const;
/// Return true if the the \p layer produced by this file format
/// streams its data to and from its serialized data store on demand.
///
/// Sdf will treat streaming layers differently to avoid pulling
/// in data unnecessarily. For example, reloading a streaming layer
/// will not perform fine-grained change notification, since doing
/// so would require the full contents of the layer to be loaded.
///
/// Edits to a streaming layer are assumed to immediately affect
/// the serialized data without an explicit call to SdfLayer::Save.
///
/// It is a coding error to call this function with a layer that was
/// not created with this file format.
bool IsStreamingLayer(const SdfLayerBase& layer) const;
/// Return true if layers produced by this file format are based
/// on physical files on disk. If so, this file format requires
/// layers to be serialized to and read from files on disk.
///
/// For file formats where this function returns true, when
/// opening a layer Sdf will fetch layers to the filesystem
/// via calls to ArResolver::FetchToLocalResolvedPath prior
/// to calling ReadFromFile.
///
/// This allows asset systems that do not store layers as individual
/// files to operate with file formats that require these files.
///
/// \sa ArResolver::Resolve
/// \sa ArResolver::FetchToLocalResolvedPath
bool LayersAreFileBased() const;
/// Returns true if \p file can be read by this format.
virtual bool CanRead(
const std::string& file) const = 0;
/// Reads data in the file at \p filePath into the layer \p layerBase. If
/// the file is successfully read, this method returns true. Otherwise,
/// false is returned and errors are posted.
///
/// \p metadataOnly is a flag that asks for only the layer metadata
//// to be read in, which can be much faster if that is all that is
/// required. Note that this is just a hint: some FileFormat readers
/// may disregard this flag and still fully populate the layer contents.
virtual bool ReadFromFile(
const SdfLayerBasePtr& layerBase,
const std::string& filePath,
bool metadataOnly) const = 0;
/// Writes the content in \p layerBase into the file at \p filePath. If the
/// content is successfully written, this method returns true. Otherwise,
/// false is returned and errors are posted. The default implementation
/// returns false.
virtual bool WriteToFile(
const SdfLayerBase* layerBase,
const std::string& filePath,
const std::string& comment = std::string(),
const FileFormatArguments& args = FileFormatArguments()) const;
/// Reads data in the string \p str into the layer \p layerBase. If
/// the file is successfully read, this method returns true. Otherwise,
/// false is returned and errors are posted.
virtual bool ReadFromString(
const SdfLayerBasePtr& layerBase,
const std::string& str) const;
/// Write the provided \p spec to \p out indented \p indent levels.
virtual bool WriteToStream(
const SdfSpecHandle &spec,
std::ostream& out,
size_t indent) const;
/// Writes the content in \p layerBase to the string \p str. This function
/// should write a textual representation of \p layerBase to the stream
/// that can be read back in via ReadFromString.
virtual bool WriteToString(
const SdfLayerBase* layerBase,
std::string* str,
const std::string& comment = std::string()) const;
/// Returns the file extension for path or file name \p s, without the
/// leading dot character.
static std::string GetFileExtension(const std::string& s);
/// Returns the file format instance with the specified \p formatId
/// identifier. If a format with a matching identifier is not found, this
/// returns a null file format pointer.
static SdfFileFormatConstPtr FindById(
const TfToken& formatId);
/// Returns the file format instance that supports the specified file \p
/// extension. If a format with a matching extension is not found, this
/// returns a null file format pointer.
///
/// An extension may be handled by multiple file formats, but each
/// with a different target. In such cases, if no \p target is specified,
/// the file format that is registered as the primary plugin will be
/// returned. Otherwise, the file format whose target matches \p target
/// will be returned.
static SdfFileFormatConstPtr FindByExtension(
const std::string& extension,
const std::string& target = std::string());
protected:
/// Constructor.
SdfFileFormat(
const TfToken& formatId,
const TfToken& versionString,
const TfToken& target,
const std::string& extensions);
/// Constructor.
SdfFileFormat(
const TfToken& formatId,
const TfToken& versionString,
const TfToken& target,
const std::vector<std::string> &extensions);
/// Destructor.
virtual ~SdfFileFormat();
//
// Minimally break layer encapsulation with the following methods. These
// methods are also intended to limit the need for SdLayer friendship with
// SdFileFormat child classes.
//
/// Swap the layers internal _data member with \p data.
static void _SwapLayerData(const SdfLayerHandle& layer,
SdfAbstractDataRefPtr& data);
/// Set the layers internal _data member to \p data.
static void _SetLayerData(const SdfLayerHandle& layer,
const SdfAbstractDataPtr& data);
/// Get the layers internal _data member.
static SdfAbstractDataConstPtr _GetLayerData(const SdfLayerHandle& layer);
/// Returns true if the layer is loading as a new layer.
static bool _LayerIsLoadingAsNew(const SdfLayerHandle& layer);
private:
virtual SdfLayerBase *_InstantiateNewLayer(
const SdfFileFormatConstPtr &fileFormat,
const std::string &identifier,
const std::string &realPath,
const ArAssetInfo& assetInfo,
const FileFormatArguments &args) const;
// File format subclasses may override this if they prefer not to skip
// reloading anonymous layers. Default implementation returns true.
virtual bool _ShouldSkipAnonymousReload() const;
// File format subclasses must override this to determine whether the
// given layer is streaming or not. The file format of \p layer is
// guaranteed to be an instance of this class.
virtual bool _IsStreamingLayer(const SdfLayerBase& layer) const = 0;
/// File format subclasses may override this to specify whether
/// their layers are backed by physical files on disk.
/// Default implementation returns true.
virtual bool _LayersAreFileBased() const;
// Helper to issue an error in case the method template NewLayer fails.
void _IssueNewLayerFailError(SdfLayerBaseRefPtr const &l,
std::type_info const &type,
std::string const &identifier,
std::string const &realPath) const;
const TfToken _formatId;
const TfToken _target;
const std::string _cookie;
const TfToken _versionString;
const std::vector<std::string> _extensions;
const bool _isPrimaryFormat;
};
/// Base file format factory.
class Sdf_FileFormatFactoryBase : public TfType::FactoryBase {
public:
virtual SdfFileFormatRefPtr New() const = 0;
};
/// Default file format factory.
template <typename T>
class Sdf_FileFormatFactory : public Sdf_FileFormatFactoryBase {
public:
virtual SdfFileFormatRefPtr New() const
{
return TfCreateRefPtr(new T);
}
};
/// Defines a file format and factory. This macro is intended for use in a
/// TfType registry function block. It defines a type for the first argument,
/// with optional bases as additional arguments, and adds a factory.
#define SDF_DEFINE_FILE_FORMAT(c, ...) \
TfType::Define<c BOOST_PP_COMMA_IF(TF_NUM_ARGS(__VA_ARGS__)) \
BOOST_PP_IF(TF_NUM_ARGS(__VA_ARGS__), \
TfType::Bases<__VA_ARGS__>, BOOST_PP_EMPTY) >() \
.SetFactory<Sdf_FileFormatFactory<c> >()
/// Defines a file format without a factory. This macro is intended for use in
/// a TfType registry function block. It defines a type for the first
/// argument, with optional bases as additional arguments.
#define SDF_DEFINE_ABSTRACT_FILE_FORMAT(c, ...) \
TfType::Define<c BOOST_PP_COMMA_IF(TF_NUM_ARGS(__VA_ARGS__)) \
BOOST_PP_IF(TF_NUM_ARGS(__VA_ARGS__), \
TfType::Bases<__VA_ARGS__>, BOOST_PP_EMPTY) >();
#define SDF_FILE_FORMAT_FACTORY_ACCESS \
template<typename T> friend class Sdf_FileFormatFactory
#endif // SDF_FILE_FORMAT_H