ancient.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* Copyright (C) Teemu Suutari */
  2. #ifndef ANCIENT_ANCIENT_HPP
  3. #define ANCIENT_ANCIENT_HPP
  4. #ifndef ANCIENT_API
  5. #if defined(ANCIENT_API_DECLSPEC_DLLEXPORT)
  6. #define ANCIENT_API __declspec(dllexport)
  7. #endif
  8. #if defined(ANCIENT_API_DECLSPEC_DLLIMPORT)
  9. #define ANCIENT_API __declspec(dllimport)
  10. #endif
  11. #if defined(ANCIENT_API_VISIBILITY_DEFAULT_USED)
  12. #define ANCIENT_API __attribute__((visibility("default"))) __attribute__((used))
  13. #endif
  14. #if defined(ANCIENT_API_VISIBILITY_DEFAULT)
  15. #define ANCIENT_API __attribute__((visibility("default")))
  16. #endif
  17. #if defined(ANCIENT_API_VISIBILITY_HIDDEN)
  18. #define ANCIENT_API __attribute__((visibility("hidden")))
  19. #endif
  20. #ifndef ANCIENT_API
  21. #define ANCIENT_API
  22. #endif
  23. #endif
  24. #include <exception>
  25. #include <memory>
  26. #include <optional>
  27. #include <string>
  28. #include <vector>
  29. #include <cstddef>
  30. #include <cstdint>
  31. namespace ancient
  32. {
  33. namespace internal
  34. {
  35. namespace APIv2
  36. {
  37. class DecompressorImpl;
  38. }
  39. }
  40. inline namespace APIv2
  41. {
  42. // just a base class to easily catch all the errors
  43. class ANCIENT_API Error : public std::exception
  44. {
  45. public:
  46. Error() noexcept;
  47. virtual ~Error();
  48. };
  49. class ANCIENT_API InvalidFormatError : public Error
  50. {
  51. public:
  52. InvalidFormatError() noexcept;
  53. virtual ~InvalidFormatError();
  54. };
  55. class ANCIENT_API DecompressionError : public Error
  56. {
  57. public:
  58. DecompressionError() noexcept;
  59. virtual ~DecompressionError();
  60. };
  61. class ANCIENT_API VerificationError : public Error
  62. {
  63. public:
  64. VerificationError() noexcept;
  65. virtual ~VerificationError();
  66. };
  67. class ANCIENT_API Decompressor final
  68. {
  69. public:
  70. // Detect signature whether it matches to any known compressor
  71. // This does not guarantee the data is decompressable though, only signature is read
  72. static bool detect(const std::vector<uint8_t> &packedData) noexcept;
  73. static bool detect(const uint8_t *packedData,size_t packedSize) noexcept;
  74. // Main entrypoint
  75. // if verify=true then check the packedData for errors: CRC or other checksum if available
  76. // check exactSizeKnown from size documentation
  77. // can throw InvalidFormatError if stream is not recognized or it is invalid
  78. // can throw VerificationError if verify enabled and checksum does not match
  79. explicit Decompressor(const std::vector<uint8_t> &packedData,bool exactSizeKnown,bool verify);
  80. explicit Decompressor(const uint8_t *packedData,size_t packedSize,bool exactSizeKnown,bool verify);
  81. // Name returned is human readable long name
  82. const std::string &getName() const noexcept;
  83. // the functions are there to protect against "accidental" large files when parsing headers
  84. // a.k.a. 16M should be enough for everybody (sizes do not have to accurate i.e.
  85. // compressors can exclude header content for simplification)
  86. // This entirely ok for the context of "old computers" and their files,
  87. // for other usages these need to be tuned up
  88. static size_t getMaxPackedSize() noexcept;
  89. static size_t getMaxRawSize() noexcept;
  90. // PackedSize or RawSize are taken from the stream if available, std::nullopt otherwise.
  91. // for those compressors having no known sizes, running decompression will update
  92. // the values.
  93. // There are exceptions: Some decompressors need to exact size of the packed data
  94. // in order to decompress. For those providing a indefinitely size packed stream
  95. // will not work
  96. // use the "exactSizeKnown" flag for create to tell whether you know the size or not
  97. std::optional<size_t> getPackedSize() const noexcept;
  98. std::optional<size_t> getRawSize() const noexcept;
  99. // in case of disk image based formats the data does not necessarily start
  100. // from logical beginnig of the image but it is offsetted inside the logical image (f.e. DMS).
  101. // getDataOffset will return the offset which can also be 0, or std::nullopt if not image-based format.
  102. // getImageSize will return the size of the the logical image, or std::nullopt if not image-based format.
  103. std::optional<size_t> getImageSize() const noexcept;
  104. std::optional<size_t> getImageOffset() const noexcept;
  105. // Actual decompression.
  106. // verify checksum if verify==true
  107. // can throw DecompressionError if stream cant be unpacked
  108. // can throw VerificationError if verify enabled and checksum does not match
  109. std::vector<uint8_t> decompress(bool verify);
  110. ~Decompressor();
  111. private:
  112. std::unique_ptr<internal::APIv2::DecompressorImpl> m_impl;
  113. private:
  114. Decompressor(const Decompressor&)=delete;
  115. Decompressor& operator=(const Decompressor&)=delete;
  116. };
  117. }
  118. }
  119. #endif