1 /* 2 * Copyright (C) 2002-2020 by the Widelands Development Team 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License 6 * as published by the Free Software Foundation; either version 2 7 * of the License, or (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 * 18 */ 19 20 #ifndef WL_LOGIC_GENERIC_SAVE_HANDLER_H 21 #define WL_LOGIC_GENERIC_SAVE_HANDLER_H 22 23 #include <functional> 24 25 #include "io/filesystem/filesystem.h" 26 27 /** 28 * Class that provides handling all errors for generic file saving. 29 * It stores error codes and error messages. 30 * It can also generate an overview message aimed at a human user. 31 * 32 * The saving routine (what actually writes data to a file system) 33 * must be provided. 34 */ 35 // TODO(Arty): Possibly make it more generic, allowing to provide options 36 // whether to overwrite files, whether to make backups, maybe allow 37 // to provide a naming scheme, etc. 38 class GenericSaveHandler { 39 public: 40 // error constants; also usable as bit masks 41 enum class Error : uint32_t { 42 kNone = 0, 43 kSuccess = 0, 44 kCreatingDirFailed = 1, 45 kBackupFailed = 2, 46 kDeletingBackupFailed = 4, 47 kSavingDataFailed = 8, 48 kCorruptFileLeft = 16, 49 kRestoringBackupFailed = 32, 50 kUnexpectedError = 64, 51 kAllErrors = 127 52 }; 53 GenericSaveHandler(std::function<void (FileSystem &)> do_save,std::string complete_filename,FileSystem::Type type)54 explicit GenericSaveHandler(std::function<void(FileSystem&)> 55 do_save, // function that actually saves data to the filesystem 56 std::string complete_filename, 57 FileSystem::Type type) 58 : do_save_(do_save), 59 complete_filename_(complete_filename), 60 dir_(FileSystem::fs_dirname(complete_filename.c_str())), 61 filename_(FileSystem::fs_filename(complete_filename.c_str())), 62 type_(type), 63 error_(static_cast<Error>(1132)) { 64 } 65 66 /** 67 * Tries to save a file. 68 * 69 * If the file already exists, it will be overwritten but a temporary backup 70 * is made, which will be restored if saving fails and deleted otherwise. 71 * 72 * Catches ALL errors. 73 * 74 * Error messages for all errors are written to the log but also stored. 75 * Stores and returns an error code (bit mask of all occurred errors). 76 */ 77 Error save(); 78 79 // returns the stored error code (of the last saving operation) error()80 Error error() { 81 return error_; 82 } 83 84 // Returns the combination of error_messages (of occurred errors) 85 // specified by a bit mask. 86 std::string error_message(Error error_mask = Error::kAllErrors); 87 88 // Generates a localized formatted message describing the result of 89 // the last saving attempt. 90 // Aimed to be sufficiently informative for a human user. 91 std::string localized_formatted_result_message(); 92 93 private: 94 std::function<void(FileSystem&)> do_save_; 95 std::string complete_filename_; 96 std::string dir_; 97 std::string filename_; 98 FileSystem::Type type_; 99 100 // Backup filename is automatically generated when saving but is also 101 // stored for generating messages containing backup-related things. 102 std::string backup_filename_; 103 104 Error error_; 105 106 static constexpr uint32_t maxErrors_ = 7; 107 static_assert((1ul << maxErrors_) == static_cast<uint32_t>(Error::kAllErrors) + 1, 108 "value of maxErrors_ doesn't match!"); 109 std::string error_msg_[maxErrors_]; 110 111 // Returns the lowest array index of the an error. 112 // Intended for use with single errors to get their array index. 113 uint32_t get_index(Error); 114 115 void clear(); 116 117 // Finds a suitable backup filename and tries to rename a file. 118 // Stores an errorcode and error message (if applicable). 119 void make_backup(); 120 121 // Saves a file. Assumes file doesn't exist yet. 122 // Stores an errorcode and error message (if applicable). 123 void save_file(); 124 }; 125 126 inline constexpr GenericSaveHandler::Error operator|(GenericSaveHandler::Error e1, 127 GenericSaveHandler::Error e2) { 128 return static_cast<GenericSaveHandler::Error>(static_cast<uint32_t>(e1) | 129 static_cast<uint32_t>(e2)); 130 } 131 132 inline constexpr GenericSaveHandler::Error operator&(GenericSaveHandler::Error e1, 133 GenericSaveHandler::Error e2) { 134 return static_cast<GenericSaveHandler::Error>(static_cast<uint32_t>(e1) & 135 static_cast<uint32_t>(e2)); 136 } 137 138 inline GenericSaveHandler::Error& operator|=(GenericSaveHandler::Error& e1, 139 GenericSaveHandler::Error e2) { 140 return e1 = e1 | e2; 141 } 142 143 inline GenericSaveHandler::Error& operator&=(GenericSaveHandler::Error& e1, 144 GenericSaveHandler::Error e2) { 145 return e1 = e1 & e2; 146 } 147 148 #endif // end of include guard: WL_LOGIC_GENERIC_SAVE_HANDLER_H 149