Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

repos-reader.cc

Go to the documentation of this file.
00001 //***************************************************************************
00002 // This source code is copyrighted 2002 by Google Inc.  All rights
00003 // reserved.  You are given a limited license to use this source code for
00004 // purposes of participating in the Google programming contest.  If you
00005 // choose to use or distribute the source code for any other purpose, you
00006 // must either (1) first obtain written approval from Google, or (2)
00007 // prominently display the foregoing copyright notice and the following
00008 // warranty and liability disclaimer on each copy used or distributed.
00009 // 
00010 // The source code and repository (the "Software") is provided "AS IS",
00011 // with no warranty, express or implied, including but not limited to the
00012 // implied warranties of merchantability and fitness for a particular
00013 // use.  In no event shall Google Inc. be liable for any damages, direct
00014 // or indirect, even if advised of the possibility of such damages.
00015 //***************************************************************************
00016 
00017 
00018 #include "repos-reader.h"
00019 
00020 #define MIN(a,b) ((a) > (b) ? (b) : (a))
00021 
00022 
00023 ReposReader::ReposReader(std::istream* repos, const string& repos_name)
00024   : repos_(repos), repos_name_(repos_name), decode_buf_len_(0), cur_pos_(0),
00025     chars_buf_(NULL), decoder_(decode_buf_, 0) {
00026   ReallocCharsBuf(kReadBufSize);
00027   RefillBuf();
00028 }
00029 
00030 // Refill decode_buf_ from repos_, keeping the last "avail()" bytes in
00031 // decode_buf_.  If there are not bytes to read, reports an error and
00032 // exits.
00033 void ReposReader::RefillBuf() {
00034   int keep = decoder_.avail();
00035   if (keep) {
00036     memmove(decode_buf_, &decode_buf_[decode_buf_len_ - keep], keep);
00037   }
00038   repos_->read(&decode_buf_[keep], sizeof(decode_buf_) - keep);
00039   if (repos_->gcount() == 0) {
00040     ParseError("ReposReader::RefillBuf: premature end of repository file "
00041                + repos_name_);
00042   }
00043   decode_buf_len_ = repos_->gcount() + keep;
00044   decoder_.reset(decode_buf_, decode_buf_len_);
00045 }
00046 
00047 // Make chars_buf_ big enough for size + 1 chars
00048 void ReposReader::ReallocCharsBuf(int size) {
00049   delete[] chars_buf_;
00050   chars_buf_len_ = size + 1;
00051   chars_buf_ = new char[chars_buf_len_];
00052 }
00053 
00054 
00055 const char* ReposReader::ReadCharStar(int* len) {
00056   *len = ReadInt();
00057   return ReadCharsOnly(*len);
00058 }
00059 
00060 const char* ReposReader::ReadCharsOnly(int numchars) {
00061   int togo = numchars;
00062 
00063   // chars_buf_ has to be big enough for numchars + 1 chars
00064   if (numchars >= chars_buf_len_) ReallocCharsBuf(numchars);
00065   
00066   while (togo > 0) {
00067     if (decoder_.avail() == 0) {
00068       RefillBuf();
00069     }
00070     int n = MIN(togo, decoder_.avail());
00071     assert(n != 0);
00072     decoder_.getn(&chars_buf_[numchars - togo], n);
00073     togo -= n;
00074     cur_pos_ += n;
00075   }
00076   return chars_buf_;
00077 }
00078 
00079 uint32 ReposReader::ReadFixedUint32() {
00080   if (decoder_.avail() < 4) {
00081     RefillBuf();
00082   }
00083   cur_pos_ += 4;
00084   return decoder_.get32();
00085 }
00086 
00087 uint32 ReposReader::ReadVarUint32() {
00088   uint32 u;
00089   int n = decoder_.avail();
00090   if (! decoder_.get_varint32(&u)) {
00091     RefillBuf();
00092     n = decoder_.avail();
00093     if (! decoder_.get_varint32(&u)) {
00094       ParseError("ReposReader::ReadVarUint32: can't decode varint32");
00095     }      
00096   }
00097   cur_pos_ += n - decoder_.avail();
00098   return u;  
00099 }
00100 
00101 int ReposReader::ReadInt() {
00102   int i;
00103   int n = decoder_.avail();
00104   if (! decoder_.get_varsigned32(&i)) {
00105     RefillBuf();
00106     n = decoder_.avail();
00107     if (! decoder_.get_varsigned32(&i)) {
00108       ParseError("ReposReader::ReadInt: can't decode varsigned32");
00109     }      
00110   }
00111   cur_pos_ += n - decoder_.avail();
00112   return i;  
00113 }
00114 
00115 unsigned char ReposReader::ReadByte() {
00116   if (!decoder_.avail()) {
00117     RefillBuf();
00118   }
00119   cur_pos_ += 1;
00120   return decoder_.get8();
00121 }
00122  
00123 bool ReposReader::AtEnd() const {
00124   return (decoder_.avail() == 0) && repos_->eof();
00125 }
00126 
00127 void ReposReader::ParseError(const string& errmsg) {
00128   cerr << errmsg << ": repository " << repos_name_ 
00129        << ", position " << cur_pos_ << std::endl;
00130   exit(1); 
00131 }

Generated on Wed May 29 11:37:15 2002 for MarkovPR by doxygen1.2.15