File.h 4.7 KB

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