00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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
00031
00032
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
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
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 }