00001
00002 #include "oxp_bunch_of_files.h"
00003
00004 #include <vcl_cassert.h>
00005 #include <vcl_cstring.h>
00006 #include <vcl_fstream.h>
00007 #include <vcl_iostream.h>
00008
00009 #include <vul/vul_awk.h>
00010 #include <vul/vul_file.h>
00011 #include <vul/vul_sprintf.h>
00012
00013 #define debug 0
00014
00015 oxp_bunch_of_files::oxp_bunch_of_files(char const* fmt)
00016 {
00017 open(fmt);
00018 }
00019
00020 bool oxp_bunch_of_files::open_1(char const* fmt)
00021 {
00022 filenames.push_back(fmt);
00023 return fix_sizes();
00024 }
00025
00026 bool oxp_bunch_of_files::open(char const* fmt)
00027 {
00028
00029 int l = vcl_strlen(fmt);
00030 if (l > 4 && vcl_strcmp(fmt + l - 4, ".lst") == 0) {
00031 vcl_ifstream f(fmt);
00032 assert(f.good());
00033 for (vul_awk awk(f); awk; ++awk) {
00034 if (awk.NF() > 0) {
00035 if (debug)
00036 vcl_cerr << awk[0] << vcl_endl;
00037 filenames.push_back(awk[0]);
00038 }
00039 }
00040 }
00041 else if (vcl_strchr(fmt, '%') ) {
00042
00043 bool found_one = false;
00044 for (int i = 0; ; ++i) {
00045 const char* buf = vul_sprintf(fmt, i).c_str();
00046 offset_t s = (offset_t)vul_file::size(buf);
00047 if (s > 0) {
00048 found_one = true;
00049 filenames.push_back(buf);
00050 filesizes.push_back(s);
00051 }
00052 else {
00053
00054 if (found_one)
00055 break;
00056 else {
00057
00058
00059 if (i > 10)
00060 break;
00061 }
00062 }
00063 }
00064 }
00065 else {
00066
00067 filenames.push_back(fmt);
00068 }
00069
00070 unsigned int n = filenames.size();
00071
00072 if (n == 0) {
00073 vcl_cerr << "oxp_bunch_of_files: ERROR: Could not turn [" << fmt << "] into a list of files\n";
00074 return false;
00075 }
00076
00077 return fix_sizes();
00078 }
00079
00080 bool oxp_bunch_of_files::fix_sizes()
00081 {
00082 current_file_index = -1;
00083
00084 unsigned int n = filenames.size();
00085
00086
00087 if (filesizes.size() < n) {
00088 filesizes.resize(n);
00089 for (unsigned int i = 0; i < n; ++i) {
00090 offset_t s = (offset_t)vul_file::size(filenames[i].c_str());
00091 if (s == 0)
00092 vcl_cerr << "WARNING: Zero size file [" << filenames[i] << "]\n";
00093 filesizes[i] = s;
00094 }
00095 }
00096
00097
00098 current_file_index = 0;
00099
00100
00101 start_byte.resize(n);
00102 start_byte[0] = 0L;
00103 for (unsigned int i = 1; i < filenames.size(); ++i)
00104 start_byte[i] = start_byte[i-1] + filesizes[i-1];
00105
00106
00107 fps.resize(n);
00108 for (unsigned int i = 0; i < filenames.size(); ++i) {
00109 char const* fn = filenames[i].c_str();
00110 fps[i] = vcl_fopen(fn, "rb");
00111 if (!fps[i]) {
00112 vcl_cerr << "oxp_bunch_of_files::fix_sizes() ERROR: Could not open [" << fn << "]\n";
00113 current_file_index = -1;
00114 return false;
00115 }
00116 }
00117
00118 if (debug) {
00119
00120 vcl_cerr << "files: sizeof(offset_t) = " << sizeof(offset_t) << '\n';
00121 for (unsigned int i = 0; i < n; ++i)
00122 vcl_cerr << " " << filenames[i] << " " << start_byte[i] << '\n';
00123 vcl_cerr << '\n';
00124 }
00125
00126 return true;
00127 }
00128
00129 bool oxp_bunch_of_files::seek(offset_t to)
00130 {
00131 int newindex = -1;
00132 for (unsigned int i = 1; i < filesizes.size(); ++i)
00133 if (start_byte[i] > to) {
00134 newindex = i-1;
00135 break;
00136 }
00137
00138 if (newindex == -1) {
00139 int i = filesizes.size() - 1;
00140
00141 if (to < start_byte[i] + filesizes[i])
00142 newindex = i;
00143 }
00144
00145 if (newindex == -1) {
00146 vcl_cerr << "oxp_bunch_of_files::seek(): ERROR: Could not seek to [" << to << "]\n";
00147 return false;
00148 }
00149
00150 current_file_index = newindex;
00151
00152 offset_t file_ptr = to - start_byte[current_file_index];
00153 vcl_cerr << " si = " << start_byte[current_file_index] << " to = " << to << '\n';
00154 assert(file_ptr < filesizes[current_file_index]);
00155
00156 return 0 <= vcl_fseek(fps[current_file_index], file_ptr, SEEK_SET);
00157 }
00158
00159 oxp_bunch_of_files::offset_t oxp_bunch_of_files::tell() const
00160 {
00161 return start_byte[current_file_index] + ftell(fps[current_file_index]);
00162 }
00163
00164 oxp_bunch_of_files::offset_t oxp_bunch_of_files::read(void* buf, offset_t len)
00165 {
00166 offset_t space_left_in_this_file = filesizes[current_file_index] - ftell(fps[current_file_index]);
00167
00168 offset_t bytes_from_curr = len;
00169 offset_t bytes_from_next = 0L;
00170 if (space_left_in_this_file < len) {
00171 bytes_from_curr = space_left_in_this_file;
00172 bytes_from_next = len - space_left_in_this_file;
00173 }
00174
00175 if (bytes_from_next == 0)
00176 return vcl_fread(buf, 1, len, fps[current_file_index]);
00177
00178 offset_t n1 = vcl_fread(buf, 1, bytes_from_curr, fps[current_file_index]);
00179 if (n1 < bytes_from_curr)
00180
00181 return n1;
00182 if ((unsigned int)(current_file_index+1) == fps.size())
00183
00184 return n1;
00185
00186
00187 ++current_file_index;
00188 vcl_fseek(fps[current_file_index], 0L, SEEK_SET);
00189 int n2 = vcl_fread((unsigned char*)buf + n1, 1, bytes_from_next, fps[current_file_index]);
00190 return n1 + n2;
00191 }
00192
00193 void oxp_bunch_of_files::close()
00194 {
00195 for (unsigned int i = 0; i < fps.size(); ++i)
00196 vcl_fclose(fps[i]);
00197 }