Logo Search packages:      
Sourcecode: catcodec version File versions  Download package

io.cpp

Go to the documentation of this file.
/* $Id: io.cpp 20614 2010-08-25 16:39:16Z rubidium $ */

/*
 * catcodec is a tool to decode/encode the sample catalogue for OpenTTD.
 * Copyright (C) 2009  Remko Bijker
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 2.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

/** @file io.cpp Implementation of reading/writing to files */

#include "stdafx.h"
#include "io.hpp"

00026 FileReader::FileReader(string filename, bool binary)
{
      this->file = fopen(filename.c_str(), binary ? "rb" : "r");
      this->filename = filename;

      if (this->file == NULL) {
            throw "Could not open " + filename + " for reading";
      }
}

00036 FileReader::~FileReader()
{
      fclose(this->file);
}

00041 uint8_t FileReader::ReadByte()
{
      uint8_t b;
      this->ReadRaw(&b, 1);
      return b;
}

00048 uint16_t FileReader::ReadWord()
{
      uint16_t b = this->ReadByte();
      return (this->ReadByte() << 8) | b;
}

00054 uint32_t FileReader::ReadDword()
{
      uint32_t b = this->ReadWord();
      return (this->ReadWord() << 16) | b;
}

00060 void FileReader::ReadRaw(uint8_t *in, size_t amount)
{
      if (fread(in, 1, amount, this->file) != amount) {
            throw "Unexpected end of " + this->filename;
      }
}

00067 char *FileReader::ReadLine(char *in, int length)
{
      char *ret = fgets(in, length, this->file);

      /* fgets doesn't guarantee string termination if no newline/EOF is found */
      in[length - 1] = '\0';

      return ret;
}

00077 void FileReader::Seek(uint32_t pos)
{
      if (fseek(this->file, pos, SEEK_SET) != 0) throw "Seeking in " + this->filename + " failed.";
}

00082 uint32_t FileReader::GetPos()
{
      return ftell(this->file);
}

00087 string FileReader::GetFilename() const
{
      return this->filename;
}


00093 FileWriter::FileWriter(string filename, bool binary)
{
      this->filename_new = filename + ".new";
      this->filename = filename;

      this->file = fopen(filename_new.c_str(), binary ? "w+b" : "w+");

      if (this->file == NULL) {
            throw "Could not open " + this->filename_new + " for writing";
      }
}

00105 FileWriter::~FileWriter()
{
      if (this->file != NULL) {
            fclose(this->file);
            unlink(this->filename_new.c_str());
      }
}

00113 void FileWriter::WriteByte(uint8_t data)
{
      this->WriteRaw(&data, 1);
}

00118 void FileWriter::WriteWord(uint16_t data)
{
      this->WriteByte(data & 0xFF);
      this->WriteByte(data >> 8);
}

00124 void FileWriter::WriteDword(uint32_t data)
{
      this->WriteWord(data & 0xFFFF);
      this->WriteWord(data >> 16);
}

00130 void FileWriter::WriteRaw(const uint8_t *out, size_t amount)
{
      assert(this->file != NULL);

      if (fwrite(out, 1, amount, this->file) != amount) {
            throw "Unexpected failure while writing to " + this->filename;
      }
}

00139 void FileWriter::WriteString(const char *format, ...)
{
      assert(this->file != NULL);

      va_list ap;

      va_start(ap, format);
      if (vfprintf(this->file, format, ap) < 0) {
            throw "Unexpected failure while writing to " + this->filename;
      }
      va_end(ap);
}

00152 uint32_t FileWriter::GetPos()
{
      assert(this->file != NULL);

      return ftell(this->file);
}

00159 string FileWriter::GetFilename() const
{
      return this->filename;
}

00164 void FileWriter::Close()
{
      /* First close the .new file */
      fclose(this->file);
      this->file = NULL;

      /* Then remove the existing .bak file */
      string filename_bak = this->filename + ".bak";
      if (unlink(filename_bak.c_str()) != 0 && errno != ENOENT) {
            fprintf(stderr, "Warning: could not remove %s (%s)\n", filename_bak.c_str(), strerror(errno));
      }

      /* Then move the existing file to .bak */
      if (rename(this->filename.c_str(), filename_bak.c_str()) != 0 && errno != ENOENT) {
            fprintf(stderr, "Warning: could not rename %s to %s (%s)\n", this->filename.c_str(), filename_bak.c_str(), strerror(errno));
      }

      /* And finally move the .new file to the actual wanted filename */
      if (rename(this->filename_new.c_str(), this->filename.c_str()) != 0) {
            fprintf(stderr, "Warning: could not rename %s to %s (%s)\n", this->filename_new.c_str(), this->filename.c_str(), strerror(errno));
            throw "Could not close " + this->filename;
      }
}

Generated by  Doxygen 1.6.0   Back to index