Handle sparse files efficiently.
[backups/.git] / filedata.cpp
1 #include <string>
2 #include <vector>
3 #include <iostream>
4
5 #include "filedata.hpp"
6
7 using namespace std;
8
9 vector<string> split( const string &line, char c, int limit = -1 ) {
10   string::size_type start = 0, end = 0;
11
12   vector<string> out;
13   while( 0 != limit-- && end != line.size() ) {
14     if( 0 == limit ) {
15       end = line.size();
16     } else {
17       end = line.find( c, start );
18       if( end == string::npos ) {
19         end = line.size();
20       }
21     }
22     out.push_back( line.substr( start, end-start ) );
23     start = end + 1;
24   }
25   return out;
26 }
27
28 ostream &operator<<( ostream &o, const FileData *d) {
29   return operator<<( o, *d );
30 }
31
32 ostream &operator<<( ostream &o, const FileData &d ) {
33   o << d.getFileType()       << ' ';
34   o << d.getPermissions()    << ' ';
35   o << d.getUserName()       << ' ';
36   o << d.getGroupName()      << ' ';
37   o << d.getFileSize()       << ' ';
38   o << d.getModifiedDate()   << ' ';
39   o << d.getLastBackupDate() << ' ';
40   o << d.getFileName()       << '\0';
41
42   return o;
43 }
44
45 istream &operator>>( istream &i, FileData *d ) {
46   return operator>>( i, *d );
47 }
48
49 istream &operator>>( istream &i, FileData &d ) {
50   string file_string;
51
52   int c;
53   // Todo, don't use char_traits<char> directly here
54   for( c = i.get(); 0 != c && char_traits<char>::eof() != c; c = i.get() ) {
55     file_string.push_back( c );
56   }
57   if( char_traits<char>::eof() == c ) {
58     i.setstate( ios_base::eofbit );
59   }
60
61   if( 0 != file_string.size() ) {
62     // Example entry
63     // type perms user group size datemodified name (8 total)
64     // f 0600 cnb cnb 424 20051015205340 0 ./.git/index
65     vector<string> vals = split( file_string, ' ', 8 );
66     d.setFileType(       vals[0][0] );
67     d.setPermissions(    vals[1] );
68     d.setUserName(       vals[2] );
69     d.setGroupName(      vals[3] );
70     d.setFileSize(       atoll( vals[4].c_str() ) );
71     d.setModifiedDate(   atoll( vals[5].c_str() ) );
72     d.setLastBackupDate( atoll( vals[6].c_str() ) );
73     d.setFileName(       vals[7] );
74   }
75
76   return i;
77 }
78
79 bool needs_backup( const FileData *before, const FileData *after ) {
80   assert( before->getFileName() == after->getFileName() );
81
82   if( after->getLastBackupDate()  <  after->getModifiedDate() ) return true;
83
84   if( before->getFileType()       != after->getFileType()     ) return true;
85   if( before->getPermissions()    != after->getPermissions()  ) return true;
86   if( before->getUserName()       != after->getUserName()     ) return true;
87   if( before->getGroupName()      != after->getGroupName()    ) return true;
88   if( before->getFileSize()       != after->getFileSize()     ) return true;
89
90   return false;
91 }