1 //
2 // Saved game helper.
3 //
4 
5 
6 #ifndef OJK_SAVED_GAME_HELPER_INCLUDED
7 #define OJK_SAVED_GAME_HELPER_INCLUDED
8 
9 
10 #include <cstdint>
11 #include <type_traits>
12 #include "ojk_saved_game_helper_fwd.h"
13 #include "ojk_scope_guard.h"
14 #include "ojk_saved_game_class_archivers.h"
15 
16 
17 namespace ojk
18 {
19 
20 
21 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
22 // Class stuff
23 
SavedGameHelper(ISavedGame * saved_game)24 inline SavedGameHelper::SavedGameHelper(
25 	ISavedGame* saved_game) :
26 		saved_game_(saved_game)
27 {
28 }
29 
30 // Class stuff
31 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
32 
33 
34 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
35 // Public methods
36 
read_chunk(const uint32_t chunk_id)37 inline void SavedGameHelper::read_chunk(
38 	const uint32_t chunk_id)
39 {
40 	if (!saved_game_->read_chunk(
41 		chunk_id))
42 	{
43 		saved_game_->throw_error();
44 	}
45 }
46 
write_chunk(const uint32_t chunk_id)47 inline void SavedGameHelper::write_chunk(
48 	const uint32_t chunk_id)
49 {
50 	if (!saved_game_->write_chunk(
51 		chunk_id))
52 	{
53 		saved_game_->throw_error();
54 	}
55 }
56 
skip(int count)57 inline void SavedGameHelper::skip(
58 	int count)
59 {
60 	if (!saved_game_->skip(
61 		count))
62 	{
63 		saved_game_->throw_error();
64 	}
65 }
66 
get_buffer_data()67 inline const void* SavedGameHelper::get_buffer_data()
68 {
69 	return saved_game_->get_buffer_data();
70 }
71 
get_buffer_size()72 inline int SavedGameHelper::get_buffer_size() const
73 {
74 	return saved_game_->get_buffer_size();
75 }
76 
reset_buffer()77 inline void SavedGameHelper::reset_buffer()
78 {
79 	saved_game_->reset_buffer();
80 }
81 
reset_buffer_offset()82 inline void SavedGameHelper::reset_buffer_offset()
83 {
84 	saved_game_->reset_buffer_offset();
85 }
86 
ensure_all_data_read()87 inline void SavedGameHelper::ensure_all_data_read()
88 {
89 	saved_game_->ensure_all_data_read();
90 }
91 
is_failed()92 inline bool SavedGameHelper::is_failed() const
93 {
94 	return saved_game_->is_failed();
95 }
96 
97 // Public methods
98 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
99 
100 
101 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
102 // try_read_chunk
103 
try_read_chunk(const uint32_t chunk_id)104 inline bool SavedGameHelper::try_read_chunk(
105 	const uint32_t chunk_id)
106 {
107 	return saved_game_->read_chunk(
108 		chunk_id);
109 }
110 
111 template<typename TSrc, typename TDst>
try_read_chunk(const uint32_t chunk_id,TDst & dst_value)112 bool SavedGameHelper::try_read_chunk(
113 	const uint32_t chunk_id,
114 	TDst& dst_value)
115 {
116 	if (!saved_game_->read_chunk(
117 		chunk_id))
118 	{
119 		return false;
120 	}
121 
122 	if (!try_read<TSrc>(
123 		dst_value))
124 	{
125 		return false;
126 	}
127 
128 	return saved_game_->is_all_data_read();
129 }
130 
131 template<typename TSrc, typename TDst>
try_read_chunk(const uint32_t chunk_id,TDst * dst_values,int dst_count)132 bool SavedGameHelper::try_read_chunk(
133 	const uint32_t chunk_id,
134 	TDst* dst_values,
135 	int dst_count)
136 {
137 	if (!saved_game_->read_chunk(
138 		chunk_id))
139 	{
140 		return false;
141 	}
142 
143 	if (!try_read<TSrc>(
144 		dst_values,
145 		dst_count))
146 	{
147 		return false;
148 	}
149 
150 	return saved_game_->is_all_data_read();
151 }
152 
153 // try_read_chunk
154 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
155 
156 
157 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
158 // read_chunk
159 
160 template<typename TSrc, typename TDst>
read_chunk(const uint32_t chunk_id,TDst & dst_value)161 void SavedGameHelper::read_chunk(
162 	const uint32_t chunk_id,
163 	TDst& dst_value)
164 {
165 	if (!try_read_chunk<TSrc>(
166 		chunk_id,
167 		dst_value))
168 	{
169 		saved_game_->throw_error();
170 	}
171 }
172 
173 template<typename TSrc, typename TDst>
read_chunk(const uint32_t chunk_id,TDst * dst_values,int dst_count)174 void SavedGameHelper::read_chunk(
175 	const uint32_t chunk_id,
176 	TDst* dst_values,
177 	int dst_count)
178 {
179 	if (!try_read_chunk<TSrc>(
180 		chunk_id,
181 		dst_values,
182 		dst_count))
183 	{
184 		saved_game_->throw_error();
185 	}
186 }
187 
188 // read_chunk
189 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
190 
191 
192 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
193 // write_chunk
194 
195 template<typename TSize>
write_chunk_and_size(const uint32_t size_chunk_id,const uint32_t data_chunk_id)196 void SavedGameHelper::write_chunk_and_size(
197 	const uint32_t size_chunk_id,
198 	const uint32_t data_chunk_id)
199 {
200 	saved_game_->save_buffer();
201 
202 	const int data_size = saved_game_->get_buffer_size();
203 
204 	saved_game_->reset_buffer();
205 
206 	write_chunk<TSize>(
207 		size_chunk_id,
208 		data_size);
209 
210 	saved_game_->load_buffer();
211 
212 	saved_game_->write_chunk(
213 		data_chunk_id);
214 }
215 
216 template<typename TDst, typename TSrc>
write_chunk(const uint32_t chunk_id,const TSrc & src_value)217 void SavedGameHelper::write_chunk(
218 	const uint32_t chunk_id,
219 	const TSrc& src_value)
220 {
221 	saved_game_->reset_buffer();
222 
223 	write<TDst>(
224 		src_value);
225 
226 	saved_game_->write_chunk(
227 		chunk_id);
228 }
229 
230 template<typename TDst, typename TSrc>
write_chunk(const uint32_t chunk_id,const TSrc * src_values,int src_count)231 void SavedGameHelper::write_chunk(
232 	const uint32_t chunk_id,
233 	const TSrc* src_values,
234 	int src_count)
235 {
236 	saved_game_->reset_buffer();
237 
238 	write<TDst>(
239 		src_values,
240 		src_count);
241 
242 	saved_game_->write_chunk(
243 		chunk_id);
244 }
245 
246 // write_chunk
247 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
248 
249 
250 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
251 // try_read
252 
253 template<typename TSrc, typename TDst>
try_read(TDst & dst_value)254 bool SavedGameHelper::try_read(
255 	TDst& dst_value)
256 {
257 	using Tag = typename std::conditional <
258 		std::is_same<TDst, bool>::value,
259 		BooleanTag,
260 		typename std::conditional<
261 			std::is_arithmetic<TDst>::value || std::is_enum<TDst>::value,
262 			NumericTag,
263 			typename std::conditional<
264 				std::is_pointer<TDst>::value,
265 				PointerTag,
266 				typename std::conditional<
267 					std::is_class<TDst>::value,
268 					ClassTag,
269 					typename std::conditional<
270 						std::rank<TDst>::value == 1,
271 						Array1dTag,
272 						typename std::conditional<
273 							std::rank<TDst>::value == 2,
274 							Array2dTag,
275 							void
276 						>::type
277 					>::type
278 				>::type
279 			>::type
280 		>::type
281 	> ::type;
282 
283 	static_assert(
284 		!std::is_same<Tag, void>::value,
285 		"Unsupported type.");
286 
287 	return try_read<TSrc>(
288 		dst_value,
289 		Tag());
290 }
291 
292 // try_read
293 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
294 
295 
296 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
297 // read
298 
299 template<typename TSrc, typename TDst>
read(TDst & dst_value)300 void SavedGameHelper::read(
301 	TDst& dst_value)
302 {
303 	if (!try_read<TSrc>(
304 		dst_value))
305 	{
306 		saved_game_->throw_error();
307 	}
308 }
309 
310 template<typename TSrc, typename TDst>
try_read(TDst & dst_value,BooleanTag)311 bool SavedGameHelper::try_read(
312 	TDst& dst_value,
313 	BooleanTag)
314 {
315 	TSrc src_value;
316 
317 	if (!saved_game_->read(
318 		&src_value,
319 		static_cast<int>(sizeof(TSrc))))
320 	{
321 		return false;
322 	}
323 
324 	// FIXME Byte order
325 	//
326 
327 	dst_value = (src_value != 0);
328 
329 	return true;
330 }
331 
332 template<typename TSrc, typename TDst>
try_read(TDst & dst_value,NumericTag)333 bool SavedGameHelper::try_read(
334 	TDst& dst_value,
335 	NumericTag)
336 {
337 	const int src_size = static_cast<int>(sizeof(TSrc));
338 
339 	TSrc src_value;
340 
341 	if (!saved_game_->read(
342 		&src_value,
343 		src_size))
344 	{
345 		return false;
346 	}
347 
348 	// FIXME Byte order
349 	//
350 
351 	dst_value = static_cast<TDst>(src_value);
352 
353 	return true;
354 }
355 
356 template<typename TSrc, typename TDst>
try_read(TDst * & dst_value,PointerTag)357 bool SavedGameHelper::try_read(
358 	TDst*& dst_value,
359 	PointerTag)
360 {
361 	static_assert(
362 		std::is_arithmetic<TSrc>::value &&
363 			!std::is_same<TSrc, bool>::value,
364 		"Unsupported types.");
365 
366 	using DstNumeric = typename std::conditional<
367 		std::is_signed<TSrc>::value,
368 		std::intptr_t,
369 		std::uintptr_t
370 	>::type;
371 
372 	DstNumeric dst_number;
373 
374 	if (!try_read<TSrc>(
375 		dst_number,
376 		NumericTag()))
377 	{
378 		return false;
379 	}
380 
381 	dst_value = reinterpret_cast<TDst*>(dst_number);
382 
383 	return true;
384 }
385 
386 template<typename TSrc, typename TDst>
try_read(TDst & dst_value,ClassTag)387 bool SavedGameHelper::try_read(
388 	TDst& dst_value,
389 	ClassTag)
390 {
391 	static_assert(
392 		std::is_same<TSrc, void>::value,
393 		"Unsupported types.");
394 
395 	using Tag = typename std::conditional<
396 		SavedGameClassArchiver<TDst>::is_implemented,
397 		ExternalTag,
398 		InternalTag
399 	>::type;
400 
401 	return try_read<TSrc>(
402 		dst_value,
403 		ClassTag(),
404 		Tag());
405 }
406 
407 template<typename TSrc, typename TDst>
try_read(TDst & dst_value,ClassTag,InternalTag)408 bool SavedGameHelper::try_read(
409 	TDst& dst_value,
410 	ClassTag,
411 	InternalTag)
412 {
413 	dst_value.sg_import(
414 		*this);
415 
416 	return !saved_game_->is_failed();
417 }
418 
419 template<typename TSrc, typename TDst>
try_read(TDst & dst_value,ClassTag,ExternalTag)420 bool SavedGameHelper::try_read(
421 	TDst& dst_value,
422 	ClassTag,
423 	ExternalTag)
424 {
425 	SavedGameClassArchiver<TDst>::sg_import(
426 		*this,
427 		dst_value);
428 
429 	return !saved_game_->is_failed();
430 }
431 
432 template<typename TSrc, typename TDst, int TCount>
try_read(TDst (& dst_values)[TCount],Array1dTag)433 bool SavedGameHelper::try_read(
434 	TDst(&dst_values)[TCount],
435 	Array1dTag)
436 {
437 	return try_read<TSrc>(
438 		&dst_values[0],
439 		TCount);
440 }
441 
442 template<typename TSrc, typename TDst, int TCount1, int TCount2>
try_read(TDst (& dst_values)[TCount1][TCount2],Array2dTag)443 bool SavedGameHelper::try_read(
444 	TDst(&dst_values)[TCount1][TCount2],
445 	Array2dTag)
446 {
447 	return try_read<TSrc>(
448 		&dst_values[0][0],
449 		TCount1 * TCount2);
450 }
451 
452 // read
453 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
454 
455 
456 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
457 // try_read (C-array)
458 
459 template<typename TSrc, typename TDst>
try_read(TDst * dst_values,int dst_count)460 bool SavedGameHelper::try_read(
461 	TDst* dst_values,
462 	int dst_count)
463 {
464 	static_assert(
465 		std::is_arithmetic<TDst>::value ||
466 			std::is_enum<TDst>::value ||
467 			std::is_pointer<TDst>::value ||
468 			std::is_class<TDst>::value,
469 		"Unsupported types.");
470 
471 	using Src = typename std::conditional<
472 		std::is_same<TSrc, void>::value,
473 		TDst,
474 		TSrc
475 	>::type;
476 
477 	const bool is_src_pure_numeric =
478 		std::is_arithmetic<Src>::value &&
479 		(!std::is_same<Src, bool>::value) &&
480 		(!std::is_enum<Src>::value);
481 
482 	const bool is_dst_pure_numeric =
483 		std::is_arithmetic<TDst>::value &&
484 		(!std::is_same<TDst, bool>::value) &&
485 		(!std::is_enum<TDst>::value);
486 
487 	const bool is_src_float_point =
488 		std::is_floating_point<Src>::value;
489 
490 	const bool is_dst_float_point =
491 		std::is_floating_point<TDst>::value;
492 
493 	const bool has_same_size =
494 		(sizeof(Src) == sizeof(TDst));
495 
496 	const bool use_inplace =
497 		is_src_pure_numeric &&
498 		is_dst_pure_numeric &&
499 		((!is_src_float_point && !is_dst_float_point) ||
500 			(is_src_float_point && is_dst_float_point)) &&
501 		has_same_size;
502 
503 	using Tag = typename std::conditional<
504 		use_inplace,
505 		InplaceTag,
506 		CastTag
507 	>::type;
508 
509 	return try_read<TSrc>(
510 		dst_values,
511 		dst_count,
512 		Tag());
513 }
514 
515 // try_read (C-array)
516 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
517 
518 
519 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
520 // read (C-array)
521 
522 template<typename TSrc, typename TDst>
read(TDst * dst_values,int dst_count)523 void SavedGameHelper::read(
524 	TDst* dst_values,
525 	int dst_count)
526 {
527 	if (!try_read<TSrc>(
528 		dst_values,
529 		dst_count))
530 	{
531 		saved_game_->throw_error();
532 	}
533 }
534 
535 template<typename TSrc, typename TDst>
try_read(TDst * dst_values,int dst_count,InplaceTag)536 bool SavedGameHelper::try_read(
537 	TDst* dst_values,
538 	int dst_count,
539 	InplaceTag)
540 {
541 	const int dst_size = dst_count * static_cast<int>(sizeof(TDst));
542 
543 	if (!saved_game_->read(
544 		dst_values,
545 		dst_size))
546 	{
547 		return false;
548 	}
549 
550 	// FIXME Byte order
551 	//
552 
553 	return true;
554 }
555 
556 template<typename TSrc, typename TDst>
try_read(TDst * dst_values,int dst_count,CastTag)557 bool SavedGameHelper::try_read(
558 	TDst* dst_values,
559 	int dst_count,
560 	CastTag)
561 {
562 	using Tag = typename std::conditional<
563 		std::is_arithmetic<TDst>::value ||
564 			std::is_enum<TDst>::value,
565 		NumericTag,
566 		typename std::conditional<
567 			std::is_pointer<TDst>::value,
568 			PointerTag,
569 			typename std::conditional<
570 				std::is_class<TDst>::value,
571 				ClassTag,
572 				void
573 			>::type
574 		>::type
575 	>::type;
576 
577 	for (int i = 0; i < dst_count; ++i)
578 	{
579 		if (!try_read<TSrc>(
580 			dst_values[i],
581 			Tag()))
582 		{
583 			return false;
584 		}
585 	}
586 
587 	return true;
588 }
589 
590 // read (C-array)
591 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
592 
593 
594 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
595 // write
596 
597 template<typename TDst, typename TSrc>
write(const TSrc & src_value)598 void SavedGameHelper::write(
599 	const TSrc& src_value)
600 {
601 	using Tag = typename std::conditional<
602 		std::is_arithmetic<TSrc>::value || std::is_enum<TSrc>::value,
603 		NumericTag,
604 		typename std::conditional<
605 			std::is_pointer<TSrc>::value,
606 			PointerTag,
607 			typename std::conditional<
608 				std::is_class<TSrc>::value,
609 				ClassTag,
610 				typename std::conditional<
611 					std::rank<TSrc>::value == 1,
612 					Array1dTag,
613 					typename std::conditional<
614 						std::rank<TSrc>::value == 2,
615 						Array2dTag,
616 						void
617 					>::type
618 				>::type
619 			>::type
620 		>::type
621 	>::type;
622 
623 	static_assert(
624 		!std::is_same<Tag, void>::value,
625 		"Unsupported type.");
626 
627 	write<TDst>(
628 		src_value,
629 		Tag());
630 }
631 
632 template<typename TDst, typename TSrc>
write(const TSrc & src_value,NumericTag)633 void SavedGameHelper::write(
634 	const TSrc& src_value,
635 	NumericTag)
636 {
637 	const int dst_size = static_cast<int>(sizeof(TDst));
638 
639 	const TDst dst_value = static_cast<TDst>(src_value);
640 
641 	// FIXME Byte order
642 	//
643 
644 	saved_game_->write(
645 		&dst_value,
646 		dst_size);
647 }
648 
649 template<typename TDst, typename TSrc>
write(const TSrc * src_value,PointerTag)650 void SavedGameHelper::write(
651 	const TSrc* src_value,
652 	PointerTag)
653 {
654 	using DstNumeric = typename std::conditional<
655 		std::is_signed<TSrc>::value,
656 		std::intptr_t,
657 		std::uintptr_t
658 	>::type;
659 
660 	const DstNumeric dst_number = reinterpret_cast<DstNumeric>(src_value);
661 
662 	write<TDst>(
663 		dst_number,
664 		NumericTag());
665 }
666 
667 template<typename TDst, typename TSrc>
write(const TSrc & src_value,ClassTag)668 void SavedGameHelper::write(
669 	const TSrc& src_value,
670 	ClassTag)
671 {
672 	static_assert(
673 		std::is_same<TDst, void>::value,
674 		"Unsupported types.");
675 
676 	using Tag = typename std::conditional<
677 		SavedGameClassArchiver<TSrc>::is_implemented,
678 		ExternalTag,
679 		InternalTag
680 	>::type;
681 
682 	write<TDst>(
683 		src_value,
684 		ClassTag(),
685 		Tag());
686 }
687 
688 template<typename TDst, typename TSrc>
write(const TSrc & src_value,ClassTag,InternalTag)689 void SavedGameHelper::write(
690 	const TSrc& src_value,
691 	ClassTag,
692 	InternalTag)
693 {
694 	src_value.sg_export(
695 		*this);
696 }
697 
698 template<typename TDst, typename TSrc>
write(const TSrc & src_value,ClassTag,ExternalTag)699 void SavedGameHelper::write(
700 	const TSrc& src_value,
701 	ClassTag,
702 	ExternalTag)
703 {
704 	SavedGameClassArchiver<TSrc>::sg_export(
705 		*this,
706 		src_value);
707 }
708 
709 template<typename TDst, typename TSrc, int TCount>
write(const TSrc (& src_values)[TCount],Array1dTag)710 void SavedGameHelper::write(
711 	const TSrc(&src_values)[TCount],
712 	Array1dTag)
713 {
714 	write<TDst>(
715 		&src_values[0],
716 		TCount);
717 }
718 
719 template<typename TDst, typename TSrc, int TCount1, int TCount2>
write(const TSrc (& src_values)[TCount1][TCount2],Array2dTag)720 void SavedGameHelper::write(
721 	const TSrc(&src_values)[TCount1][TCount2],
722 	Array2dTag)
723 {
724 	write<TDst>(
725 		&src_values[0][0],
726 		TCount1 * TCount2);
727 }
728 
729 // write
730 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
731 
732 
733 // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
734 // write (C-array)
735 
736 template<typename TDst, typename TSrc>
write(const TSrc * src_values,int src_count)737 void SavedGameHelper::write(
738 	const TSrc* src_values,
739 	int src_count)
740 {
741 	static_assert(
742 		std::is_arithmetic<TSrc>::value ||
743 			std::is_enum<TSrc>::value ||
744 			std::is_pointer<TSrc>::value ||
745 			std::is_class<TSrc>::value,
746 		"Unsupported types.");
747 
748 	using Dst = typename std::conditional<
749 		std::is_same<TDst, void>::value,
750 		TSrc,
751 		TDst>::type;
752 
753 	const bool is_src_pure_numeric =
754 		std::is_arithmetic<TSrc>::value &&
755 		(!std::is_same<TSrc, bool>::value) &&
756 		(!std::is_enum<TSrc>::value);
757 
758 	const bool is_dst_pure_numeric =
759 		std::is_arithmetic<Dst>::value &&
760 		(!std::is_same<Dst, bool>::value) &&
761 		(!std::is_enum<Dst>::value);
762 
763 	const bool is_src_float_point =
764 		std::is_floating_point<TSrc>::value;
765 
766 	const bool is_dst_float_point =
767 		std::is_floating_point<Dst>::value;
768 
769 	const bool has_same_size =
770 		(sizeof(TSrc) == sizeof(Dst));
771 
772 	const bool use_inplace =
773 		is_src_pure_numeric &&
774 		is_dst_pure_numeric &&
775 		((!is_src_float_point && !is_dst_float_point) ||
776 		(is_src_float_point && is_dst_float_point)) &&
777 		has_same_size;
778 
779 	using Tag = typename std::conditional<
780 		use_inplace,
781 		InplaceTag,
782 		CastTag
783 	>::type;
784 
785 	write<TDst>(
786 		src_values,
787 		src_count,
788 		Tag());
789 }
790 
791 template<typename TDst, typename TSrc>
write(const TSrc * src_values,int src_count,InplaceTag)792 void SavedGameHelper::write(
793 	const TSrc* src_values,
794 	int src_count,
795 	InplaceTag)
796 {
797 	const int src_size = src_count * static_cast<int>(sizeof(TSrc));
798 
799 	saved_game_->write(
800 		src_values,
801 		src_size);
802 
803 	// FIXME Byte order
804 	//
805 }
806 
807 template<typename TDst, typename TSrc>
write(const TSrc * src_values,int src_count,CastTag)808 void SavedGameHelper::write(
809 	const TSrc* src_values,
810 	int src_count,
811 	CastTag)
812 {
813 	using Tag = typename std::conditional<
814 		std::is_arithmetic<TSrc>::value ||
815 			std::is_enum<TSrc>::value,
816 		NumericTag,
817 		typename std::conditional<
818 			std::is_pointer<TSrc>::value,
819 			PointerTag,
820 			typename std::conditional<
821 				std::is_class<TSrc>::value,
822 				ClassTag,
823 				void
824 			>::type
825 		>::type
826 	>::type;
827 
828 	for (int i = 0; i < src_count; ++i)
829 	{
830 		write<TDst>(
831 			src_values[i],
832 			Tag());
833 	}
834 }
835 
836 // write (C-array)
837 // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
838 
839 
840 } // ojk
841 
842 
843 #endif // OJK_SAVED_GAME_HELPER_INCLUDED
844