00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <fvutils/fileformat/fvfile.h>
00025
00026 #include <core/exceptions/system.h>
00027
00028 #include <cstring>
00029 #include <cstdio>
00030 #include <cerrno>
00031 #include <netinet/in.h>
00032 #include <sys/time.h>
00033 #ifdef __FreeBSD__
00034 # include <strfunc.h>
00035 #endif
00036
00037 using namespace fawkes;
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 FireVisionDataFile::FireVisionDataFile(unsigned short int magic_token,
00093 unsigned short int version)
00094 {
00095 __header = (fvff_header_t *)calloc(1, sizeof(fvff_header_t));
00096
00097 __magic_token = magic_token;
00098 __version = version;
00099 __comment = strdup("");
00100
00101 _spec_header = NULL;
00102 _spec_header_size = 0;
00103
00104 __owns_blocks = true;
00105
00106 clear();
00107 }
00108
00109
00110
00111 FireVisionDataFile::~FireVisionDataFile()
00112 {
00113 clear();
00114
00115 free(__header);
00116 free(__comment);
00117 if ( _spec_header ) {
00118 free(_spec_header);
00119 }
00120 }
00121
00122
00123
00124
00125
00126 void
00127 FireVisionDataFile::clear()
00128 {
00129 if (__owns_blocks) {
00130 for (__bi = __blocks.begin(); __bi != __blocks.end(); ++__bi) {
00131 delete *__bi;
00132 }
00133 }
00134
00135 __blocks.clear();
00136 memset(__header, 0, sizeof(fvff_header_t));
00137
00138 __header->magic_token = htons(__magic_token);
00139 __header->version = __version;
00140 __header->num_blocks = 0;
00141 #if __BYTE_ORDER == __BIG_ENDIAN
00142 __header->endianess = 1;
00143 #else
00144 __header->endianess = 0;
00145 #endif
00146 free(__comment);
00147 __comment = strdup("");
00148 }
00149
00150
00151
00152
00153
00154 unsigned int
00155 FireVisionDataFile::magic_token()
00156 {
00157 return __header->magic_token;
00158 }
00159
00160
00161
00162
00163
00164 unsigned int
00165 FireVisionDataFile::version()
00166 {
00167 return __header->version;
00168 }
00169
00170
00171
00172
00173
00174 bool
00175 FireVisionDataFile::is_big_endian()
00176 {
00177 return (__header->endianess == 1);
00178 }
00179
00180
00181
00182
00183
00184 bool
00185 FireVisionDataFile::is_little_endian()
00186 {
00187 return (__header->endianess == 0);
00188 }
00189
00190
00191
00192
00193
00194 const char *
00195 FireVisionDataFile::get_comment() const
00196 {
00197 return __comment;
00198 }
00199
00200
00201
00202
00203
00204 void
00205 FireVisionDataFile::set_comment(const char *comment)
00206 {
00207 free(__comment);
00208 __comment = strndup(comment, FVFF_COMMENT_SIZE);
00209 strncpy(__header->comment, comment, FVFF_COMMENT_SIZE);
00210 }
00211
00212
00213
00214
00215
00216
00217
00218 void
00219 FireVisionDataFile::set_owns_blocks(bool owns_blocks)
00220 {
00221 __owns_blocks = owns_blocks;
00222 }
00223
00224
00225
00226
00227
00228 size_t
00229 FireVisionDataFile::num_blocks()
00230 {
00231 return __blocks.size();
00232 }
00233
00234
00235
00236
00237
00238 void
00239 FireVisionDataFile::add_block(FireVisionDataFileBlock *block)
00240 {
00241 __blocks.push_back(block);
00242 }
00243
00244
00245
00246
00247
00248 FireVisionDataFile::BlockList &
00249 FireVisionDataFile::blocks()
00250 {
00251 return __blocks;
00252 }
00253
00254
00255
00256
00257
00258 void
00259 FireVisionDataFile::write(const char *file_name)
00260 {
00261 FILE *f = fopen(file_name, "w");
00262 if ( f == NULL ) {
00263 throw CouldNotOpenFileException(file_name, errno, "Could not open rectlut file "
00264 "for writing");
00265 }
00266
00267 __header->num_blocks = (unsigned int)__blocks.size();
00268 timeval t;
00269 gettimeofday(&t, NULL);
00270 __header->created_sec = t.tv_sec;
00271 __header->created_usec = t.tv_usec;
00272 __header->spec_head_size = _spec_header_size;
00273
00274
00275 if ( fwrite(__header, sizeof(fvff_header_t), 1, f) != 1 ) {
00276 fclose(f);
00277 throw FileWriteException(file_name, errno, "Writing fvff header failed");
00278 }
00279
00280 if ( _spec_header_size > 0 ) {
00281
00282 if ( fwrite(_spec_header, _spec_header_size, 1, f) != 1 ) {
00283 fclose(f);
00284 throw FileWriteException(file_name, errno, "Writing content specific header failed");
00285 }
00286 }
00287
00288 for (__bi = __blocks.begin(); __bi != __blocks.end(); ++__bi) {
00289
00290
00291 if ( fwrite((*__bi)->block_memptr(), (*__bi)->block_size(), 1, f) != 1 ) {
00292 fclose(f);
00293 throw FileWriteException(file_name, errno, "Failed to write info block");
00294 }
00295 }
00296
00297 fclose(f);
00298 }
00299
00300
00301
00302
00303
00304 void
00305 FireVisionDataFile::read(const char *file_name)
00306 {
00307 FILE *f = fopen(file_name, "r");
00308 if ( f == NULL ) {
00309 throw CouldNotOpenFileException(file_name, errno, "Could not open rectlut file "
00310 "for reading");
00311 }
00312
00313 clear();
00314
00315
00316 if ( fread(__header, sizeof(fvff_header_t), 1, f) != 1) {
00317 fclose(f);
00318 throw FileReadException(file_name, errno, "Reading header failed");
00319 }
00320
00321 if ( __header->magic_token != htons(__magic_token) ) {
00322 fclose(f);
00323 throw Exception("Unknown magic in fvff file (read: 0x%04x req: 0x%04x)",
00324 __header->magic_token, __magic_token);
00325 }
00326
00327 if ( __header->version != __version ) {
00328 fclose(f);
00329 throw Exception("Unsupported version of fvff file (read: %u req: %u)",
00330 __header->version, __version);
00331 }
00332
00333 if ( __header->endianess ==
00334 #if __BYTE_ORDER == __BIG_ENDIAN
00335 0
00336 #else
00337 1
00338 #endif
00339 ) {
00340 fclose(f);
00341 throw Exception("FVFile header cannot be translated for endianess by now");
00342 }
00343
00344 free(__comment);
00345 __comment = strndup(__header->comment, FVFF_COMMENT_SIZE);
00346
00347 if ( _spec_header ) {
00348 free(_spec_header);
00349 }
00350 _spec_header = calloc(1, __header->spec_head_size);
00351 if ( ! _spec_header ) {
00352 throw OutOfMemoryException("Cannot allocate memory for content specific header");
00353 }
00354
00355 if ( __header->spec_head_size > 0 ) {
00356
00357 if ( fread(_spec_header, __header->spec_head_size, 1, f) != 1) {
00358 fclose(f);
00359 throw FileReadException(file_name, errno, "Reading content specific header failed");
00360 }
00361 }
00362
00363
00364 for (uint8_t b = 0; b < __header->num_blocks && !feof(f); ++b) {
00365 fvff_block_header_t bh;
00366
00367 if ( fread(&bh, sizeof(bh), 1, f) != 1 ) {
00368 fclose(f);
00369 throw FileReadException(file_name, errno,
00370 "Could not read block info header while there should be one");
00371 }
00372 void *spec_header = NULL;
00373
00374 if ( bh.spec_head_size > 0 ) {
00375
00376 spec_header = malloc(bh.spec_head_size);
00377 if ( ! spec_header ) {
00378 throw OutOfMemoryException("Could not allocate %u bytes for content specific header",
00379 bh.spec_head_size);
00380 }
00381
00382
00383 if ( fread(spec_header, bh.spec_head_size, 1, f) != 1 ) {
00384 fclose(f);
00385 free(spec_header);
00386 throw FileReadException(file_name, errno,
00387 "Could not read content specific block header");
00388 }
00389 }
00390
00391 FireVisionDataFileBlock *block = new FireVisionDataFileBlock(bh.type, bh.size,
00392 spec_header, bh.spec_head_size);
00393
00394 free(spec_header);
00395
00396
00397 if ( bh.size && fread(block->data_ptr(), bh.size, 1, f) != 1 ) {
00398 fclose(f);
00399 delete block;
00400 throw FileReadException(file_name, errno,
00401 "Could not read block data");
00402 }
00403
00404 __blocks.push_back(block);
00405 }
00406
00407 fclose(f);
00408 }
00409
00410
00411
00412
00413
00414
00415 unsigned short int
00416 FireVisionDataFile::read_magic_token(const char *filename)
00417 {
00418 uint16_t magic_token = 0;
00419
00420 FILE *f;
00421 f = fopen(filename, "r");
00422 if (f != NULL) {
00423 if ( fread((char *)&magic_token, sizeof(magic_token), 1, f) != 1 ) {
00424 fclose(f);
00425 throw FileReadException(filename, errno, "Could not read magic token from file");
00426 }
00427 }
00428 fclose(f);
00429
00430 return magic_token;
00431 }
00432
00433
00434
00435
00436
00437
00438
00439 bool
00440 FireVisionDataFile::has_magic_token(const char *filename, unsigned short int magic_token)
00441 {
00442 uint16_t file_magic_token = read_magic_token(filename);
00443 return (htons(magic_token) == file_magic_token);
00444 }