File.h 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (C) 2009-2015, Panagiotis Christopoulos Charitos.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include "anki/util/String.h"
  7. #include "anki/util/Enum.h"
  8. #include "anki/util/NonCopyable.h"
  9. #include <cstdio>
  10. namespace anki {
  11. // Undefine some flags because someone else is polluting the global namespace
  12. #if defined(LITTLE_ENDIAN)
  13. # undef LITTLE_ENDIAN
  14. #endif
  15. #if defined(BIG_ENDIAN)
  16. # undef BIG_ENDIAN
  17. #endif
  18. /// @addtogroup util_file
  19. /// @{
  20. /// An abstraction over typical files and files in ziped archives. This class
  21. /// can read from regular C files, zip files and on Android from the packed
  22. /// asset files.
  23. /// To identify the file:
  24. /// - If the path contains ".ankizip" (eg /path/to/arch.ankizip/path/file.ext)
  25. /// it tries to open the archive and read the file from there.
  26. /// - If the filename starts with '$' it will try to load a system specific
  27. /// file. For Android this is a file in the .apk
  28. /// - If the above are false then try to load a regular C file
  29. class File: public NonCopyable
  30. {
  31. public:
  32. /// Open mode
  33. enum class OpenFlag: U8
  34. {
  35. NONE = 0,
  36. READ = 1 << 0,
  37. WRITE = 1 << 1,
  38. APPEND = WRITE | (1 << 3),
  39. BINARY = 1 << 4,
  40. LITTLE_ENDIAN = 1 << 5, ///< The default
  41. BIG_ENDIAN = 1 << 6
  42. };
  43. ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(OpenFlag, friend);
  44. /// Passed to seek function
  45. enum class SeekOrigin
  46. {
  47. BEGINNING = SEEK_SET,
  48. CURRENT = SEEK_CUR,
  49. END = SEEK_END
  50. };
  51. /// Default constructor
  52. File() = default;
  53. /// Move
  54. File(File&& b)
  55. {
  56. *this = std::move(b);
  57. }
  58. /// Closes the file if it's open
  59. ~File();
  60. /// Move
  61. File& operator=(File&& b);
  62. /// Open a file.
  63. /// @param[in] filename The file to open
  64. /// @param[in] openMask The open flags. It's a combination of OpenFlag enum
  65. ANKI_USE_RESULT Error open(const CString& filename, OpenFlag openMask);
  66. /// Return true if the file is oppen
  67. Bool isOpen() const
  68. {
  69. return m_file != nullptr;
  70. }
  71. /// Close the file
  72. void close();
  73. /// Flush pending operations
  74. ANKI_USE_RESULT Error flush();
  75. /// Read data from the file
  76. ANKI_USE_RESULT Error read(void* buff, PtrSize size);
  77. /// Read all the contents of a text file
  78. /// If the file is not rewined it will probably fail
  79. ANKI_USE_RESULT Error readAllText(
  80. GenericMemoryPoolAllocator<U8> alloc, String& out);
  81. /// Read all the contents of a text file
  82. /// If the file is not rewined it will probably fail
  83. ANKI_USE_RESULT Error readAllText(StringAuto& out);
  84. /// Read 32bit unsigned integer. Set the endianness if the file's
  85. /// endianness is different from the machine's
  86. ANKI_USE_RESULT Error readU32(U32& u);
  87. /// Read 32bit float. Set the endianness if the file's endianness is
  88. /// different from the machine's
  89. ANKI_USE_RESULT Error readF32(F32& f);
  90. /// Write data to the file
  91. ANKI_USE_RESULT Error write(void* buff, PtrSize size);
  92. /// Write formated text
  93. ANKI_USE_RESULT Error writeText(CString format, ...);
  94. /// Set the position indicator to a new position
  95. /// @param offset Number of bytes to offset from origin
  96. /// @param origin Position used as reference for the offset
  97. ANKI_USE_RESULT Error seek(PtrSize offset, SeekOrigin origin);
  98. /// The the size of the file.
  99. PtrSize getSize() const;
  100. private:
  101. /// Internal filetype
  102. enum class Type: U8
  103. {
  104. NONE = 0,
  105. C, ///< C file
  106. ZIP, ///< Ziped file
  107. SPECIAL ///< For example file is located in the android apk
  108. };
  109. void* m_file = nullptr; ///< A native file type
  110. Type m_type = Type::NONE;
  111. OpenFlag m_flags = OpenFlag::NONE; ///< All the flags. Set on open
  112. U32 m_size = 0;
  113. /// Get the current machine's endianness
  114. static OpenFlag getMachineEndianness();
  115. /// Get the type of the file
  116. ANKI_USE_RESULT Error identifyFile(const CString& filename,
  117. char* archiveFilename, PtrSize archiveFilenameSize,
  118. CString& filenameInArchive, Type& type);
  119. /// Open a C file
  120. ANKI_USE_RESULT Error openCFile(const CString& filename, OpenFlag flags);
  121. /// Open an archive and the file inside
  122. /// @param[in] archive The filename of the archive
  123. /// @param[in] archived The filename of the file inside the archive
  124. ANKI_USE_RESULT Error openZipFile(
  125. const CString& archive, const CString& archived, OpenFlag flags);
  126. #if ANKI_OS == ANKI_OS_ANDROID
  127. /// Open an Android file
  128. ANKI_USE_RESULT Error openAndroidFile(
  129. const CString& filename, OpenFlag flags);
  130. #endif
  131. void zero()
  132. {
  133. m_file = nullptr;
  134. m_type = Type::NONE;
  135. m_flags = OpenFlag::NONE;
  136. m_size = 0;
  137. }
  138. };
  139. /// @}
  140. } // end namespace anki