@@ -97,6 +97,18 @@ vips_target_finalize(GObject *gobject)
97
97
G_OBJECT_CLASS (vips_target_parent_class )-> finalize (gobject );
98
98
}
99
99
100
+ static void
101
+ vips_target_dispose (GObject * gobject )
102
+ {
103
+ VipsTarget * target = VIPS_TARGET (gobject );
104
+
105
+ VIPS_DEBUG_MSG ("vips_target_dispose:\n" );
106
+
107
+ VIPS_UNREF (target -> temp );
108
+
109
+ G_OBJECT_CLASS (vips_target_parent_class )-> dispose (gobject );
110
+ }
111
+
100
112
static int
101
113
vips_target_build (VipsObject * object )
102
114
{
@@ -275,6 +287,7 @@ vips_target_class_init(VipsTargetClass *class)
275
287
GObjectClass * gobject_class = G_OBJECT_CLASS (class );
276
288
VipsObjectClass * object_class = VIPS_OBJECT_CLASS (class );
277
289
290
+ gobject_class -> dispose = vips_target_dispose ;
278
291
gobject_class -> finalize = vips_target_finalize ;
279
292
gobject_class -> set_property = vips_object_set_property ;
280
293
gobject_class -> get_property = vips_object_get_property ;
@@ -427,8 +440,7 @@ vips_target_new_temp(VipsTarget *based_on)
427
440
428
441
if (!(filename = vips__temp_name ("%s.target" )))
429
442
return NULL ;
430
- if ((descriptor =
431
- vips__open_image_write (filename , TRUE)) < 0 ) {
443
+ if ((descriptor = vips__open_image_write (filename , TRUE)) < 0 ) {
432
444
g_free (filename );
433
445
return NULL ;
434
446
}
@@ -468,10 +480,9 @@ vips_target_write_unbuffered(VipsTarget *target,
468
480
* one to make sure we don't get stuck in this loop.
469
481
*/
470
482
if (bytes_written <= 0 ) {
471
- vips_error_system (errno ,
472
- vips_connection_nick (
473
- VIPS_CONNECTION (target )),
474
- "%s" , _ ("write error" ));
483
+ const char * nick = vips_connection_nick (VIPS_CONNECTION (target ));
484
+
485
+ vips_error_system (errno , nick , "%s" , _ ("write error" ));
475
486
return -1 ;
476
487
}
477
488
@@ -515,20 +526,52 @@ vips_target_write(VipsTarget *target, const void *buffer, size_t length)
515
526
{
516
527
VIPS_DEBUG_MSG ("vips_target_write: %zd bytes\n" , length );
517
528
518
- if (length > VIPS_TARGET_BUFFER_SIZE - target -> write_point &&
519
- vips_target_flush (target ))
520
- return -1 ;
521
-
522
- if (length > VIPS_TARGET_BUFFER_SIZE - target -> write_point ) {
523
- /* Still too large? Do an unbuffered write.
524
- */
525
- if (vips_target_write_unbuffered (target , buffer , length ))
529
+ if (target -> temp ) {
530
+ if (vips_target_write (target -> temp , data , length ))
526
531
return -1 ;
527
532
}
528
533
else {
529
- memcpy (target -> output_buffer + target -> write_point ,
530
- buffer , length );
531
- target -> write_point += length ;
534
+ if (length > VIPS_TARGET_BUFFER_SIZE - target -> write_point &&
535
+ vips_target_flush (target ))
536
+ return -1 ;
537
+
538
+ if (length > VIPS_TARGET_BUFFER_SIZE - target -> write_point ) {
539
+ /* Still too large? Do an unbuffered write.
540
+ */
541
+ if (vips_target_write_unbuffered (target , buffer , length ))
542
+ return -1 ;
543
+ }
544
+ else {
545
+ memcpy (target -> output_buffer + target -> write_point , buffer , length );
546
+ target -> write_point += length ;
547
+ }
548
+ }
549
+
550
+ return 0 ;
551
+ }
552
+
553
+ /**
554
+ * vips_target_need_seek:
555
+ * @target: target to operate on
556
+ *
557
+ * Some writers need to be able to seek the output (for example, `tiffsave`),
558
+ * however, some targets (eg. pipes) don't support this.
559
+ *
560
+ * Calling `vips_target_need_seek()` on a target with no seek method redirects
561
+ * output to a temporary file or to memory, then on close, copies that object
562
+ * to the output.
563
+ *
564
+ * Returns: 0 on success, -1 on error.
565
+ */
566
+ int
567
+ vips_target_need_seek (VipsTarget * target )
568
+ {
569
+ g_assert (!target -> temp );
570
+
571
+ if (vips_target_seek (target , 0 , SEEK_CUR ) != -1 ) {
572
+ VIPS_DEBUG_MSG ("vips_target_need_seek: redirecting output to temp\n" );
573
+ if (!(target -> temp = vips_target_new_temp (target )))
574
+ return -1 ;
532
575
}
533
576
534
577
return 0 ;
@@ -558,10 +601,17 @@ vips_target_read(VipsTarget *target, void *buffer, size_t length)
558
601
559
602
VIPS_DEBUG_MSG ("vips_target_read: %zd bytes\n" , length );
560
603
561
- if (vips_target_flush (target ))
562
- return -1 ;
604
+ if (target -> temp ) {
605
+ if (vips_target_read (target -> temp , buffer , length ))
606
+ return -1 ;
607
+ }
608
+ else {
609
+ if (vips_target_flush (target ) ||
610
+ class -> read (target , buffer , length ))
611
+ return -1 ;
612
+ }
563
613
564
- return class -> read ( target , buffer , length ) ;
614
+ return 0 ;
565
615
}
566
616
567
617
/**
@@ -584,17 +634,21 @@ vips_target_seek(VipsTarget *target, gint64 position, int whence)
584
634
585
635
gint64 new_position ;
586
636
587
- VIPS_DEBUG_MSG ("vips_target_seek: pos = %" G_GINT64_FORMAT
588
- ", whence = %d\n" ,
589
- position , whence );
637
+ if (target -> temp )
638
+ new_position = vips_target_seek (target -> temp , position , whence );
639
+ else {
640
+ VIPS_DEBUG_MSG ("vips_target_seek: pos = %" G_GINT64_FORMAT
641
+ ", whence = %d\n" ,
642
+ position , whence );
590
643
591
- if (vips_target_flush (target ))
592
- return -1 ;
644
+ if (vips_target_flush (target ))
645
+ return -1 ;
593
646
594
- new_position = class -> seek (target , position , whence );
647
+ new_position = class -> seek (target , position , whence );
595
648
596
- VIPS_DEBUG_MSG ("vips_target_seek: new_position = %" G_GINT64_FORMAT "\n" ,
597
- new_position );
649
+ VIPS_DEBUG_MSG ("vips_target_seek: "
650
+ "new_position = %" G_GINT64_FORMAT "\n" , new_position );
651
+ }
598
652
599
653
return new_position ;
600
654
}
0 commit comments