Line data Source code
1 : /*
2 : Zipios++ - a small C++ library that provides easy access to .zip files.
3 :
4 : Copyright (C) 2000-2007 Thomas Sondergaard
5 : Copyright (C) 2015 Made to Order Software Corporation
6 :
7 : This library is free software; you can redistribute it and/or
8 : modify it under the terms of the GNU Lesser General Public
9 : License as published by the Free Software Foundation; either
10 : version 2 of the License, or (at your option) any later version.
11 :
12 : This library is distributed in the hope that it will be useful,
13 : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : Lesser General Public License for more details.
16 :
17 : You should have received a copy of the GNU Lesser General Public
18 : License along with this library; if not, write to the Free Software
19 : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 : */
21 :
22 : /** \file
23 : * \brief Implementation of zipios::FileEntry.
24 : *
25 : * This file includes the implementation of the Fzipios::ileEntry.
26 : * Many of the functions in zipios::FileEntry are pure virtual so
27 : * only their documentation appears here.
28 : *
29 : * zipios::FileEntry is used to build collections of files.
30 : */
31 :
32 : #include "zipios/fileentry.hpp"
33 :
34 : #include "dostime.h"
35 : #include "zipios/zipiosexceptions.hpp"
36 :
37 : #include "zipios_common.hpp"
38 :
39 :
40 : namespace zipios
41 : {
42 :
43 : /** \enum StorageMethod
44 : * \brief The types used with FileEntry::setMethod and FileEntry::getMethod.
45 : *
46 : * The current entries are the types supported by the zip format. The
47 : * numbering matches one to one the numbering used in the zip file format,
48 : * i.e. STORED is indicated by a 0 in the method field in a zip file and
49 : * so on.
50 : *
51 : * The zipios library only support STORED and DEFLATED at this time.
52 : */
53 :
54 :
55 : /** \class FileEntry
56 : * \brief A FileEntry represents an entry in a FileCollection.
57 : *
58 : * The interface is a copy of the ZipEntry interface from the java.util.zip
59 : * package. The name has been changed to FileEntry, as FileCollection
60 : * is a more general abstraction, that covers other types of file
61 : * collections than just zip files.
62 : *
63 : * \note
64 : * The hashCode() supported in Java is not included as we do not have an
65 : * equivalent in this library.
66 : */
67 :
68 :
69 : /** \typedef int FileEntry::CompressionLevel
70 : * \brief The compression level to be used to save an entry.
71 : *
72 : * Values defined using this time represent the compression level to
73 : * be used when compressing an entry.
74 : *
75 : * If unchanged, use the DEFAULT_COMPRESSION value.
76 : *
77 : * It is possible to change the compression level to NO_COMPRESSION or
78 : * use the setMethod() with STORED to avoid any compression (i.e. create
79 : * a zip file which awfully looks like a tarball).
80 : *
81 : * \todo
82 : * These values are one to one mapped to zlib compression values. This
83 : * is likely to change once we start offering other compression scheme
84 : * for a number defined between 0 and 100 instead.
85 : */
86 :
87 :
88 : /** \brief Initialize a FileEntry object.
89 : *
90 : * This funciton initializes a FileEntry object. By default you may define
91 : * the filename of the FileEntry object.
92 : *
93 : * In case of an on disk directory, the filename should be the path to the
94 : * file that can be read from disk, otherwise the FileEntry object will be
95 : * viewed as invalid. There is, otherwise, no restriction to the filename.
96 : *
97 : * \param[in] filename The file entry filename.
98 : * \param[in] comment The comment attached to the file.
99 : */
100 377720 : FileEntry::FileEntry(FilePath const& filename, std::string const& comment)
101 : : m_filename(filename)
102 377720 : , m_comment(comment)
103 : //, m_uncompressed_size(0) -- auto-init
104 : //, m_unix_time(0) -- auto-init
105 : //, m_entry_offset(0) -- auto-init
106 : //, m_compress_method(StorageMethod::STORED) -- auto-init
107 : //, m_compression_level(COMPRESSION_LEVEL_DEFAULT) -- auto-init
108 : //, m_crc_32(0) -- auto-init
109 : //, m_has_crc_32(false) -- auto-init
110 : //, m_valid(false) -- auto-init
111 : {
112 377720 : }
113 :
114 :
115 : /** \fn FileEntry::pointer_t FileEntry::clone() const;
116 : * \brief Create a clone of a file entry.
117 : *
118 : * This function creates a heap allocated clone of the object
119 : * this method is called for.
120 : *
121 : * Note that the object is expected to overload this function in
122 : * order to create a clone of the correct type.
123 : *
124 : * \return A smart pointer to the clone.
125 : */
126 :
127 :
128 : /** \brief Clean up a FileEntry object.
129 : *
130 : * The destructor is defined as it has to be virtual.
131 : *
132 : * It will eventually clean up resources used by the FileEntry class.
133 : */
134 675119 : FileEntry::~FileEntry()
135 : {
136 675119 : }
137 :
138 :
139 : /** \brief Retrieve the comment of the file entry.
140 : *
141 : * This function returns the comment of this entry.
142 : *
143 : * If the entry was not assigned a comment, this function returns
144 : * an empty string. All entries can be given a comment, although
145 : * for most it will be ignored unless you save the file to a Zip
146 : * archive.
147 : *
148 : * \return The comment associated with this entry, if there is one.
149 : */
150 107192 : std::string FileEntry::getComment() const
151 : {
152 107192 : return m_comment;
153 : }
154 :
155 :
156 : /** \brief Retrive the size of the file when compressed.
157 : *
158 : * This function returns the compressed size of the entry. If the
159 : * entry is not stored in a compressed format, the uncompressed
160 : * size is returned.
161 : *
162 : * \return The compressed size of the entry.
163 : */
164 27095 : size_t FileEntry::getCompressedSize() const
165 : {
166 27095 : return getSize();
167 : }
168 :
169 :
170 :
171 :
172 : /** \brief Return the CRC of the entry.
173 : *
174 : * This function returns the CRC 32 of this entry, if it has one.
175 : *
176 : * The CRC is set only after the file is compressed so it may
177 : * not always be available. The hasCrc() function can be used
178 : * to know whether it was set before.
179 : *
180 : * \return The CRC32 for the entry, if it has one.
181 : */
182 26403 : FileEntry::crc32_t FileEntry::getCrc() const
183 : {
184 : /** \FIXME
185 : * Should we throw if m_has_crc_32 is false?
186 : */
187 26403 : return m_crc_32;
188 : }
189 :
190 :
191 : /** \brief Get the offset of this entry in a Zip archive.
192 : *
193 : * This function retrieves the offset at which this FileEntry
194 : * resides in the Zip archive it is attached to.
195 : *
196 : * Note that in case of a Zip archive embedded in another file,
197 : * the offset is virtual (relative to the start of the Zip archive
198 : * in the larger file.)
199 : *
200 : * \return The position in the Zip archive.
201 : */
202 471816 : std::streampos FileEntry::getEntryOffset() const
203 : {
204 471816 : return m_entry_offset;
205 : }
206 :
207 :
208 : /** \brief Some extra data to be stored along the entry.
209 : *
210 : * This function returns a copy of the vector of bytes of extra data
211 : * that are stored with the entry.
212 : *
213 : * This buffer should be generated using the still non-existant
214 : * ZipExtra class. This includes definitions of additional meta
215 : * data necessary on various operating systems. For example, Linux
216 : * makes use of the "UT" (Universal Time) to save the atime, ctime,
217 : * and mtime parameters, and "ux" (Unix) to save the Unix permissions
218 : * and user identifier (uid) and group identifier (gid).
219 : *
220 : * \return A buffer_t of extra bytes that are associated with this entry.
221 : */
222 26447 : FileEntry::buffer_t FileEntry::getExtra() const
223 : {
224 26447 : return m_extra_field;
225 : }
226 :
227 :
228 : /** \brief Retrieve the size of the header.
229 : *
230 : * This function determines the size of the Zip archive header necessary
231 : * for that file.
232 : *
233 : * By default the function returns zero meaning that no header is defined.
234 : *
235 : * \return The size of the header in bytes.
236 : */
237 26403 : size_t FileEntry::getHeaderSize() const
238 : {
239 26403 : return 0;
240 : }
241 :
242 :
243 : /** \brief Retrieve the compression level.
244 : *
245 : * Use this function to read the compression level to use to compress
246 : * a file.
247 : *
248 : * Note that the compression level is rarely saved in the
249 : * destination file, so after reading a file from a Zip archive this
250 : * parameter is set to the default compression level which does not
251 : * represent the level used to create the file.
252 : *
253 : * The compression level is a number between 1 and 100 if compression
254 : * is wanted. 0 for no compression. A few negative numbers represent
255 : * various default compression levels.
256 : *
257 : * \return The compression level to use to write this entry to a Zip archive.
258 : *
259 : * \sa CompressionLevel
260 : * \sa setLevel()
261 : */
262 71341 : FileEntry::CompressionLevel FileEntry::getLevel() const
263 : {
264 71341 : if(isDirectory())
265 : {
266 22 : return COMPRESSION_LEVEL_NONE;
267 : }
268 71319 : return m_compression_level;
269 : }
270 :
271 :
272 : /** \brief Return the method used to create this entry.
273 : *
274 : * This function returns the method used to store the entry data in
275 : * the FileCollection it is attached to.
276 : *
277 : * \return the storage method used to store the entry in a collection.
278 : *
279 : * \sa StorageMethod
280 : * \sa setMethod()
281 : */
282 892597 : StorageMethod FileEntry::getMethod() const
283 : {
284 892597 : if(isDirectory())
285 : {
286 : // make sure we do not return anything else than STORED
287 : // for a directory
288 19422 : return StorageMethod::STORED;
289 : }
290 873175 : return m_compress_method;
291 : }
292 :
293 :
294 :
295 :
296 : /** \brief Return the filename of the entry.
297 : *
298 : * The function returns the full filename of the entry, including
299 : * a path if the entry is stored in a sub-folder.
300 : *
301 : * \return The filename of the entry including its path.
302 : */
303 63323509 : std::string FileEntry::getName() const
304 : {
305 63323509 : return m_filename;
306 : }
307 :
308 :
309 : /** \brief Return the basename of this entry.
310 : *
311 : * This function returns the filename only of the entry.
312 : *
313 : * \warning
314 : * The function returns the last segment of the filename whether it is
315 : * a regular file or a directory so one can search for a directory with
316 : * the MATCH or IGNORE search options.
317 : *
318 : * \return The filename of the entry.
319 : */
320 3747588 : std::string FileEntry::getFileName() const
321 : {
322 3747588 : return m_filename.filename();
323 : }
324 :
325 :
326 : /** \brief Retrieve the size of the file when uncompressed.
327 : *
328 : * This function returns the uncompressed size of the entry data.
329 : *
330 : * \return Returns the uncompressed size of the entry.
331 : */
332 331556 : size_t FileEntry::getSize() const
333 : {
334 331556 : return m_uncompressed_size;
335 : }
336 :
337 :
338 : /** \brief Get the MS-DOS date/time of this entry.
339 : *
340 : * This function returns the date and time of the entry in MSDOS
341 : * date/time format.
342 : *
343 : * \note
344 : * An MS-DOS date is limited to 127 years starting on 1980.
345 : * So it will be over after Dec 31, 2107.
346 : *
347 : * \return The date and time of the entry in MS-DOS format.
348 : */
349 107192 : FileEntry::dostime_t FileEntry::getTime() const
350 : {
351 107192 : return unix2dostime(m_unix_time);
352 : }
353 :
354 :
355 : /** \brief Get the Unix date/time of this entry.
356 : *
357 : * This function returns the date and time of the entry in Unix
358 : * date/time format (see time()).
359 : *
360 : * \note
361 : * The FileEntry object saves the time as a Unix time_t value,
362 : * however, the Zip file format uses the DOS time format. So
363 : * for a Zip file, the precision of the date is to the next
364 : * even second. Yet, this function may return a value which
365 : * is odd when the time comes from a file on disk.
366 : *
367 : * \note
368 : * Unless you have an old 32 bit system that defines time_t
369 : * as a 32 bit value, a Unix date can be considered infinite.
370 : * Otherwise it is limited to some time in 2068.
371 : *
372 : * \return The date and time of the entry as a time_t value.
373 : */
374 107192 : std::time_t FileEntry::getUnixTime() const
375 : {
376 107192 : return m_unix_time;
377 : }
378 :
379 :
380 : /** \brief Check whether the CRC32 was defined.
381 : *
382 : * This function returns true if the setCrc() function was called earlier
383 : * with a valid CRC32 and the FileEntry implementation supports a CRC (i.e.
384 : * a DirectoryEntry does not have a CRC).
385 : *
386 : * \return true if a CRC32 is defined in this class.
387 : */
388 107192 : bool FileEntry::hasCrc() const
389 : {
390 107192 : return m_has_crc_32;
391 : }
392 :
393 :
394 : /** \brief Check whether the filename represents a directory.
395 : *
396 : * This function checks the last character of the filename, if it
397 : * is a separator ('/') then the function returns true meaning
398 : * that the file represents a directory.
399 : *
400 : * \return true if the entry represents a directory.
401 : */
402 656997 : bool FileEntry::isDirectory() const
403 : {
404 656997 : return m_filename.isDirectory();
405 : }
406 :
407 :
408 : /** \brief Compare two file entries for equality.
409 : *
410 : * This function compares most of the fields between two file
411 : * entries to see whether they are equal or not.
412 : *
413 : * \warning
414 : * The Extra buffer is ignored in the comparison. There are two
415 : * reasons for this: (1) it is unlikely that such a parameter
416 : * should could in the comparison (just like the compressed
417 : * size of the file) and (2) the comparison is not trivial as
418 : * each chunk in the buffer needs to be separately compared
419 : * (we may offer that capability once we have a ZipExtra class.)
420 : *
421 : * \param[in] file_entry The file entry to compare this against.
422 : *
423 : * \return true if both FileEntry objects are considered equal.
424 : */
425 82663 : bool FileEntry::isEqual(FileEntry const & file_entry) const
426 : {
427 82663 : return m_filename == file_entry.m_filename
428 82435 : && m_comment == file_entry.m_comment
429 82435 : && m_uncompressed_size == file_entry.m_uncompressed_size
430 82435 : && m_unix_time == file_entry.m_unix_time
431 82435 : && m_compress_method == file_entry.m_compress_method
432 82425 : && m_crc_32 == file_entry.m_crc_32
433 82425 : && m_has_crc_32 == file_entry.m_has_crc_32
434 165088 : && m_valid == file_entry.m_valid;
435 : //&& m_extra_field == file_entry.m_extra_field -- ignored in comparison
436 : }
437 :
438 :
439 : /** \brief Check whether this entry is valid.
440 : *
441 : * Any method or operator that initializes a FileEntry may set a
442 : * flag that specifies whether the file entry is valid or not. If
443 : * it is not this method returns false.
444 : *
445 : * \return true if the FileEntry has been parsed succesfully.
446 : */
447 179633 : bool FileEntry::isValid() const
448 : {
449 179633 : return m_valid;
450 : }
451 :
452 :
453 : /** \brief Set the comment field for the FileEntry.
454 : *
455 : * This function sets the comment of this FileEntry. Note that
456 : * all implementations of the FileEntry may not include support
457 : * for a comment. In that case this function does nothing.
458 : *
459 : * \param[in] comment A string with the new comment.
460 : */
461 46 : void FileEntry::setComment(std::string const& comment)
462 : {
463 : // WARNING: we do NOT check the maximum size here because it can depend
464 : // on the output format which is just zip now but could be a
465 : // bit extended later (i.e. Zip64)
466 46 : m_comment = comment;
467 46 : }
468 :
469 :
470 : /** \brief Set the size when the file is compressed.
471 : *
472 : * This function saves the compressed size of the entry in this object.
473 : *
474 : * By default the compressed size is viewed as the same as the
475 : * uncompressed size (i.e. as if STORED was used for the compression
476 : * method.)
477 : *
478 : * \param[in] size Value to set the compressed size field of the entry to.
479 : */
480 24 : void FileEntry::setCompressedSize(size_t size)
481 : {
482 : static_cast<void>(size);
483 24 : }
484 :
485 :
486 : /** \brief Save the CRC of the entry.
487 : *
488 : * This funciton savees the CRC field in this FileEntry field.
489 : *
490 : * \param crc value to set the crc field to.
491 : */
492 24 : void FileEntry::setCrc(crc32_t crc)
493 : {
494 : static_cast<void>(crc);
495 24 : }
496 :
497 :
498 : /** \brief Defines the position of the entry in a Zip archive.
499 : *
500 : * This function defines the position of the FileEntry in a
501 : * Zip archive. By default the position is set to zero.
502 : *
503 : * The offset is generally read from a Zip directory entry.
504 : *
505 : * When used to seek in a file, the FileCollection will add
506 : * the start offset defined in the VirtualSeeker. In other words
507 : * this is the position in the Zip archive itself, not the final
508 : * position in the file you are reading the archive from.
509 : *
510 : * \param[in] offset The new archive entry offset.
511 : */
512 145382 : void FileEntry::setEntryOffset(std::streampos offset)
513 : {
514 145382 : m_entry_offset = offset;
515 145382 : }
516 :
517 :
518 : /** \brief Set the extra field buffer.
519 : *
520 : * This function is used to set the extra field.
521 : *
522 : * Only one type of file entry supports an extra field buffer.
523 : * The others do nothing when this function is called.
524 : *
525 : * \param[in] extra The extra field is set to this value.
526 : */
527 46 : void FileEntry::setExtra(buffer_t const& extra)
528 : {
529 46 : m_extra_field = extra;
530 46 : }
531 :
532 :
533 : /** \brief Define the level of compression to use by this FileEntry.
534 : *
535 : * This function saves the level of compression the library should use
536 : * to compress the file before saving it in the output file.
537 : *
538 : * \note
539 : * If the StorageMethod is set to STORED, then the compression level is
540 : * ignored, but it is left unchanged.
541 : *
542 : * \exception InvalidStateException
543 : * This function raises this exception if the specified level is out of
544 : * the allowed range.
545 : *
546 : * \param[in] level The compression level to use to compress the file data.
547 : */
548 85698 : void FileEntry::setLevel(CompressionLevel level)
549 : {
550 85698 : if(level < COMPRESSION_LEVEL_DEFAULT || level > COMPRESSION_LEVEL_MAXIMUM)
551 : {
552 5691 : throw InvalidStateException("level must be between COMPRESSION_LEVEL_DEFAULT and COMPRESSION_LEVEL_MAXIMUM");
553 : }
554 80007 : if(isDirectory())
555 : {
556 8322 : if(level >= COMPRESSION_LEVEL_MINIMUM)
557 : {
558 100 : throw InvalidStateException("directories cannot be marked with a compression level other than COMPRESSION_LEVEL_NONE (defaults will also work");
559 : }
560 8222 : m_compression_level = COMPRESSION_LEVEL_NONE;
561 : }
562 : else
563 : {
564 71685 : m_compression_level = level;
565 : }
566 79907 : }
567 :
568 :
569 : /** \brief Sets the storage method field for the entry.
570 : *
571 : * This function sets the method with which the file data is to
572 : * be compressed.
573 : *
574 : * The method is ignored in a file entry which cannot be compressed.
575 : * (or more precisly, the method is forced as STORED.)
576 : *
577 : * \exception InvalidStateException
578 : * This exception is raised if the \p method parameter does not represent
579 : * a supported method. At this time the library only supports STORED and
580 : * DEFLATED. The getMethod() may return more types as read from a Zip
581 : * archive, but it is not possible to set such types using this function.
582 : *
583 : * \param[in] method The method field is set to the specified value.
584 : */
585 79971 : void FileEntry::setMethod(StorageMethod method)
586 : {
587 79971 : switch(method)
588 : {
589 : case StorageMethod::STORED:
590 : //case StorageMethod::SHRUNK:
591 : //case StorageMethod::REDUCED1:
592 : //case StorageMethod::REDUCED2:
593 : //case StorageMethod::REDUCED3:
594 : //case StorageMethod::REDUCED4:
595 : //case StorageMethod::IMPLODED:
596 : //case StorageMethod::TOKENIZED:
597 : case StorageMethod::DEFLATED:
598 : //case StorageMethod::DEFLATED64:
599 : //case StorageMethod::OLD_TERSE:
600 : //case StorageMethod::RESERVED11:
601 : //case StorageMethod::BZIP2:
602 : //case StorageMethod::REVERVED13:
603 : //case StorageMethod::LZMA:
604 : //case StorageMethod::RESERVED15:
605 : //case StorageMethod::RESERVED16:
606 : //case StorageMethod::RESERVED17:
607 : //case StorageMethod::NEW_TERSE:
608 : //case StorageMethod::LZ77:
609 : //case StorageMethod::WAVPACK:
610 : //case StorageMethod::PPMD_I_1:
611 79717 : break;
612 :
613 : default:
614 254 : throw InvalidStateException("unknown method");
615 :
616 : }
617 :
618 79717 : if(isDirectory())
619 : {
620 : // force uncompressed for directories
621 8219 : m_compress_method = StorageMethod::STORED;
622 : }
623 : else
624 : {
625 71498 : m_compress_method = method;
626 : }
627 79717 : }
628 :
629 :
630 : /** \brief Sets the size field for the entry.
631 : *
632 : * This function is used to save the size of this file on disk
633 : * when uncompressed.
634 : *
635 : * \param[in] size The size field is set to this value.
636 : */
637 145423 : void FileEntry::setSize(size_t size)
638 : {
639 145423 : m_uncompressed_size = size;
640 145423 : }
641 :
642 :
643 : /** \brief Set the FileEntry time using a DOS time.
644 : *
645 : * This function saves the specified \p dostime value as the last modification
646 : * date and time of this entry. This is generally used when reading that information
647 : * from a Zip archive. Otherwise you probably want to use the setUnixTime()
648 : * instead since it is one to one compatible with the value handle by time(),
649 : * stat(), and other OS functions.
650 : *
651 : * \param[in] dostime Set time field as is using this MSDOS date/time value.
652 : */
653 24 : void FileEntry::setTime(dostime_t dostime)
654 : {
655 24 : setUnixTime(dos2unixtime(dostime));
656 24 : }
657 :
658 :
659 : /** \brief Sets the time field in Unix time format for the entry.
660 : *
661 : * This function is used to set the last modification time of this
662 : * entry. In most cases this comes from the stat structure field
663 : * named st_mtime. If you are creating a file directly in memory,
664 : * you may use the return value of <code>time(nullptr);</code>.
665 : *
666 : * \param[in] time The time field is set to the specified value.
667 : */
668 48 : void FileEntry::setUnixTime(std::time_t time)
669 : {
670 48 : m_unix_time = time;
671 48 : }
672 :
673 :
674 : /** \brief Returns a human-readable string representation of the entry.
675 : *
676 : * This function transforms the basic information of the entry in a
677 : * string. Note that most of the information is lost as the function
678 : * is likely to only display the filename and the size of the file,
679 : * nothing more.
680 : *
681 : * \return A human-readable string representation of the entry.
682 : */
683 716 : std::string FileEntry::toString() const
684 : {
685 716 : OutputStringStream sout;
686 716 : sout << m_filename;
687 716 : if(isDirectory())
688 : {
689 24 : sout << " (directory)";
690 : }
691 : else
692 : {
693 692 : sout << " ("
694 1384 : << m_uncompressed_size << " byte"
695 1384 : << (m_uncompressed_size == 1 ? "" : "s");
696 692 : size_t const compressed_size(getCompressedSize());
697 692 : if(compressed_size != m_uncompressed_size)
698 : {
699 : // this is not currently accessible since only the
700 : // ZipLocalEntry and ZipCentralDirectoryEntry have
701 : // a compressed size
702 : sout << ", " // LCOV_EXCL_LINE
703 : << compressed_size << " byte" // LCOV_EXCL_LINE
704 : << (compressed_size == 1 ? "" : "s") // LCOV_EXCL_LINE
705 : << " compressed"; // LCOV_EXCL_LINE
706 : }
707 692 : sout << ")";
708 : }
709 716 : return sout.str();
710 : }
711 :
712 :
713 : /** \brief Read this FileEntry from the input stream.
714 : *
715 : * This function is called when the FileEntry should be initialized from
716 : * the specified input stream.
717 : *
718 : * \exception IOException
719 : * The default implementation raise an IOException error because there is
720 : * no reading the FileEntry from anywhere.
721 : *
722 : * \param[in,out] is The input stream.
723 : */
724 25690 : void FileEntry::read(std::istream& is)
725 : {
726 : static_cast<void>(is);
727 25690 : throw IOException("FileEntry::read(): read not available with this type of FileEntry.");
728 : }
729 :
730 :
731 : /** \brief Write this FileEntry to the output stream.
732 : *
733 : * This function is called when the FileEntry should be saved in the
734 : * specified output stream.
735 : *
736 : * \exception IOException
737 : * The default implementation raise an IOException error because there is
738 : * no writing the FileEntry anywhere.
739 : *
740 : * \param[in,out] os The output stream.
741 : */
742 25690 : void FileEntry::write(std::ostream& os)
743 : {
744 : static_cast<void>(os);
745 25690 : throw IOException("FileEntry::write(): write not available with this type of FileEntry.");
746 : }
747 :
748 :
749 : /** \brief Output an entry as a string to a stream.
750 : *
751 : * This function transforms the FileEntry into a string and prints
752 : * the result to the specified output stream.
753 : *
754 : * \param[in,out] os The output stream.
755 : * \param[in] entry The entry to print out.
756 : *
757 : * \return A reference to the output stream.
758 : */
759 1 : std::ostream& operator << (std::ostream& os, FileEntry const& entry)
760 : {
761 1 : os << entry.toString();
762 1 : return os;
763 : }
764 :
765 :
766 3 : } // namespace
767 :
768 : // Local Variables:
769 : // mode: cpp
770 : // indent-tabs-mode: nil
771 : // c-basic-offset: 4
772 : // tab-width: 4
773 : // End:
774 :
775 : // vim: ts=4 sw=4 et
|