~adrian-arroyocalle/freerct/freerct

« back to all changes in this revision

Viewing changes to src/rcdgen/file_writing.cpp

  • Committer: charlespigott at googlemail
  • Date: 2013-07-09 17:30:05 UTC
  • Revision ID: svn-v4:d3bf82d2-0c16-e458-5408-27be57bd1276:trunk:780
-Codechange: Reorganise the project files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id$ */
 
2
 
 
3
/*
 
4
 * This file is part of FreeRCT.
 
5
 * FreeRCT 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.
 
6
 * FreeRCT 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.
 
7
 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with FreeRCT. If not, see <http://www.gnu.org/licenses/>.
 
8
 */
 
9
 
 
10
/** @file file_writing.cpp File write code. */
 
11
 
 
12
#include "../../src/stdafx.h"
 
13
#include "file_writing.h"
 
14
 
 
15
 
 
16
FileBlock::FileBlock()
 
17
{
 
18
        this->data = NULL;
 
19
        this->length = 0;
 
20
}
 
21
 
 
22
FileBlock::~FileBlock()
 
23
{
 
24
        free(this->data);
 
25
}
 
26
 
 
27
/**
 
28
 * Setup storing of data to the file block.
 
29
 * Supply name of the block, version number, and expected data length (without the 12 byte header).
 
30
 * After setup, use #SaveUInt8, #SaveUInt16, #SaveUInt32, and #SaveBytes to store the data in the block.
 
31
 * Afterwards, use #CheckEndSave to verify the amount of actually written data matches with the expected length.
 
32
 * @param blk_name Name of the block (a 4 character text string).
 
33
 * @param version Version of the block.
 
34
 * @param data_length Length of the data part (that is, excluding the header).
 
35
 */
 
36
void FileBlock::StartSave(const char *blk_name, int version, int data_length)
 
37
{
 
38
        this->length = data_length + 12; // Add length of the header.
 
39
        free(this->data);
 
40
        this->data = (uint8 *)malloc(this->length);
 
41
        this->save_index = 0;
 
42
 
 
43
        assert(strlen(blk_name) == 4);
 
44
        this->SaveBytes((uint8 *)blk_name, 4);
 
45
        this->SaveUInt32(version);
 
46
        this->SaveUInt32(data_length);
 
47
}
 
48
 
 
49
/**
 
50
 * Save a 8 bit unsigned value into the file block.
 
51
 * @param d Value to write.
 
52
 */
 
53
void FileBlock::SaveUInt8(uint8 d)
 
54
{
 
55
        assert(this->save_index < this->length);
 
56
        this->data[this->save_index] = d;
 
57
        this->save_index++;
 
58
}
 
59
 
 
60
/**
 
61
 * Save a 8 bit signed value into the file block.
 
62
 * @param d Value to write.
 
63
 */
 
64
void FileBlock::SaveInt8(int8 d)
 
65
{
 
66
        this->SaveUInt8(d);
 
67
}
 
68
 
 
69
/**
 
70
 * Save a 16 bit unsigned value into the file block.
 
71
 * @param d Value to write.
 
72
 */
 
73
void FileBlock::SaveUInt16(uint16 d)
 
74
{
 
75
        this->SaveUInt8(d);
 
76
        this->SaveUInt8(d >> 8);
 
77
}
 
78
/**
 
79
 * Save a 16 bit signed value into the file block.
 
80
 * @param d Value to write.
 
81
 */
 
82
void FileBlock::SaveInt16(uint16 d)
 
83
{
 
84
        this->SaveUInt8(d);
 
85
        this->SaveUInt8(d >> 8);
 
86
}
 
87
 
 
88
/**
 
89
 * Save a 32 bit unsigned value into the file block.
 
90
 * @param d Value to write.
 
91
 */
 
92
void FileBlock::SaveUInt32(uint32 d)
 
