Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/dnn/src/torch/THDiskFile.cpp
16337 views
1
#include "../precomp.hpp"
2
#include "THGeneral.h"
3
#include "THDiskFile.h"
4
#include "THFilePrivate.h"
5
6
namespace TH
7
{
8
9
typedef struct THDiskFile__
10
{
11
THFile file;
12
13
FILE *handle;
14
int isNativeEncoding;
15
int longSize;
16
17
} THDiskFile;
18
19
static int THDiskFile_isOpened(THFile *self)
20
{
21
THDiskFile *dfself = (THDiskFile*)self;
22
return (dfself->handle != NULL);
23
}
24
25
/* workaround mac osx lion ***insane*** fread bug */
26
#ifdef __APPLE__
27
static size_t fread__(void *ptr, size_t size, size_t nitems, FILE *stream)
28
{
29
size_t nread = 0;
30
while(!feof(stream) && !ferror(stream) && (nread < nitems))
31
nread += fread((char*)ptr+nread*size, size, std::min<size_t>(2147483648UL/size, nitems-nread), stream);
32
return nread;
33
}
34
#else
35
#define fread__ fread
36
#endif
37
38
#define READ_WRITE_METHODS(TYPE, TYPEC, ASCII_READ_ELEM, ASCII_WRITE_ELEM) \
39
static long THDiskFile_read##TYPEC(THFile *self, TYPE *data, long n) \
40
{ \
41
THDiskFile *dfself = (THDiskFile*)(self); \
42
long nread = 0L; \
43
\
44
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file"); \
45
THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file"); \
46
\
47
if(dfself->file.isBinary) \
48
{ \
49
nread = fread__(data, sizeof(TYPE), n, dfself->handle); \
50
if(!dfself->isNativeEncoding && (sizeof(TYPE) > 1) && (nread > 0)) \
51
THDiskFile_reverseMemory(data, data, sizeof(TYPE), nread); \
52
} \
53
else \
54
{ \
55
long i; \
56
for(i = 0; i < n; i++) \
57
{ \
58
ASCII_READ_ELEM; /* increment here result and break if wrong */ \
59
} \
60
if(dfself->file.isAutoSpacing && (n > 0)) \
61
{ \
62
int c = fgetc(dfself->handle); \
63
if( (c != '\n') && (c != EOF) ) \
64
ungetc(c, dfself->handle); \
65
} \
66
} \
67
\
68
if(nread != n) \
69
{ \
70
dfself->file.hasError = 1; /* shouldn't we put hasError to 0 all the time ? */ \
71
if(!dfself->file.isQuiet) \
72
THError("read error: read %ld blocks instead of %ld", nread, n);\
73
} \
74
\
75
return nread; \
76
}
77
78
static int THDiskFile_mode(const char *mode, int *isReadable, int *isWritable)
79
{
80
*isReadable = 0;
81
*isWritable = 0;
82
if(strlen(mode) == 1)
83
{
84
if(*mode == 'r')
85
{
86
*isReadable = 1;
87
return 1;
88
}
89
else if(*mode == 'w')
90
{
91
*isWritable = 1;
92
return 1;
93
}
94
}
95
else if(strlen(mode) == 2)
96
{
97
if(mode[0] == 'r' && mode[1] == 'w')
98
{
99
*isReadable = 1;
100
*isWritable = 1;
101
return 1;
102
}
103
}
104
return 0;
105
}
106
107
static void THDiskFile_seek(THFile *self, long position)
108
{
109
THDiskFile *dfself = (THDiskFile*)(self);
110
111
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
112
113
#if defined(_WIN64)
114
if(_fseeki64(dfself->handle, (__int64)position, SEEK_SET) < 0)
115
#elif defined(_WIN32)
116
if(fseek(dfself->handle, (long)position, SEEK_SET) < 0)
117
#else
118
if(fseeko(dfself->handle, (off_t)position, SEEK_SET) < 0)
119
#endif
120
{
121
dfself->file.hasError = 1;
122
if(!dfself->file.isQuiet)
123
THError("unable to seek at position %ld", position);
124
}
125
}
126
127
static void THDiskFile_seekEnd(THFile *self)
128
{
129
THDiskFile *dfself = (THDiskFile*)(self);
130
131
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
132
133
#if defined(_WIN64)
134
if(_fseeki64(dfself->handle, 0L, SEEK_END) < 0)
135
#elif defined(_WIN32)
136
if(fseek(dfself->handle, 0L, SEEK_END) < 0)
137
#else
138
if(fseeko(dfself->handle, 0L, SEEK_END) < 0)
139
#endif
140
{
141
dfself->file.hasError = 1;
142
if(!dfself->file.isQuiet)
143
THError("unable to seek at end of file");
144
}
145
}
146
147
static long THDiskFile_position(THFile *self)
148
{
149
THDiskFile *dfself = (THDiskFile*)(self);
150
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
151
152
#if defined(_WIN64)
153
__int64 offset = _ftelli64(dfself->handle);
154
#elif defined(_WIN32)
155
long offset = ftell(dfself->handle);
156
#else
157
off_t offset = ftello(dfself->handle);
158
#endif
159
if (offset > -1)
160
return (long)offset;
161
else if(!dfself->file.isQuiet)
162
THError("unable to obtain disk file offset (maybe a long overflow occurred)");
163
164
return 0;
165
}
166
167
static void THDiskFile_close(THFile *self)
168
{
169
THDiskFile *dfself = (THDiskFile*)(self);
170
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
171
fclose(dfself->handle);
172
dfself->handle = NULL;
173
}
174
175
/* Little and Big Endian */
176
177
static void THDiskFile_reverseMemory(void *dst, const void *src, long blockSize, long numBlocks)
178
{
179
if(blockSize != 1)
180
{
181
long halfBlockSize = blockSize/2;
182
char *charSrc = (char*)src;
183
char *charDst = (char*)dst;
184
long b, i;
185
for(b = 0; b < numBlocks; b++)
186
{
187
for(i = 0; i < halfBlockSize; i++)
188
{
189
char z = charSrc[i];
190
charDst[i] = charSrc[blockSize-1-i];
191
charDst[blockSize-1-i] = z;
192
}
193
charSrc += blockSize;
194
charDst += blockSize;
195
}
196
}
197
}
198
199
int THDiskFile_isLittleEndianCPU(void)
200
{
201
int x = 7;
202
char *ptr = (char *)&x;
203
204
if(ptr[0] == 0)
205
return 0;
206
else
207
return 1;
208
}
209
210
int THDiskFile_isBigEndianCPU(void)
211
{
212
return(!THDiskFile_isLittleEndianCPU());
213
}
214
215
void THDiskFile_nativeEndianEncoding(THFile *self)
216
{
217
THDiskFile *dfself = (THDiskFile*)(self);
218
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
219
dfself->isNativeEncoding = 1;
220
}
221
222
void THDiskFile_littleEndianEncoding(THFile *self)
223
{
224
THDiskFile *dfself = (THDiskFile*)(self);
225
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
226
dfself->isNativeEncoding = THDiskFile_isLittleEndianCPU();
227
}
228
229
void THDiskFile_bigEndianEncoding(THFile *self)
230
{
231
THDiskFile *dfself = (THDiskFile*)(self);
232
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
233
dfself->isNativeEncoding = !THDiskFile_isLittleEndianCPU();
234
}
235
236
/* End of Little and Big Endian Stuff */
237
238
void THDiskFile_longSize(THFile *self, int size)
239
{
240
THDiskFile *dfself = (THDiskFile*)(self);
241
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
242
THArgCheck(size == 0 || size == 4 || size == 8, 1, "Invalid long size specified");
243
dfself->longSize = size;
244
}
245
246
void THDiskFile_noBuffer(THFile *self)
247
{
248
THDiskFile *dfself = (THDiskFile*)(self);
249
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
250
if (setvbuf(dfself->handle, NULL, _IONBF, 0)) {
251
THError("error: cannot disable buffer");
252
}
253
}
254
255
static void THDiskFile_free(THFile *self)
256
{
257
THDiskFile *dfself = (THDiskFile*)(self);
258
if(dfself->handle)
259
fclose(dfself->handle);
260
THFree(dfself);
261
}
262
263
/* Note that we do a trick */
264
READ_WRITE_METHODS(unsigned char, Byte,
265
nread = fread(data, 1, n, dfself->handle); break,
266
nwrite = fwrite(data, 1, n, dfself->handle); break)
267
268
READ_WRITE_METHODS(char, Char,
269
nread = fread(data, 1, n, dfself->handle); break,
270
nwrite = fwrite(data, 1, n, dfself->handle); break)
271
272
READ_WRITE_METHODS(short, Short,
273
int ret = fscanf(dfself->handle, "%hd", &data[i]); if(ret <= 0) break; else nread++,
274
int ret = fprintf(dfself->handle, "%hd", data[i]); if(ret <= 0) break; else nwrite++)
275
276
READ_WRITE_METHODS(int, Int,
277
int ret = fscanf(dfself->handle, "%d\n\r", &data[i]); if(ret <= 0) break; else nread++,
278
int ret = fprintf(dfself->handle, "%d", data[i]); if(ret <= 0) break; else nwrite++)
279
280
/*READ_WRITE_METHODS(long, Long,
281
int ret = fscanf(dfself->handle, "%ld", &data[i]); if(ret <= 0) break; else nread++,
282
int ret = fprintf(dfself->handle, "%ld", data[i]); if(ret <= 0) break; else nwrite++)*/
283
284
READ_WRITE_METHODS(float, Float,
285
int ret = fscanf(dfself->handle, "%g", &data[i]); if(ret <= 0) break; else nread++,
286
int ret = fprintf(dfself->handle, "%.9g", data[i]); if(ret <= 0) break; else nwrite++)
287
288
READ_WRITE_METHODS(double, Double,
289
int ret = fscanf(dfself->handle, "%lg", &data[i]); if(ret <= 0) break; else nread++,
290
int ret = fprintf(dfself->handle, "%.17g", data[i]); if(ret <= 0) break; else nwrite++)
291
292
293
/* For Long we need to rewrite everything, because of the special management of longSize */
294
static long THDiskFile_readLong(THFile *self, int64 *data, long n)
295
{
296
THDiskFile *dfself = (THDiskFile*)(self);
297
long nread = 0L;
298
299
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
300
THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file");
301
302
if(dfself->file.isBinary)
303
{
304
if(dfself->longSize == 0 || dfself->longSize == sizeof(int64))
305
{
306
nread = fread__(data, sizeof(int64), n, dfself->handle);
307
if(!dfself->isNativeEncoding && (sizeof(int64) > 1) && (nread > 0))
308
THDiskFile_reverseMemory(data, data, sizeof(int64), nread);
309
} else if(dfself->longSize == 4)
310
{
311
nread = fread__(data, 4, n, dfself->handle);
312
if(!dfself->isNativeEncoding && (nread > 0))
313
THDiskFile_reverseMemory(data, data, 4, nread);
314
long i;
315
for(i = nread; i > 0; i--)
316
data[i-1] = ((int *)data)[i-1];
317
}
318
else /* if(dfself->longSize == 8) */
319
{
320
int big_endian = !THDiskFile_isLittleEndianCPU();
321
int32_t *buffer = (int32_t*)THAlloc(8*n);
322
if (!buffer)
323
THError("can not allocate buffer");
324
nread = fread__(buffer, 8, n, dfself->handle);
325
long i;
326
for(i = nread; i > 0; i--)
327
data[i-1] = buffer[2*(i-1) + big_endian];
328
THFree(buffer);
329
if(!dfself->isNativeEncoding && (nread > 0))
330
THDiskFile_reverseMemory(data, data, 4, nread);
331
}
332
}
333
else
334
{
335
long i;
336
for(i = 0; i < n; i++)
337
{
338
long d;
339
int ret = fscanf(dfself->handle, "%ld", &d); if(ret <= 0) break; else nread++;
340
data[i] = d;
341
}
342
if(dfself->file.isAutoSpacing && (n > 0))
343
{
344
int c = fgetc(dfself->handle);
345
if( (c != '\n') && (c != EOF) )
346
ungetc(c, dfself->handle);
347
}
348
}
349
350
if(nread != n)
351
{
352
dfself->file.hasError = 1; /* shouldn't we put hasError to 0 all the time ? */
353
if(!dfself->file.isQuiet)
354
THError("read error: read %ld blocks instead of %ld", nread, n);
355
}
356
357
return nread;
358
}
359
360
361
static long THDiskFile_readString(THFile *self, const char *format, char **str_)
362
{
363
THDiskFile *dfself = (THDiskFile*)(self);
364
THArgCheck(dfself->handle != NULL, 1, "attempt to use a closed file");
365
THArgCheck(dfself->file.isReadable, 1, "attempt to read in a write-only file");
366
THArgCheck((strlen(format) >= 2 ? (format[0] == '*') && (format[1] == 'a' || format[1] == 'l') : 0), 2, "format must be '*a' or '*l'");
367
368
/* note: the string won't survive long, as it is copied into lua */
369
/* so 1024 is not that big... */
370
#define TBRS_BSZ 1024L
371
372
if(format[1] == 'a')
373
{
374
char *p = (char*)THAlloc(TBRS_BSZ);
375
long total = TBRS_BSZ;
376
long pos = 0L;
377
378
for (;;)
379
{
380
if(total-pos == 0) /* we need more space! */
381
{
382
total += TBRS_BSZ;
383
p = (char*)THRealloc(p, total);
384
}
385
if (p == NULL)
386
THError("read error: failed to allocate buffer");
387
pos += fread(p+pos, 1, total-pos, dfself->handle);
388
if (pos < total) /* eof? */
389
{
390
if(pos == 0L)
391
{
392
THFree(p);
393
dfself->file.hasError = 1;
394
if(!dfself->file.isQuiet)
395
THError("read error: read 0 blocks instead of 1");
396
397
*str_ = NULL;
398
return 0;
399
}
400
*str_ = p;
401
return pos;
402
}
403
}
404
}
405
else
406
{
407
char *p = (char*)THAlloc(TBRS_BSZ);
408
long total = TBRS_BSZ;
409
long pos = 0L;
410
long size;
411
412
for (;;)
413
{
414
if(total-pos <= 1) /* we can only write '\0' in there! */
415
{
416
total += TBRS_BSZ;
417
p = (char*)THRealloc(p, total);
418
}
419
if (p == NULL)
420
THError("read error: failed to allocate buffer");
421
if (fgets(p+pos, total-pos, dfself->handle) == NULL) /* eof? */
422
{
423
if(pos == 0L)
424
{
425
THFree(p);
426
dfself->file.hasError = 1;
427
if(!dfself->file.isQuiet)
428
THError("read error: read 0 blocks instead of 1");
429
430
*str_ = NULL;
431
return 0;
432
}
433
*str_ = p;
434
return pos;
435
}
436
size = strlen(p+pos);
437
if (size == 0L || (p+pos)[size-1] != '\n')
438
{
439
pos += size;
440
}
441
else
442
{
443
pos += size-1L; /* do not include `eol' */
444
*str_ = p;
445
return pos;
446
}
447
}
448
}
449
450
*str_ = NULL;
451
return 0;
452
}
453
454
THFile *THDiskFile_new(const std::string &name, const char *mode, int isQuiet)
455
{
456
static struct THFileVTable vtable = {
457
THDiskFile_isOpened,
458
459
THDiskFile_readByte,
460
THDiskFile_readChar,
461
THDiskFile_readShort,
462
THDiskFile_readInt,
463
THDiskFile_readLong,
464
THDiskFile_readFloat,
465
THDiskFile_readDouble,
466
THDiskFile_readString,
467
468
THDiskFile_seek,
469
THDiskFile_seekEnd,
470
THDiskFile_position,
471
THDiskFile_close,
472
THDiskFile_free
473
};
474
475
int isReadable;
476
int isWritable;
477
FILE *handle;
478
THDiskFile *self;
479
480
THArgCheck(THDiskFile_mode(mode, &isReadable, &isWritable), 2, "file mode should be 'r','w' or 'rw'");
481
482
CV_Assert(isReadable && !isWritable);
483
484
#ifdef _MSC_VER
485
if (fopen_s(&handle, name.c_str(), "rb") != 0)
486
handle = NULL;
487
#else
488
handle = fopen(name.c_str(),"rb");
489
#endif
490
491
if(!handle)
492
{
493
if(isQuiet)
494
return 0;
495
else
496
THError("cannot open <%s> in mode %c%c", name.c_str(), (isReadable ? 'r' : ' '), (isWritable ? 'w' : ' '));
497
}
498
499
self = (THDiskFile*)THAlloc(sizeof(THDiskFile));
500
if (!self)
501
THError("cannot allocate memory for self");
502
503
self->handle = handle;
504
self->isNativeEncoding = 1;
505
self->longSize = 0;
506
507
self->file.vtable = &vtable;
508
self->file.isQuiet = isQuiet;
509
self->file.isReadable = isReadable;
510
self->file.isWritable = isWritable;
511
self->file.isBinary = 0;
512
self->file.isAutoSpacing = 1;
513
self->file.hasError = 0;
514
515
return (THFile*)self;
516
}
517
518
}
519
520