djiparsetxt
Macros | Functions | Variables
djiparsetxt.cpp File Reference
#include "DJITxtParser.hh"
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <errno.h>
Include dependency graph for djiparsetxt.cpp:

Go to the source code of this file.

Macros

#define OLD_HEADER_SIZE   12
 
#define NEW_HEADER_SIZE   100
 
#define MIN_RECORD_SIZE   3
 

Functions

int main (int argc, char **argv)
 

Variables

u_int8_t fileVersionNumber
 

Macro Definition Documentation

◆ MIN_RECORD_SIZE

#define MIN_RECORD_SIZE   3

Definition at line 33 of file djiparsetxt.cpp.

◆ NEW_HEADER_SIZE

#define NEW_HEADER_SIZE   100

Definition at line 32 of file djiparsetxt.cpp.

◆ OLD_HEADER_SIZE

#define OLD_HEADER_SIZE   12

Definition at line 31 of file djiparsetxt.cpp.

Function Documentation

◆ main()

int main ( int  argc,
char **  argv 
)

Definition at line 37 of file djiparsetxt.cpp.

37  {
38  fprintf(stderr, "\"%s\", version 2021-05-20. Copyright (c) 2021 Live Networks, Inc. All rights reserved.\n", argv[0]);
39  fprintf(stderr, "For the latest version of this program (and more information), visit http://djilogs.live555.com\n");
40 
41  int fileNamePos = 1;
42  if (argc != 2) {
43  fprintf(stderr, "Usage: %s <txtFileName>\n", argv[0]);
44  return 1;
45  }
46  char const* fileName = argv[fileNamePos];
47 
48  FILE* fid = fopen(fileName, "rb");
49  if (fid == NULL) {
50  fprintf(stderr, "Failed to open \"%s\"\n", fileName);
51  return 1;
52  }
53 
54  // Figure out the file's size
55  struct stat sb;
56  u_int64_t fileSize;
57  if (stat(fileName, &sb) == 0) {
58  fileSize = sb.st_size;
59  } else {
60  fprintf(stderr, "Failed to get file size\n");
61  return 1;
62  }
63 
64  // Check the file size:
65  if (fileSize < OLD_HEADER_SIZE) {
66  fprintf(stderr, "Bad file size: %llu bytes\n", fileSize);
67  return 1;
68  }
69 
70  // Map the file into memory:
71  u_int8_t* const mappedFile
72  = (u_int8_t*)mmap(0, fileSize, PROT_READ, MAP_SHARED, fileno(fid), 0);
73  if (mappedFile == MAP_FAILED) {
74  extern int errno;
75  fprintf(stderr, "mmap() call failed: %s\n", strerror(errno));
76  return 1;
77  }
78 
79  // Figure out the start and end position of the header/records/details areas:
80  u_int64_t recordsAreaStart, recordsAreaEnd;
81  u_int64_t detailsAreaStart, detailsAreaEnd;
82 
83  // The first 8 bytes (little-endian) of the file points to the end of records area:
84  u_int8_t const* ptr = mappedFile;
85  recordsAreaEnd = getWord64LE(ptr);
86 
87  // The next 2 bytes (little-endian) is the size of the details area:
88  u_int16_t const detailsAreaSize = get2BytesLE(ptr);
89 
90  // The next byte is the version number of the file:
91  fileVersionNumber = *ptr++;
92  fprintf(stderr, "File version number: 0x%02x\n", fileVersionNumber);
93 
94  // The next byte is unknown; skip over it:
95  ++ptr;
96 
97  // Old versions of the file have a smaller header, and are not scrambled:
98  unsigned headerSize;
99  int isScrambled;
100  if (fileVersionNumber < 0x06) {
101  headerSize = OLD_HEADER_SIZE;
102  isScrambled = 0;
103  } else {
104  headerSize = NEW_HEADER_SIZE;
105  isScrambled = 1;
106  }
107 
108  // Newer versions of the file have a different order:
109  u_int64_t computedFileSize;
110  if (fileVersionNumber >= 0x0C) {
111  // Order is "header";"details area";"records area"
112  recordsAreaStart = headerSize + detailsAreaSize;
113  detailsAreaStart = headerSize;
114  detailsAreaEnd = detailsAreaStart + detailsAreaSize;
115 
116  computedFileSize = recordsAreaEnd;
117  } else {
118  // Order is "header";"records area";"details area"
119  recordsAreaStart = headerSize;
120  detailsAreaStart = recordsAreaEnd;
121  detailsAreaEnd = detailsAreaStart + detailsAreaSize;
122 
123  computedFileSize = detailsAreaEnd;
124  }
125 
126  // Check the sanity of these values:
127  u_int64_t const minFileSize = headerSize + MIN_RECORD_SIZE;
128  if (computedFileSize < minFileSize || computedFileSize > fileSize) {
129  fprintf(stderr, "Bad 'recordsAreaEnd' %llu (0x%llx) and/or 'detailsAreaSize' %u (0x%x); file size is %llu\n",
130  recordsAreaEnd, recordsAreaEnd,
131  detailsAreaSize, detailsAreaSize,
132  fileSize);
133  return 1;
134  }
135 
136  // Create a parser:
138 
139  // Begin by parsing the 'DETAILS' area:
140  ptr = &mappedFile[detailsAreaStart];
141  parser->parseDetailsArea(ptr, &mappedFile[detailsAreaEnd]);
142 
143  // Then, parse all of the records in the file:
144  ptr = &mappedFile[recordsAreaStart];
145  u_int8_t* const recordsAreaEndPtr = &mappedFile[recordsAreaEnd];
146 
147  while (ptr < recordsAreaEndPtr) {
148 #ifdef DEBUG_RECORD_PARSING
149  u_int64_t curFilePosition = ptr - mappedFile;
150  fprintf(stderr, "@0x%08llx: ", curFilePosition);
151 #endif
152  if (!parser->parseRecord(ptr, recordsAreaEndPtr, isScrambled)) break;
153  }
154  if (ptr < recordsAreaEndPtr) {
155  u_int64_t curFilePosition = ptr - mappedFile;
156  fprintf(stderr, "Premature end of record parsing at file position %llu (0x%08llx)\n", curFilePosition, curFilePosition);
157  }
158  parser->outputOneRow(); // the final row of data
159  parser->summarizeRecordParsing();
160 
161  delete parser;
162 
163  fprintf(stderr, "Done writing CSV.\n");
164  return 0;
165 }
#define OLD_HEADER_SIZE
Definition: djiparsetxt.cpp:31
static DJITxtParser * createNew()
u_int64_t getWord64LE(u_int8_t const *&ptr, u_int8_t const *limit)
virtual void summarizeRecordParsing()=0
#define NEW_HEADER_SIZE
Definition: djiparsetxt.cpp:32
virtual void outputOneRow(int outputColumnLabels=0)=0
u_int8_t fileVersionNumber
Definition: djiparsetxt.cpp:35
#define MIN_RECORD_SIZE
Definition: djiparsetxt.cpp:33
virtual void parseDetailsArea(u_int8_t const *&ptr, u_int8_t const *limit)=0
u_int16_t get2BytesLE(u_int8_t const *&ptr, u_int8_t const *limit)
virtual int parseRecord(u_int8_t const *&ptr, u_int8_t const *limit, int isScrambled)=0

References DJITxtParser::createNew(), fileVersionNumber, get2BytesLE(), getWord64LE(), MIN_RECORD_SIZE, NEW_HEADER_SIZE, OLD_HEADER_SIZE, DJITxtParser::outputOneRow(), DJITxtParser::parseDetailsArea(), DJITxtParser::parseRecord(), and DJITxtParser::summarizeRecordParsing().

Variable Documentation

◆ fileVersionNumber

u_int8_t fileVersionNumber

Definition at line 35 of file djiparsetxt.cpp.

Referenced by main(), and RecordAndDetailsParser::parseDetailsArea().