File indexing completed on 2024-05-12 16:23:28
0001 /*************************************************************************** 0002 * Copyright (C) 2013-2017 by Linuxstopmotion contributors; * 0003 * see the AUTHORS file for details. * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 * * 0010 * This program is distributed in the hope that it will be useful, * 0011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0013 * GNU General Public License for more details. * 0014 * * 0015 * You should have received a copy of the GNU General Public License * 0016 * along with this program; if not, write to the * 0017 * Free Software Foundation, Inc., * 0018 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0019 ***************************************************************************/ 0020 0021 #include "filelogger.h" 0022 #include "commandlogger.h" 0023 0024 #include <stdio.h> 0025 #include <string.h> 0026 #include <string> 0027 0028 class FileCommandLoggerImpl : public CommandLogger { 0029 FILE* fh; 0030 std::string buffer; 0031 std::string::size_type committedUpTo; 0032 public: 0033 void close() { 0034 if (fh) { 0035 flush(); 0036 fclose(fh); 0037 } 0038 fh = 0; 0039 } 0040 void flush() { 0041 if (!fh) { 0042 buffer.erase(0, committedUpTo); 0043 committedUpTo = 0; 0044 return; 0045 } 0046 while (0 < committedUpTo) { 0047 ssize_t s = fwrite(buffer.c_str(), 1, committedUpTo, fh); 0048 if (s <= 0) { 0049 throw LoggerWriteFailedException(ferror(fh)); 0050 } 0051 buffer.erase(0, s); 0052 committedUpTo -= s; 0053 } 0054 fflush(fh); 0055 } 0056 FileCommandLoggerImpl() : fh(0), committedUpTo(0) { 0057 } 0058 ~FileCommandLoggerImpl() { 0059 close(); 0060 } 0061 void setLogFile(FILE* f) { 0062 close(); 0063 fh = f; 0064 } 0065 FILE* getLogFile() const { 0066 return fh; 0067 } 0068 void deleteUncommitted() { 0069 buffer.resize(committedUpTo); 0070 } 0071 void writePendingCommand(const char* text) { 0072 deleteUncommitted(); 0073 buffer.append(text); 0074 buffer.append("!\n"); 0075 } 0076 void writePendingUndo() { 0077 deleteUncommitted(); 0078 buffer.append("?\n"); 0079 } 0080 void writePendingRedo() { 0081 deleteUncommitted(); 0082 buffer.append("!\n"); 0083 } 0084 void commit() { 0085 committedUpTo = buffer.length(); 0086 flush(); 0087 } 0088 }; 0089 0090 FileCommandLogger::FileCommandLogger() { 0091 pImpl = new FileCommandLoggerImpl; 0092 } 0093 0094 FileCommandLogger::~FileCommandLogger() { 0095 delete pImpl; 0096 } 0097 0098 void FileCommandLogger::setLogFile(FILE* f) { 0099 pImpl->setLogFile(f); 0100 } 0101 0102 FILE* FileCommandLogger::getLogFile() const { 0103 return pImpl->getLogFile(); 0104 } 0105 0106 CommandLogger* FileCommandLogger::getLogger() { 0107 return pImpl; 0108 } 0109 0110 const CommandLogger* FileCommandLogger::getLogger() const { 0111 return pImpl; 0112 } 0113 0114 LoggerWriteFailedException::LoggerWriteFailedException(int error) { 0115 snprintf(msg, sizeof(msg), 0116 "Failed to write to command logger (%s)!\n" 0117 "Disaster recovery will be impossible after this point!", 0118 strerror(error)); 0119 } 0120 0121 const char* LoggerWriteFailedException::what() const throw() { 0122 return msg; 0123 }