summaryrefslogtreecommitdiff
path: root/Runtime/Serialize/TransferFunctions/StreamedBinaryWrite.h
blob: b5d90744c25ea8407d17501c3229fd47df43c2b6 (plain)
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
#ifndef STREAMEDBINARYWRITE_H
#define STREAMEDBINARYWRITE_H

#include "Runtime/Serialize/TransferFunctions/TransferBase.h"
#include "Runtime/Serialize/CacheWrap.h"
#include "Runtime/Serialize/SwapEndianBytes.h"

template<bool kSwapEndianess>
class EXPORT_COREMODULE StreamedBinaryWrite : public TransferBase
{
	CachedWriter m_Cache;
	BuildTargetSelection m_Target;

	#if UNITY_EDITOR
	BuildUsageTag m_BuildUsageTag;
	#endif
	friend class MonoBehaviour;

public:

	CachedWriter& Init (int flags, BuildTargetSelection target);
	CachedWriter& Init (const CachedWriter& cachedWriter, int flags, BuildTargetSelection target, const BuildUsageTag& buildUsageTag);

	bool IsWriting ()                 { return true; }
	bool IsWritingPPtr ()             { return true; }
	bool NeedsInstanceIDRemapping ()          { return m_Flags & kNeedsInstanceIDRemapping; }
	bool ConvertEndianess ()          { return kSwapEndianess; }
	bool IsWritingGameReleaseData ()
	{
		return IsSerializingForGameRelease ();
	}
	bool IsBuildingTargetPlatform (BuildTargetPlatform platform)
	{
		#if UNITY_EDITOR
		if (platform == kBuildAnyPlayerData)
			return m_Target.platform >= kBuildValidPlayer;
		else
			return m_Target.platform == platform;
		#else
		return false;
		#endif
	}

	#if UNITY_EDITOR
	BuildUsageTag GetBuildUsage ()
	{
		return m_BuildUsageTag;
	}
	#endif

	BuildTargetSelection GetBuildingTarget () { return m_Target; }

	template<class T>
	void Transfer (T& data, const char* name, TransferMetaFlags metaFlag = kNoTransferFlags);

	template<class T>
	void TransferWithTypeString (T& data, const char* name, const char* typeName, TransferMetaFlags metaFlag = kNoTransferFlags);

	void EnableResourceImage (ActiveResourceImage targetResourceImage)
	{
		#if UNITY_EDITOR
		m_Cache.BeginResourceImage (targetResourceImage);
		#endif
	}

	/// In order to transfer typeless data (Read: transfer data real fast)
	/// Call TransferTypeless. You have to always do this. Even for a proxytransfer. Then when you want to access the datablock.
	/// Call TransferTypelessData
	/// On return:
	/// When reading bytesize will contain the size of the data block that should be read,
	/// when writing bytesize has to contain the size of the datablock.
	/// MarkerID will contain an marker which you have to give TransferTypelessData when you want to start the actual transfer.
	/// optional: A serializedFile will be seperated into two chunks. One is the normal object data. (It is assumed that they are all relatively small)
	/// So caching them makes a lot of sense. Big datachunks will be stored in another part of the file.
	/// They will not be cached but usually read directly into the allocated memory, probably reading them asynchronously
	void TransferTypeless (unsigned* byteSize, const char* name, TransferMetaFlags metaFlag = kNoTransferFlags);

	// markerID is the id that was given by TransferTypeless.
	// copyData is a pointer to where the data will be written or read from
	void TransferTypelessData (unsigned byteSize, void* copyData, int metaFlag = 0);

	bool GetTransferFileInfo(unsigned* position, const char** filePath) const;

	template<class T>
	void TransferBasicData (T& data);

	template<class T>
	void TransferPtr (bool, ReduceCopyData*){}

	template<class T>
	void TransferSTLStyleArray (T& data, TransferMetaFlags metaFlag = kNoTransferFlags);

	template<class T>
	void TransferSTLStyleMap (T& data, TransferMetaFlags metaFlag = kNoTransferFlags);

	void Align ();

	CachedWriter& GetCachedWriter() { return m_Cache; }
};



template<bool kSwapEndianess>
template<class T> inline
void StreamedBinaryWrite<kSwapEndianess>::TransferSTLStyleArray (T& data, TransferMetaFlags /*metaFlags*/)
{
	#if UNITY_EDITOR
	if (m_Cache.IsWritingResourceImage())
	{
		// Grab the offset where the resourceImage is currently at
		UInt32 offsetInResourceImage = m_Cache.GetPosition();

		// Write the actual data to the resource image
		typename T::iterator end = data.end ();
		for (typename T::iterator i = data.begin ();i != end;++i)
			Transfer (*i, "data");

		Assert (m_Cache.IsWritingResourceImage());
		m_Cache.EndResourceImage ();
		Assert (!m_Cache.IsWritingResourceImage());

		UInt32 size = data.size ();

		// Writ ethe size & offset to the serialized file
		Transfer (size, "ri_size");
		Transfer (offsetInResourceImage, "ri_offset");
	}
	else
	#endif
	{
		SInt32 size = data.size ();
		Transfer (size, "size");
		typename T::iterator end = data.end ();
		for (typename T::iterator i = data.begin ();i != end;++i)
			Transfer (*i, "data");
	}
}


template<bool kSwapEndianess>
template<class T> inline
void StreamedBinaryWrite<kSwapEndianess>::TransferSTLStyleMap (T& data, TransferMetaFlags)
{
	SInt32 size = data.size ();
	Transfer (size, "size");

	// maps value_type is: pair<const First, Second>
	// So we have to write to maps non-const value type
	typedef typename NonConstContainerValueType<T>::value_type non_const_value_type;

	typename T::iterator end = data.end ();
	for (typename T::iterator i = data.begin ();i != end;++i)
	{
		non_const_value_type& p = (non_const_value_type&)(*i);
		Transfer (p, "data");
	}
}

template<bool kSwapEndianess>
template<class T> inline
void StreamedBinaryWrite<kSwapEndianess>::Transfer (T& data, const char*, TransferMetaFlags)
{
	SerializeTraits<T>::Transfer (data, *this);
}

template<bool kSwapEndianess>
template<class T> inline
void StreamedBinaryWrite<kSwapEndianess>::TransferWithTypeString (T& data, const char*, const char*, TransferMetaFlags)
{
	SerializeTraits<T>::Transfer (data, *this);
}

template<bool kSwapEndianess>
template<class T> inline
void StreamedBinaryWrite<kSwapEndianess>::TransferBasicData (T& data)
{
	if (kSwapEndianess)
	{
		T temp = data;
		SwapEndianBytes (temp);
		m_Cache.Write (temp);
	}
	else
		m_Cache.Write (data);
}

#endif