Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

oxp_bunch_of_files.cxx

Go to the documentation of this file.
00001 // This is oxl/oxp/oxp_bunch_of_files.cxx
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   // fmt could be a "lst" file, or a single vob or mpg or a %d list
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     // Assume a list.  Could start from some low number... Could glob.  hmmm.
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         // If got at least one so far, then bail now
00054         if (found_one)
00055           break;
00056         else {
00057           // If not found one yet, and still only tried < 10, then
00058           // keep trying.
00059           if (i > 10)
00060             break;
00061         }
00062       }
00063     }
00064   }
00065   else {
00066     // No %, not .lst: assume it's an mpeg/vob
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   // Fill in sizes if not done already
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   // Set up file ptr etc.
00098   current_file_index = 0;
00099 
00100   // Fill start_bytes
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   // Open them all
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     // Summarize:
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     // Know start_byte[i] <= to
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     // First read stopped short, don't even bother with next one
00181     return n1;
00182   if ((unsigned int)(current_file_index+1) == fps.size())
00183     // First was OK, and we've run out of files
00184     return n1;
00185 
00186   // First read was OK.  Advance to next file.
00187   ++current_file_index;
00188   vcl_fseek(fps[current_file_index], 0L, SEEK_SET); // need to seek(0) since we may have read from this file before.
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 }

Generated on Thu Jan 10 14:46:06 2008 for contrib/oxl/oxp by  doxygen 1.4.4