1/*****************************************************************************/
2// Copyright 2006-2007 Adobe Systems Incorporated
3// All Rights Reserved.
4//
5// NOTICE:  Adobe permits you to use, modify, and distribute this file in
6// accordance with the terms of the Adobe license agreement accompanying it.
7/*****************************************************************************/
8
9/* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_stream.cpp#2 $ */
10/* $DateTime: 2012/06/01 07:28:57 $ */
11/* $Change: 832715 $ */
12/* $Author: tknoll $ */
13
14/*****************************************************************************/
15
16#include "dng_stream.h"
17
18#include "dng_abort_sniffer.h"
19#include "dng_auto_ptr.h"
20#include "dng_bottlenecks.h"
21#include "dng_exceptions.h"
22#include "dng_flags.h"
23#include "dng_memory.h"
24#include "dng_tag_types.h"
25
26/*****************************************************************************/
27
28dng_stream::dng_stream (dng_abort_sniffer *sniffer,
29						uint32 bufferSize,
30						uint64 offsetInOriginalFile)
31
32	:	fSwapBytes			  (false)
33	,	fHaveLength			  (false)
34	,	fLength				  (0)
35	,	fOffsetInOriginalFile (offsetInOriginalFile)
36	,	fPosition			  (0)
37	,	fMemBlock			  (bufferSize)
38	,	fBuffer				  (fMemBlock.Buffer_uint8 ())
39	,	fBufferSize			  (bufferSize)
40	,	fBufferStart		  (0)
41	,	fBufferEnd			  (0)
42	,	fBufferLimit		  (bufferSize)
43	,	fBufferDirty		  (false)
44	,	fSniffer			  (sniffer)
45
46	{
47
48	}
49
50/*****************************************************************************/
51
52dng_stream::dng_stream (const void *data,
53						uint32 count,
54						uint64 offsetInOriginalFile)
55
56	:	fSwapBytes			  (false)
57	,	fHaveLength			  (true)
58	,	fLength				  (count)
59	,	fOffsetInOriginalFile (offsetInOriginalFile)
60	,	fPosition			  (0)
61	,	fMemBlock			  ()
62	,	fBuffer				  ((uint8 *) data)
63	,	fBufferSize			  (count)
64	,	fBufferStart		  (0)
65	,	fBufferEnd			  (count)
66	,	fBufferLimit		  (count)
67	,	fBufferDirty		  (false)
68	,	fSniffer			  (NULL)
69
70	{
71
72	}
73
74/*****************************************************************************/
75
76dng_stream::~dng_stream ()
77	{
78
79	}
80
81/*****************************************************************************/
82
83uint64 dng_stream::DoGetLength ()
84	{
85
86	ThrowProgramError ();
87
88	return 0;
89
90	}
91
92/*****************************************************************************/
93
94void dng_stream::DoRead (void * /* data */,
95						 uint32 /* count */,
96						 uint64 /* offset */)
97	{
98
99	ThrowProgramError ();
100
101	}
102
103/*****************************************************************************/
104
105void dng_stream::DoSetLength (uint64 /* length */)
106	{
107
108	ThrowProgramError ();
109
110	}
111
112/*****************************************************************************/
113
114void dng_stream::DoWrite (const void * /* data */,
115						  uint32 /* count */,
116						  uint64 /* offset */)
117	{
118
119	ThrowProgramError ();
120
121	}
122
123/*****************************************************************************/
124
125bool dng_stream::BigEndian () const
126	{
127
128	return fSwapBytes != (!!qDNGBigEndian);
129
130	}
131
132/*****************************************************************************/
133
134void dng_stream::SetBigEndian (bool bigEndian)
135	{
136
137	fSwapBytes = (bigEndian != (!!qDNGBigEndian));
138
139	}
140
141/*****************************************************************************/
142
143const void * dng_stream::Data () const
144	{
145
146	if (fBufferStart == 0 && fHaveLength && fBufferEnd == fLength)
147		{
148
149		return fBuffer;
150
151		}
152
153	return NULL;
154
155	}
156
157/*****************************************************************************/
158
159dng_memory_block * dng_stream::AsMemoryBlock (dng_memory_allocator &allocator)
160	{
161
162	Flush ();
163
164	uint64 len64 = Length ();
165
166	if (len64 > 0xFFFFFFFF)
167		{
168		ThrowProgramError ();
169		}
170
171	uint32 len = (uint32) len64;
172
173	AutoPtr<dng_memory_block> block (allocator.Allocate (len));
174
175	if (len)
176		{
177
178		SetReadPosition (0);
179
180		Get (block->Buffer (), len);
181
182		}
183
184	return block.Release ();
185
186	}
187
188/*****************************************************************************/
189
190void dng_stream::SetReadPosition (uint64 offset)
191	{
192
193	fPosition = offset;
194
195	if (fPosition > Length ())
196		{
197
198		ThrowEndOfFile ();
199
200		}
201
202	}
203
204/*****************************************************************************/
205
206uint64 dng_stream::OffsetInOriginalFile () const
207	{
208
209	return fOffsetInOriginalFile;
210
211	}
212
213/*****************************************************************************/
214
215uint64 dng_stream::PositionInOriginalFile () const
216	{
217
218	if (fOffsetInOriginalFile == kDNGStreamInvalidOffset)
219		return kDNGStreamInvalidOffset;
220
221	return fOffsetInOriginalFile + Position ();
222
223	}
224
225/*****************************************************************************/
226
227void dng_stream::Get (void *data, uint32 count)
228	{
229
230	while (count)
231		{
232
233		// See if the request is totally inside buffer.
234
235		if (fPosition >= fBufferStart && fPosition + count <= fBufferEnd)
236			{
237
238			DoCopyBytes (fBuffer + (uint32) (fPosition - fBufferStart),
239						 data,
240						 count);
241
242			fPosition += count;
243
244			return;
245
246			}
247
248		// See if first part of request is inside buffer.
249
250		if (fPosition >= fBufferStart && fPosition < fBufferEnd)
251			{
252
253			uint32 block = (uint32) (fBufferEnd - fPosition);
254
255			DoCopyBytes (fBuffer + (fPosition - fBufferStart),
256						 data,
257						 block);
258
259			count -= block;
260
261			data = (void *) (((char *) data) + block);
262
263			fPosition += block;
264
265			}
266
267		// Flush buffer if dirty.
268
269		Flush ();
270
271		// Do large reads unbuffered.
272
273		if (count > fBufferSize)
274			{
275
276			if (fPosition + count > Length ())
277				{
278
279				ThrowEndOfFile ();
280
281				}
282
283			DoRead (data,
284					count,
285					fPosition);
286
287			fPosition += count;
288
289			return;
290
291			}
292
293		// Figure out new buffer range.
294
295		fBufferStart = fPosition;
296
297		if (fBufferSize >= 4096)
298			{
299
300			// Align to a 4K file block.
301
302			fBufferStart &= (uint64) ~((int64) 4095);
303
304			}
305
306		fBufferEnd = Min_uint64 (fBufferStart + fBufferSize, Length ());
307
308		if (fBufferEnd <= fPosition)
309			{
310
311			ThrowEndOfFile ();
312
313			}
314
315		// Read data into buffer.
316
317		dng_abort_sniffer::SniffForAbort (fSniffer);
318
319		DoRead (fBuffer,
320				(uint32) (fBufferEnd - fBufferStart),
321				fBufferStart);
322
323		}
324
325	}
326
327/*****************************************************************************/
328
329void dng_stream::SetWritePosition (uint64 offset)
330	{
331
332	fPosition = offset;
333
334	}
335
336/*****************************************************************************/
337
338void dng_stream::Flush ()
339	{
340
341	if (fBufferDirty)
342		{
343
344		dng_abort_sniffer::SniffForAbort (fSniffer);
345
346		DoWrite (fBuffer,
347				 (uint32) (fBufferEnd - fBufferStart),
348				 fBufferStart);
349
350		fBufferStart = 0;
351		fBufferEnd   = 0;
352		fBufferLimit = fBufferSize;
353
354		fBufferDirty = false;
355
356		}
357
358	}
359
360/*****************************************************************************/
361
362void dng_stream::SetLength (uint64 length)
363	{
364
365	Flush ();
366
367	if (Length () != length)
368		{
369
370		DoSetLength (length);
371
372		fLength = length;
373
374		}
375
376	}
377
378/*****************************************************************************/
379
380void dng_stream::Put (const void *data,
381					  uint32 count)
382	{
383
384	// See if we can replace or append to the existing buffer.
385
386	uint64 endPosition = fPosition + count;
387
388	if (fBufferDirty                &&
389		fPosition   >= fBufferStart &&
390		fPosition   <= fBufferEnd   &&
391		endPosition <= fBufferLimit)
392		{
393
394		DoCopyBytes (data,
395					 fBuffer + (uint32) (fPosition - fBufferStart),
396				     count);
397
398		if (fBufferEnd < endPosition)
399			fBufferEnd = endPosition;
400
401		}
402
403	// Else we need to write to the file.
404
405	else
406		{
407
408		// Write existing buffer.
409
410		Flush ();
411
412		// Write large blocks unbuffered.
413
414		if (count >= fBufferSize)
415			{
416
417			dng_abort_sniffer::SniffForAbort (fSniffer);
418
419			DoWrite (data, count, fPosition);
420
421			}
422
423		// Start a new buffer with small blocks.
424
425		else
426			{
427
428			fBufferDirty = true;
429
430			fBufferStart = fPosition;
431			fBufferEnd   = endPosition;
432			fBufferLimit = fBufferStart + fBufferSize;
433
434			DoCopyBytes (data,
435						 fBuffer,
436					     count);
437
438			}
439
440		}
441
442	fPosition = endPosition;
443
444	fLength = Max_uint64 (Length (), fPosition);
445
446	}
447
448/*****************************************************************************/
449
450uint16 dng_stream::Get_uint16 ()
451	{
452
453	uint16 x;
454
455	Get (&x, 2);
456
457	if (fSwapBytes)
458		{
459
460		x = SwapBytes16 (x);
461
462		}
463
464	return x;
465
466	}
467
468/*****************************************************************************/
469
470void dng_stream::Put_uint16 (uint16 x)
471	{
472
473	if (fSwapBytes)
474		{
475
476		x = SwapBytes16 (x);
477
478		}
479
480	Put (&x, 2);
481
482	}
483
484/*****************************************************************************/
485
486uint32 dng_stream::Get_uint32 ()
487	{
488
489	uint32 x;
490
491	Get (&x, 4);
492
493	if (fSwapBytes)
494		{
495
496		x = SwapBytes32 (x);
497
498		}
499
500	return x;
501
502	}
503
504/*****************************************************************************/
505
506void dng_stream::Put_uint32 (uint32 x)
507	{
508
509	if (fSwapBytes)
510		{
511
512		x = SwapBytes32 (x);
513
514		}
515
516	Put (&x, 4);
517
518	}
519
520/*****************************************************************************/
521
522uint64 dng_stream::Get_uint64 ()
523	{
524
525	if (fSwapBytes)
526		{
527
528		union
529			{
530			uint32 u32 [2];
531			uint64 u64;
532			} u;
533
534		u.u32 [1] = Get_uint32 ();
535		u.u32 [0] = Get_uint32 ();
536
537		return u.u64;
538
539		}
540
541	uint64 x;
542
543	Get (&x, 8);
544
545	return x;
546
547	}
548
549/*****************************************************************************/
550
551void dng_stream::Put_uint64 (uint64 x)
552	{
553
554	if (fSwapBytes)
555		{
556
557		union
558			{
559			uint32 u32 [2];
560			uint64 u64;
561			} u;
562
563		u.u64 = x;
564
565		Put_uint32 (u.u32 [1]);
566		Put_uint32 (u.u32 [0]);
567
568		}
569
570	else
571		{
572
573		Put (&x, 8);
574
575		}
576
577	}
578
579/*****************************************************************************/
580
581real32 dng_stream::Get_real32 ()
582	{
583
584	union
585		{
586		uint32 i;
587		real32 r;
588		} u;
589
590	u.i = Get_uint32 ();
591
592	return u.r;
593
594	}
595
596/*****************************************************************************/
597
598void dng_stream::Put_real32 (real32 x)
599	{
600
601	if (fSwapBytes)
602		{
603
604		union
605			{
606			uint32 i;
607			real32 r;
608			} u;
609
610		u.r = x;
611
612		Put_uint32 (u.i);
613
614		}
615
616	else
617		{
618
619		Put (&x, 4);
620
621		}
622
623	}
624
625/*****************************************************************************/
626
627real64 dng_stream::Get_real64 ()
628	{
629
630	if (fSwapBytes)
631		{
632
633		union
634			{
635			uint32 i [2];
636			real64 r;
637			} u;
638
639		u.i [1] = Get_uint32 ();
640		u.i [0] = Get_uint32 ();
641
642		return u.r;
643
644		}
645
646	real64 x;
647
648	Get (&x, 8);
649
650	return x;
651
652	}
653
654/*****************************************************************************/
655
656void dng_stream::Put_real64 (real64 x)
657	{
658
659	if (fSwapBytes)
660		{
661
662		union
663			{
664			uint32 i [2];
665			real64 r;
666			} u;
667
668		u.r = x;
669
670		Put_uint32 (u.i [1]);
671		Put_uint32 (u.i [0]);
672
673		}
674
675	else
676		{
677
678		Put (&x, 8);
679
680		}
681
682	}
683
684/*****************************************************************************/
685
686void dng_stream::Get_CString (char *data, uint32 maxLength)
687	{
688
689	memset (data, 0, maxLength);
690
691	uint32 index = 0;
692
693	while (true)
694		{
695
696		char c = (char) Get_uint8 ();
697
698		if (index + 1 < maxLength)
699			data [index++] = c;
700
701		if (c == 0)
702			break;
703
704		}
705
706	}
707
708/*****************************************************************************/
709
710void dng_stream::Get_UString (char *data, uint32 maxLength)
711	{
712
713	memset (data, 0, maxLength);
714
715	uint32 index = 0;
716
717	while (true)
718		{
719
720		char c = (char) Get_uint16 ();
721
722		if (index + 1 < maxLength)
723			data [index++] = (char) c;
724
725		if (c == 0)
726			break;
727
728		}
729
730	}
731
732/*****************************************************************************/
733
734void dng_stream::PutZeros (uint64 count)
735	{
736
737	const uint32 kZeroBufferSize = 4096;
738
739	if (count >= kZeroBufferSize)
740		{
741
742		dng_memory_data zeroBuffer (kZeroBufferSize);
743
744		DoZeroBytes (zeroBuffer.Buffer (),
745					 kZeroBufferSize);
746
747		while (count)
748			{
749
750			uint64 blockSize = Min_uint64 (count, kZeroBufferSize);
751
752			Put (zeroBuffer.Buffer (), (uint32) blockSize);
753
754			count -= blockSize;
755
756			}
757
758		}
759
760	else
761		{
762
763		uint32 count32 = (uint32) count;
764
765		for (uint32 j = 0; j < count32; j++)
766			{
767
768			Put_uint8 (0);
769
770			}
771
772		}
773
774	}
775
776/*****************************************************************************/
777
778void dng_stream::PadAlign2 ()
779	{
780
781	PutZeros (Position () & 1);
782
783	}
784
785/*****************************************************************************/
786
787void dng_stream::PadAlign4 ()
788	{
789
790	PutZeros ((4 - (Position () & 3)) & 3);
791
792	}
793
794/*****************************************************************************/
795
796uint32 dng_stream::TagValue_uint32 (uint32 tagType)
797	{
798
799	switch (tagType)
800		{
801
802		case ttByte:
803			return (uint32) Get_uint8 ();
804
805		case ttShort:
806			return (uint32) Get_uint16 ();
807
808		case ttLong:
809		case ttIFD:
810			return Get_uint32 ();
811
812		}
813
814	real64 x = TagValue_real64 (tagType);
815
816	if (x < 0.0)
817		x = 0.0;
818
819	if (x > (real64) 0xFFFFFFFF)
820		x = (real64) 0xFFFFFFFF;
821
822	return ConvertDoubleToUint32(x + 0.5);
823
824	}
825
826/*****************************************************************************/
827
828int32 dng_stream::TagValue_int32 (uint32 tagType)
829	{
830
831	switch (tagType)
832		{
833
834		case ttSByte:
835			return (int32) Get_int8 ();
836
837		case ttSShort:
838			return (int32) Get_int16 ();
839
840		case ttSLong:
841			return Get_int32 ();
842
843		}
844
845	real64 x = TagValue_real64 (tagType);
846
847	if (x < 0.0)
848		{
849
850		if (x < -2147483648.0)
851			x = -2147483648.0;
852
853		return ConvertDoubleToInt32(x - 0.5);
854
855		}
856
857	else
858		{
859
860		if (x > 2147483647.0)
861			x = 2147483647.0;
862
863		return ConvertDoubleToInt32(x + 0.5);
864
865		}
866
867	}
868
869/*****************************************************************************/
870
871dng_urational dng_stream::TagValue_urational (uint32 tagType)
872	{
873
874	dng_urational result;
875
876	result.n = 0;
877	result.d = 1;
878
879	switch (tagType)
880		{
881
882		case ttRational:
883			{
884
885			result.n = Get_uint32 ();
886			result.d = Get_uint32 ();
887
888			break;
889
890			}
891
892		case ttSRational:
893			{
894
895			int32 n = Get_int32 ();
896			int32 d = Get_int32 ();
897
898			if ((n < 0) == (d < 0))
899				{
900
901				if (d < 0)
902					{
903					result.n = (uint32) ((int64) n * -1);
904					result.d = (uint32) ((int64) d * -1);
905					}
906				else
907					{
908					result.n = (uint32) n;
909					result.d = (uint32) d;
910					}
911
912				}
913
914			break;
915
916			}
917
918		case ttByte:
919		case ttShort:
920		case ttLong:
921		case ttIFD:
922			{
923
924			result.n = TagValue_uint32 (tagType);
925
926			break;
927
928			}
929
930		case ttSByte:
931		case ttSShort:
932		case ttSLong:
933			{
934
935			int32 n = TagValue_int32 (tagType);
936
937			if (n > 0)
938				{
939				result.n = (uint32) n;
940				}
941
942			break;
943
944			}
945
946		default:
947			{
948
949			real64 x = TagValue_real64 (tagType);
950
951			if (x > 0.0)
952				{
953
954				while (result.d < 10000 && x < 1000000)
955					{
956
957					result.d *= 10;
958
959					x *= 10.0;
960
961					}
962
963				result.n = ConvertDoubleToUint32(x + 0.5);
964
965				}
966
967			}
968
969		}
970
971	return result;
972
973	}
974
975/*****************************************************************************/
976
977dng_srational dng_stream::TagValue_srational (uint32 tagType)
978	{
979
980	dng_srational result;
981
982	result.n = 0;
983	result.d = 1;
984
985	switch (tagType)
986		{
987
988		case ttSRational:
989			{
990
991			result.n = Get_int32 ();
992			result.d = Get_int32 ();
993
994			break;
995
996			}
997
998		default:
999			{
1000
1001			real64 x = TagValue_real64 (tagType);
1002
1003			if (x > 0.0)
1004				{
1005
1006				while (result.d < 10000 && x < 1000000.0)
1007					{
1008
1009					result.d *= 10;
1010
1011					x *= 10.0;
1012
1013					}
1014
1015				result.n = ConvertDoubleToInt32(x + 0.5);
1016
1017				}
1018
1019			else
1020				{
1021
1022				while (result.d < 10000 && x > -1000000.0)
1023					{
1024
1025					result.d *= 10;
1026
1027					x *= 10.0;
1028
1029					}
1030
1031				result.n = ConvertDoubleToInt32(x - 0.5);
1032
1033				}
1034
1035			}
1036
1037		}
1038
1039	return result;
1040
1041	}
1042
1043/*****************************************************************************/
1044
1045real64 dng_stream::TagValue_real64 (uint32 tagType)
1046	{
1047
1048	switch (tagType)
1049		{
1050
1051		case ttByte:
1052		case ttShort:
1053		case ttLong:
1054		case ttIFD:
1055			return (real64) TagValue_uint32 (tagType);
1056
1057		case ttSByte:
1058		case ttSShort:
1059		case ttSLong:
1060			return (real64) TagValue_int32 (tagType);
1061
1062		case ttRational:
1063			{
1064
1065			uint32 n = Get_uint32 ();
1066			uint32 d = Get_uint32 ();
1067
1068			if (d == 0)
1069				return 0.0;
1070			else
1071				return (real64) n / (real64) d;
1072
1073			}
1074
1075		case ttSRational:
1076			{
1077
1078			int32 n = Get_int32 ();
1079			int32 d = Get_int32 ();
1080
1081			if (d == 0)
1082				return 0.0;
1083			else
1084				return (real64) n / (real64) d;
1085
1086			}
1087
1088		case ttFloat:
1089			return (real64) Get_real32 ();
1090
1091		case ttDouble:
1092			return Get_real64 ();
1093
1094		}
1095
1096	return 0.0;
1097
1098	}
1099
1100/*****************************************************************************/
1101
1102void dng_stream::CopyToStream (dng_stream &dstStream,
1103							   uint64 count)
1104	{
1105
1106	uint8 smallBuffer [1024];
1107
1108	if (count <= sizeof (smallBuffer))
1109		{
1110
1111		Get (smallBuffer, (uint32) count);
1112
1113		dstStream.Put (smallBuffer, (uint32) count);
1114
1115		}
1116
1117	else
1118		{
1119
1120		const uint32 bigBufferSize = (uint32) Min_uint64 (kBigBufferSize,
1121													      count);
1122
1123		dng_memory_data bigBuffer (bigBufferSize);
1124
1125		while (count)
1126			{
1127
1128			uint32 blockCount = (uint32) Min_uint64 (bigBufferSize,
1129													 count);
1130
1131			Get (bigBuffer.Buffer (),
1132				 blockCount);
1133
1134			dstStream.Put (bigBuffer.Buffer (),
1135						   blockCount);
1136
1137			count -= blockCount;
1138
1139			}
1140
1141		}
1142
1143	}
1144
1145/*****************************************************************************/
1146
1147void dng_stream::DuplicateStream (dng_stream &dstStream)
1148	{
1149
1150	// Turn off sniffers for this operation.
1151
1152	TempStreamSniffer noSniffer1 (*this    , NULL);
1153	TempStreamSniffer noSniffer2 (dstStream, NULL);
1154
1155	// First grow the destination stream if required, in an attempt to
1156	// reserve any needed space before overwriting the existing data.
1157
1158	if (dstStream.Length () < Length ())
1159		{
1160		dstStream.SetLength (Length ());
1161		}
1162
1163	SetReadPosition (0);
1164
1165	dstStream.SetWritePosition (0);
1166
1167	CopyToStream (dstStream, Length ());
1168
1169	dstStream.Flush ();
1170
1171	dstStream.SetLength (Length ());
1172
1173	}
1174
1175/*****************************************************************************/
1176
1177TempBigEndian::TempBigEndian (dng_stream &stream,
1178						 	  bool bigEndian)
1179
1180	:	fStream  (stream)
1181	,	fOldSwap (stream.SwapBytes ())
1182
1183	{
1184
1185	fStream.SetBigEndian (bigEndian);
1186
1187	}
1188
1189/*****************************************************************************/
1190
1191TempBigEndian::~TempBigEndian ()
1192	{
1193
1194	fStream.SetSwapBytes (fOldSwap);
1195
1196	}
1197
1198/*****************************************************************************/
1199
1200TempStreamSniffer::TempStreamSniffer (dng_stream &stream,
1201									  dng_abort_sniffer *sniffer)
1202
1203	:	fStream     (stream)
1204	,	fOldSniffer (stream.Sniffer ())
1205
1206	{
1207
1208	fStream.SetSniffer (sniffer);
1209
1210	}
1211
1212/*****************************************************************************/
1213
1214TempStreamSniffer::~TempStreamSniffer ()
1215	{
1216
1217	fStream.SetSniffer (fOldSniffer);
1218
1219	}
1220
1221/*****************************************************************************/
1222