Coverage Report

Created: 2026-01-17 06:44

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