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 }