1 #include "stdafx.h"
2 #include <algorithm>
3 #include "Snapshotable.h"
4 #include "SaveStateManager.h"
5 
StreamStartBlock()6 void Snapshotable::StreamStartBlock()
7 {
8 	if(_inBlock) {
9 		throw new std::runtime_error("Cannot start a new block before ending the last block");
10 	}
11 
12 	if(!_saving) {
13 		InternalStream(_blockSize);
14 		_blockSize = std::min(_blockSize, (uint32_t)0xFFFFF);
15 		_blockBuffer = new uint8_t[_blockSize];
16 		ArrayInfo<uint8_t> arrayInfo = { _blockBuffer, _blockSize };
17 		InternalStream(arrayInfo);
18 	} else {
19 		_blockSize = 0x100;
20 		_blockBuffer = new uint8_t[_blockSize];
21 	}
22 	_blockPosition = 0;
23 	_inBlock = true;
24 }
25 
StreamEndBlock()26 void Snapshotable::StreamEndBlock()
27 {
28 	_inBlock = false;
29 	if(_saving) {
30 		InternalStream(_blockPosition);
31 		ArrayInfo<uint8_t> arrayInfo = { _blockBuffer, _blockPosition };
32 		InternalStream(arrayInfo);
33 	}
34 
35 	delete[] _blockBuffer;
36 	_blockBuffer = nullptr;
37 }
38 
Stream(Snapshotable * snapshotable)39 void Snapshotable::Stream(Snapshotable* snapshotable)
40 {
41 	stringstream stream;
42 	if(_saving) {
43 		snapshotable->SaveSnapshot(&stream);
44 		uint32_t size = (uint32_t)stream.tellp();
45 		stream.seekg(0, ios::beg);
46 		stream.seekp(0, ios::beg);
47 
48 		uint8_t *buffer = new uint8_t[size];
49 		stream.read((char*)buffer, size);
50 		InternalStream(size);
51 		ArrayInfo<uint8_t> arrayInfo = { buffer, size };
52 		InternalStream(arrayInfo);
53 		delete[] buffer;
54 	} else {
55 		uint32_t size = 0;
56 		InternalStream(size);
57 
58 		uint8_t *buffer = new uint8_t[size];
59 		ArrayInfo<uint8_t> arrayInfo = { buffer, size };
60 		InternalStream(arrayInfo);
61 
62 		stream.write((char*)buffer, size);
63 		stream.seekg(0, ios::beg);
64 		stream.seekp(0, ios::beg);
65 		snapshotable->LoadSnapshot(&stream, _stateVersion);
66 		delete[] buffer;
67 	}
68 }
69 
SaveSnapshot(ostream * file)70 void Snapshotable::SaveSnapshot(ostream* file)
71 {
72 	_stateVersion = SaveStateManager::FileFormatVersion;
73 
74 	_streamSize = 0x1000;
75 	_stream = new uint8_t[_streamSize];
76 	_position = 0;
77 	_saving = true;
78 
79 	StreamState(_saving);
80 	file->write((char*)&_position, sizeof(_position));
81 	file->write((char*)_stream, _position);
82 
83 	delete[] _stream;
84 
85 	if(_blockBuffer) {
86 		throw new std::runtime_error("A call to StreamEndBlock is missing.");
87 	}
88 }
89 
LoadSnapshot(istream * file,uint32_t stateVersion)90 void Snapshotable::LoadSnapshot(istream* file, uint32_t stateVersion)
91 {
92 	_stateVersion = stateVersion;
93 
94 	_position = 0;
95 	_saving = false;
96 
97 	file->read((char*)&_streamSize, sizeof(_streamSize));
98 	_stream = new uint8_t[_streamSize];
99 	file->read((char*)_stream, _streamSize);
100 	StreamState(_saving);
101 
102 	delete[] _stream;
103 
104 	if(_blockBuffer) {
105 		throw new std::runtime_error("A call to StreamEndBlock is missing.");
106 	}
107 }
108 
WriteEmptyBlock(ostream * file)109 void Snapshotable::WriteEmptyBlock(ostream* file)
110 {
111 	int blockSize = 0;
112 	file->write((char*)&blockSize, sizeof(blockSize));
113 }
114 
SkipBlock(istream * file)115 void Snapshotable::SkipBlock(istream* file)
116 {
117 	int blockSize = 0;
118 	file->read((char*)&blockSize, sizeof(blockSize));
119 	file->seekg(blockSize, ios::cur);
120 }