| //##################################################################### |
| // Copyright 2002-2004, Ronald Fedkiw, Eran Guendelman, Geoffrey Irving, Igor Neverov, Andrew Selle. |
| // This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt. |
| //##################################################################### |
| // Namespace FILE_UTILITIES |
| //##################################################################### |
| #ifndef __FILE_UTILITIES__ |
| #define __FILE_UTILITIES__ |
| #include <fstream> |
| |
| #include <cstdlib> |
| |
| #include "READ_WRITE_FUNCTIONS.h" |
| #include "../Utilities/STRING_UTILITIES.h" |
| namespace PhysBAM |
| { |
| namespace FILE_UTILITIES |
| { |
| |
| //##################################################################### |
| // ADD NEW FILE EXTENSIONS HERE |
| // The enumeration should match the file_extensions array, and |
| // UNKNOWN_FILE should be matched with a 0 in the array. |
| enum FILE_TYPE {RGD_FILE, RGD2D_FILE, TRI_FILE, PHI_FILE, PHI2D_FILE, OCT_FILE, PLY_FILE, PLY2D_FILE, RGB_FILE, TRI2D_FILE, CURVE_FILE, CURVE2D_FILE, TET_FILE, HEX_FILE, UNKNOWN_FILE}; |
| static const char *file_extensions[] = {"rgd", "rgd2d", "tri", "phi", "phi2d", "oct", "ply", "ply2d", "rgb", "tri2d", "curve", "curve2d", "tet", "hex", 0}; |
| //##################################################################### |
| |
| //################################################################### |
| // Platform Specific Function Definitions |
| //################################################################### |
| bool Directory_Exists (const std::string& dirname); |
| bool Create_Directory (const std::string& dirname, bool exit_on_fail = true); |
| std::string Real_Path (const std::string& path); |
| int Compare_File_Times_Ignoring_Compression_Suffix (const std::string& filename1, const std::string& filename2); |
| std::istream* Safe_Open_Input (const std::string& filename, bool binary = true, bool exit_on_fail = true); |
| std::ostream* Safe_Open_Output (const std::string& filename, bool binary = true, bool exit_on_fail = true); |
| //################################################################### |
| // Platform Compare_File_Times |
| //################################################################### |
| int Compare_File_Times (const std::string& filename1, const std::string& filename2); |
| //################################################################### |
| // Platform Non-Specific Function Definitions |
| //################################################################### |
| inline std::string Get_File_Extension_Ignoring_Compression_Suffix (const std::string &filename) |
| { |
| std::string::size_type lastperiod = filename.rfind ('.'), lastslash = filename.rfind ('/'); |
| |
| if (lastperiod != std::string::npos && (lastslash == std::string::npos || lastperiod > lastslash)) return filename.substr (lastperiod + 1); |
| else return ""; |
| } |
| |
| inline std::string Get_Basename_Ignoring_Compression_Suffix (const std::string& filename) |
| { |
| std::string::size_type lastperiod = filename.rfind ("."); |
| std::string::size_type lastslash = filename.rfind ("/"); |
| |
| if (lastperiod != std::string::npos && (lastslash == std::string::npos || lastperiod > lastslash)) return filename.substr (0, lastperiod); |
| else return filename; |
| } |
| |
| inline bool File_Extension_Matches_Ignoring_Compression_Suffix (const std::string& filename, const std::string& ext, const bool case_sensitive = true) |
| { |
| return !STRING_UTILITIES::Compare_Strings (Get_File_Extension_Ignoring_Compression_Suffix (filename), ext, case_sensitive); |
| } |
| |
| inline bool File_Is_Compressed (const std::string& filename) |
| { |
| return File_Extension_Matches_Ignoring_Compression_Suffix (filename, "gz"); |
| } |
| |
| inline bool File_Exists_Ignoring_Compression_Suffix (const std::string& filename) |
| { |
| return !!std::ifstream (filename.c_str()); |
| } |
| |
| inline bool File_Exists (const std::string& filename) |
| { |
| return File_Exists_Ignoring_Compression_Suffix (filename) || (!File_Is_Compressed (filename) && File_Exists_Ignoring_Compression_Suffix (filename + ".gz")); |
| } |
| |
| inline bool File_Writable_Ignoring_Compression_Suffix (const std::string& filename) |
| { |
| return !!std::ofstream (filename.c_str()); |
| } |
| |
| inline bool File_Writable (const std::string& filename) |
| { |
| return File_Writable_Ignoring_Compression_Suffix (filename) || (!File_Is_Compressed (filename) && File_Writable_Ignoring_Compression_Suffix (filename + ".gz")); |
| } |
| |
| inline std::string Strip_Compression_Suffix (const std::string& filename) |
| { |
| if (File_Is_Compressed (filename)) return Get_Basename_Ignoring_Compression_Suffix (filename); |
| else return filename; |
| } |
| |
| inline std::string Real_File (const std::string& filename) |
| { |
| if (File_Exists_Ignoring_Compression_Suffix (filename)) return filename; |
| else if (!File_Is_Compressed (filename) && File_Exists_Ignoring_Compression_Suffix (filename + ".gz")) return filename + ".gz"; |
| else return ""; |
| } |
| |
| inline bool File_Extension_Matches (const std::string& filename, const std::string& ext, const bool case_sensitive = true) |
| { |
| return File_Extension_Matches_Ignoring_Compression_Suffix (Strip_Compression_Suffix (filename), ext, case_sensitive); |
| } |
| |
| inline FILE_TYPE Get_File_Type_Ignoring_Compression_Suffix (const std::string& filename) |
| { |
| std::string ext = Get_File_Extension_Ignoring_Compression_Suffix (filename); |
| |
| for (int i = 0; file_extensions[i]; i++) if (ext == file_extensions[i]) return (FILE_TYPE) i; |
| |
| return UNKNOWN_FILE; |
| } |
| |
| inline FILE_TYPE Get_File_Type (const std::string& filename) |
| { |
| return Get_File_Type_Ignoring_Compression_Suffix (Strip_Compression_Suffix (filename)); |
| } |
| |
| inline bool File_Type_Matches_Ignoring_Compression_Suffix (const std::string& filename, FILE_TYPE type) |
| { |
| return File_Extension_Matches_Ignoring_Compression_Suffix (filename, file_extensions[ (int) type]); |
| } |
| |
| inline bool File_Type_Matches (const std::string& filename, FILE_TYPE type) |
| { |
| return File_Type_Matches_Ignoring_Compression_Suffix (Strip_Compression_Suffix (filename), type); |
| } |
| |
| inline bool Is_Rgd_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, RGD_FILE); |
| } |
| |
| inline bool Is_Rgd2D_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, RGD2D_FILE); |
| } |
| |
| inline bool Is_Tri_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, TRI_FILE); |
| } |
| |
| inline bool Is_Tet_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, TET_FILE); |
| } |
| |
| inline bool Is_Hex_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, HEX_FILE); |
| } |
| |
| inline bool Is_Phi_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, PHI_FILE); |
| } |
| |
| inline bool Is_Phi2D_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, PHI2D_FILE); |
| } |
| |
| inline bool Is_Oct_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, OCT_FILE); |
| } |
| |
| inline bool Is_Ply_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, PLY_FILE); |
| } |
| |
| inline bool Is_Ply2D_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, PLY2D_FILE); |
| } |
| |
| inline bool Is_Rgb_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, RGB_FILE); |
| } |
| |
| inline bool Is_Curve_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, CURVE_FILE); |
| } |
| |
| inline bool Is_Curve2D_File (const std::string& filename) |
| { |
| return File_Type_Matches (filename, CURVE2D_FILE); |
| } |
| |
| inline std::string Get_File_Extension (const std::string &filename) |
| { |
| return Get_File_Extension_Ignoring_Compression_Suffix (Strip_Compression_Suffix (filename)); |
| } |
| |
| inline std::string Get_Basename (const std::string& filename) |
| { |
| return Get_Basename_Ignoring_Compression_Suffix (Strip_Compression_Suffix (filename)); |
| } |
| |
| inline std::string Get_Base_Directory_Name (const std::string& path) |
| { |
| size_t lastslash = path.rfind ('/'); |
| |
| if (lastslash == std::string::npos) return "."; |
| else return path.substr (0, lastslash); |
| } |
| |
| inline std::string Number_To_String (const int i) |
| { |
| return STRING_UTILITIES::string_sprintf ("%d", i); |
| } |
| |
| inline std::string Find_First_Nonexistent_File_In_Sequence (std::string filename_base, std::string filename_suffix, const int id_start = 0, int* id_result = 0) |
| { |
| int i = id_start; |
| |
| while (File_Exists ( (filename_base + Number_To_String (i) + filename_suffix))) ++i; |
| |
| if (id_result) *id_result = i; |
| |
| return filename_base + Number_To_String (i) + filename_suffix; |
| } |
| |
| inline std::string Find_First_Nonexistent_Directory_In_Sequence (std::string directory_name_base, const int id_start = 0, int* id_final = 0) |
| { |
| int id = id_start; |
| |
| while (Directory_Exists ( (directory_name_base + Number_To_String (id)))) ++id; |
| |
| if (id_final) *id_final = id; |
| |
| return directory_name_base + Number_To_String (id); |
| } |
| |
| inline std::string Make_First_Nonexistent_Directory_In_Sequence (std::string directory_name_base, const int id_start = 0, int* id_final = 0) |
| { |
| std::string output_directory = Find_First_Nonexistent_Directory_In_Sequence (directory_name_base, id_start, id_final); |
| |
| if (!Create_Directory (output_directory, false)) |
| { |
| std::cerr << "Can't create directory " << output_directory << std::endl; |
| exit (1); |
| } |
| else std::cout << "Created directory " << output_directory << std::endl; |
| |
| return output_directory; |
| } |
| //################################################################### |
| // Utilities for "animated" files (files with %d for frame number) |
| //################################################################### |
| inline bool Is_Animated (const std::string &filename) |
| { |
| return filename.find ("%d") != std::string::npos; |
| } |
| |
| inline std::string Get_Frame_Filename (const std::string &filename, int frame) |
| { |
| return Is_Animated (filename) ? STRING_UTILITIES::string_sprintf (filename.c_str(), frame) : filename; |
| } |
| |
| inline bool Frame_File_Exists (const std::string &filename, int frame) |
| { |
| return File_Exists (Get_Frame_Filename (filename, frame)); |
| } |
| //##################################################################### |
| // Read_From_File |
| //##################################################################### |
| // Convenience functions |
| template<class RW, class T1> |
| inline void Read_From_File (const std::string& filename, T1& d1) |
| { |
| std::istream* input = Safe_Open_Input (filename); |
| Read_Binary<RW> (*input, d1); |
| delete input; |
| } |
| template<class RW, class T1, class T2> |
| inline void Read_From_File (const std::string& filename, T1& d1, T2& d2) |
| { |
| std::istream* input = Safe_Open_Input (filename); |
| Read_Binary<RW> (*input, d1, d2); |
| delete input; |
| } |
| template<class RW, class T1, class T2, class T3> |
| inline void Read_From_File (const std::string& filename, T1& d1, T2& d2, T3& d3) |
| { |
| std::istream* input = Safe_Open_Input (filename); |
| Read_Binary<RW> (*input, d1, d2, d3); |
| delete input; |
| } |
| template<class RW, class T1, class T2, class T3, class T4> |
| inline void Read_From_File (const std::string& filename, T1& d1, T2& d2, T3& d3, T4& d4) |
| { |
| std::istream* input = Safe_Open_Input (filename); |
| Read_Binary<RW> (*input, d1, d2, d3, d4); |
| delete input; |
| } |
| template<class RW, class T1, class T2, class T3, class T4, class T5> |
| inline void Read_From_File (const std::string& filename, T1& d1, T2& d2, T3& d3, T4& d4, T5& d5) |
| { |
| std::istream* input = Safe_Open_Input (filename); |
| Read_Binary<RW> (*input, d1, d2, d3, d4, d5); |
| delete input; |
| } |
| template<class RW, class T1, class T2, class T3, class T4, class T5, class T6> |
| inline void Read_From_File (const std::string& filename, T1& d1, T2& d2, T3& d3, T4& d4, T5& d5, T6& d6) |
| { |
| std::istream* input = Safe_Open_Input (filename); |
| Read_Binary<RW> (*input, d1, d2, d3, d4, d5, d6); |
| delete input; |
| } |
| //##################################################################### |
| // Write_To_File |
| //##################################################################### |
| // Convenience functions |
| template<class RW, class T1> |
| inline void Write_To_File (const std::string& filename, const T1& d1) |
| { |
| std::ostream* output = Safe_Open_Output (filename); |
| Write_Binary<RW> (*output, d1); |
| delete output; |
| } |
| template<class RW, class T1, class T2> |
| inline void Write_To_File (const std::string& filename, const T1& d1, const T2& d2) |
| { |
| std::ostream* output = Safe_Open_Output (filename); |
| Write_Binary<RW> (*output, d1, d2); |
| delete output; |
| } |
| template<class RW, class T1, class T2, class T3> |
| inline void Write_To_File (const std::string& filename, const T1& d1, const T2& d2, const T3& d3) |
| { |
| std::ostream* output = Safe_Open_Output (filename); |
| Write_Binary<RW> (*output, d1, d2, d3); |
| delete output; |
| } |
| template<class RW, class T1, class T2, class T3, class T4> |
| inline void Write_To_File (const std::string& filename, const T1& d1, const T2& d2, const T3& d3, const T4& d4) |
| { |
| std::ostream* output = Safe_Open_Output (filename); |
| Write_Binary<RW> (*output, d1, d2, d3, d4); |
| delete output; |
| } |
| template<class RW, class T1, class T2, class T3, class T4, class T5> |
| inline void Write_To_File (const std::string& filename, const T1& d1, const T2& d2, const T3& d3, const T4& d4, const T5& d5) |
| { |
| std::ostream* output = Safe_Open_Output (filename); |
| Write_Binary<RW> (*output, d1, d2, d3, d4, d5); |
| delete output; |
| } |
| template<class RW, class T1, class T2, class T3, class T4, class T5, class T6> |
| inline void Write_To_File (const std::string& filename, const T1& d1, const T2& d2, const T3& d3, const T4& d4, const T5& d5, const T6& d6) |
| { |
| std::ostream* output = Safe_Open_Output (filename); |
| Write_Binary<RW> (*output, d1, d2, d3, d4, d5, d6); |
| delete output; |
| } |
| //##################################################################### |
| // Read_From_Text_File |
| //##################################################################### |
| // Convenience function |
| template<class T1> |
| inline void Read_From_Text_File (const std::string& filename, T1& d1) |
| { |
| std::istream* input = Safe_Open_Input (filename, false); |
| *input >> d1; |
| delete input; |
| } |
| //##################################################################### |
| // Write_To_Text_File |
| //##################################################################### |
| // Convenience function |
| template<class T1> |
| inline void Write_To_Text_File (const std::string& filename, const T1& d1) |
| { |
| std::ostream* output = Safe_Open_Output (filename, false); |
| *output << d1; |
| delete output; |
| } |
| //##################################################################### |
| // Create_From_File |
| //##################################################################### |
| template<class RW, class T> |
| inline void Create_From_File (const std::string& filename, T*& d) |
| { |
| d = T::Create(); |
| Read_From_File<RW> (filename, *d); |
| } |
| //##################################################################### |
| } |
| } |
| #endif |