93
{
 
94
        this->SaveUInt16(d);
 
95
        this->SaveUInt16(d >> 16);
 
96
}
 
97
 
 
98
/**
 
99
 * Save a sequence of bytes in the file block.
 
100
 * @param data Start address of the data.
 
101
 * @param size Length of the data.
 
102
 */
 
103
void FileBlock::SaveBytes(uint8 *data, int size)
 
104
{
 
105
        while (size > 0) {
 
106
                this->SaveUInt8(*data);
 
107
                data++;
 
108
                size--;
 
109
        }
 
110
}
 
111
 
 
112
/** Check that all data has been written. */
 
113
void FileBlock::CheckEndSave()
 
114
{
 
115
        assert(this->save_index == this->length);
 
116
}
 
117
 
 
118
/**
 
119
 * Write the file block to the output.
 
120
 * @param fp File handle to write to.
 
121
 */
 
122
void FileBlock::Write(FILE *fp)
 
123
{
 
124
        if (this->length == 0) return;
 
125
 
 
126
        if ((int)fwrite(this->data, 1, this->length, fp) != this->length) {
 
127
                fprintf(stderr, "Failed to write RCD block\n");
 
128
                exit(1);
 
129
        }
 
130
}
 
131
 
 
132
/**
 
133
 * Check whether two file blocks are identical.
 
134
 * @param fb1 First block to compare.
 
135
 * @param fb2 Second block to compare.
 
136
 * @return Whether both blocks are the same.
 
137
 */
 
138
bool operator==(const FileBlock &fb1, const FileBlock &fb2)
 
139
{
 
140
        if (fb1.length != fb2.length) return false;
 
141
        if (fb1.length == 0) return true;
 
142
        return memcmp(fb1.data, fb2.data, fb1.length) == 0;
 
143
}
 
144
 
 
145
FileWriter::FileWriter()
 
146
{
 
147
}
 
148
 
 
149
FileWriter::~FileWriter()
 
150
{
 
151
        for (FileBlockPtrList::iterator iter = this->blocks.begin(); iter != this->blocks.end(); iter++) {
 
152
                delete *iter;
 
153
        }
 
154
}
 
155
 
 
156
/**
 
157
 * Add a block to the file.
 
158
 * @param blk Block to add.
 
159
 * @return Block index number where the block is stored in the file.
 
160
 */
 
161
int FileWriter::AddBlock(FileBlock *blk)
 
162
{
 
163
        int idx = 1;
 
164
        FileBlockPtrList::iterator iter = this->blocks.begin();
 
165
        while (iter != this->blocks.end()) {
 
166
                if (*(*iter) == *blk) { // Block already added, just return the old block number.
 
167
                        delete blk;
 
168
                        return idx;
 
169
                }
 
170
                idx++;
 
171
                iter++;
 
172
        }
 
173
        this->blocks.push_back(blk);
 
174
        return idx;
 
175
}
 
176
 
 
177
/**
 
178
 * Write all blocks of the RCD file to the file.
 
179
 * @param fname Filename to create.
 
180
 */
 
181
void FileWriter::WriteFile(const char *fname)
 
182
{
 
183
        FILE *fp = fopen(fname, "wb");
 
184
        if (fp == NULL) {
 
185
                fprintf(stderr, "Failed to open \"%s\" for writing.", fname);
 
186
                exit(1);
 
187
        }
 
188
 
 
189
        static const uint8 file_header[8] = {'R', 'C', 'D', 'F', 1, 0, 0, 0};
 
190
        if (fwrite(file_header, 1, 8, fp) != 8) {
 
191
                fprintf(stderr, "Failed to write the RCD file header of \"%s\".", fname);
 
192
                exit(1);
 
193
        }
 
194
 
 
195
        for (FileBlockPtrList::iterator iter = this->blocks.begin(); iter != this->blocks.end(); iter++) {
 
196
                (*iter)->Write(fp);
 
197
        }
 
198
        fclose(fp);
 
199
}