~ubuntu-branches/ubuntu/raring/protobuf/raring

« back to all changes in this revision

Viewing changes to src/google/protobuf/io/zero_copy_stream_impl.cc

  • Committer: Bazaar Package Importer
  • Author(s): Steve Kowalik
  • Date: 2010-02-11 11:13:19 UTC
  • mfrom: (2.2.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100211111319-zdn8hmw0gh8s4cf8
Tags: 2.2.0a-0.1ubuntu1
* Merge from Debian testing.
* Remaining Ubuntu changes:
  - Don't use python2.4.
* Ubuntu changes dropped:
  - Disable death tests on Itanium, fixed upstream.

Show diffs side-by-side

added added

removed removed

Lines of Context:
60
60
 
61
61
namespace {
62
62
 
63
 
 
64
63
// EINTR sucks.
65
64
int close_no_eintr(int fd) {
66
65
  int result;
70
69
  return result;
71
70
}
72
71
 
73
 
// Default block size for Copying{In,Out}putStreamAdaptor.
74
 
static const int kDefaultBlockSize = 8192;
75
 
 
76
72
}  // namespace
77
73
 
78
 
// ===================================================================
79
 
 
80
 
ArrayInputStream::ArrayInputStream(const void* data, int size,
81
 
                                   int block_size)
82
 
  : data_(reinterpret_cast<const uint8*>(data)),
83
 
    size_(size),
84
 
    block_size_(block_size > 0 ? block_size : size),
85
 
    position_(0),
86
 
    last_returned_size_(0) {
87
 
}
88
 
 
89
 
ArrayInputStream::~ArrayInputStream() {
90
 
}
91
 
 
92
 
bool ArrayInputStream::Next(const void** data, int* size) {
93
 
  if (position_ < size_) {
94
 
    last_returned_size_ = min(block_size_, size_ - position_);
95
 
    *data = data_ + position_;
96
 
    *size = last_returned_size_;
97
 
    position_ += last_returned_size_;
98
 
    return true;
99
 
  } else {
100
 
    // We're at the end of the array.
101
 
    last_returned_size_ = 0;   // Don't let caller back up.
102
 
    return false;
103
 
  }
104
 
}
105
 
 
106
 
void ArrayInputStream::BackUp(int count) {
107
 
  GOOGLE_CHECK_GT(last_returned_size_, 0)
108
 
      << "BackUp() can only be called after a successful Next().";
109
 
  GOOGLE_CHECK_LE(count, last_returned_size_);
110
 
  GOOGLE_CHECK_GE(count, 0);
111
 
  position_ -= count;
112
 
  last_returned_size_ = 0;  // Don't let caller back up further.
113
 
}
114
 
 
115
 
bool ArrayInputStream::Skip(int count) {
116
 
  GOOGLE_CHECK_GE(count, 0);
117
 
  last_returned_size_ = 0;   // Don't let caller back up.
118
 
  if (count > size_ - position_) {
119
 
    position_ = size_;
120
 
    return false;
121
 
  } else {
122
 
    position_ += count;
123
 
    return true;
124
 
  }
125
 
}
126
 
 
127
 
int64 ArrayInputStream::ByteCount() const {
128
 
  return position_;
129
 
}
130
 
 
131
 
 
132
 
// ===================================================================
133
 
 
134
 
ArrayOutputStream::ArrayOutputStream(void* data, int size, int block_size)
135
 
  : data_(reinterpret_cast<uint8*>(data)),
136
 
    size_(size),
137
 
    block_size_(block_size > 0 ? block_size : size),
138
 
    position_(0),
139
 
    last_returned_size_(0) {
140
 
}
141
 
 
142
 
ArrayOutputStream::~ArrayOutputStream() {
143
 
}
144
 
 
145
 
bool ArrayOutputStream::Next(void** data, int* size) {
146
 
  if (position_ < size_) {
147
 
    last_returned_size_ = min(block_size_, size_ - position_);
148
 
    *data = data_ + position_;
149
 
    *size = last_returned_size_;
150
 
    position_ += last_returned_size_;
151
 
    return true;
152
 
  } else {
153
 
    // We're at the end of the array.
154
 
    last_returned_size_ = 0;   // Don't let caller back up.
155
 
    return false;
156
 
  }
157
 
}
158
 
 
159
 
void ArrayOutputStream::BackUp(int count) {
160
 
  GOOGLE_CHECK_GT(last_returned_size_, 0)
161
 
      << "BackUp() can only be called after a successful Next().";
162
 
  GOOGLE_CHECK_LE(count, last_returned_size_);
163
 
  GOOGLE_CHECK_GE(count, 0);
164
 
  position_ -= count;
165
 
  last_returned_size_ = 0;  // Don't let caller back up further.
166
 
}
167
 
 
168
 
int64 ArrayOutputStream::ByteCount() const {
169
 
  return position_;
170
 
}
171
 
 
172
 
// ===================================================================
173
 
 
174
 
StringOutputStream::StringOutputStream(string* target)
175
 
  : target_(target) {
176
 
}
177
 
 
178
 
StringOutputStream::~StringOutputStream() {
179
 
}
180
 
 
181
 
bool StringOutputStream::Next(void** data, int* size) {
182
 
  int old_size = target_->size();
183
 
 
184
 
  // Grow the string.
185
 
  if (old_size < target_->capacity()) {
186
 
    // Resize the string to match its capacity, since we can get away
187
 
    // without a memory allocation this way.
188
 
    STLStringResizeUninitialized(target_, target_->capacity());
189
 
  } else {
190
 
    // Size has reached capacity, so double the size.  Also make sure
191
 
    // that the new size is at least kMinimumSize.
192
 
    STLStringResizeUninitialized(
193
 
      target_,
194
 
      max(old_size * 2,
195
 
          kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
196
 
  }
197
 
 
198
 
  *data = string_as_array(target_) + old_size;
199
 
  *size = target_->size() - old_size;
200
 
  return true;
201
 
}
202
 
 
203
 
void StringOutputStream::BackUp(int count) {
204
 
  GOOGLE_CHECK_GE(count, 0);
205
 
  GOOGLE_CHECK_LE(count, target_->size());
206
 
  target_->resize(target_->size() - count);
207
 
}
208
 
 
209
 
int64 StringOutputStream::ByteCount() const {
210
 
  return target_->size();
211
 
}
212
 
 
213
 
// ===================================================================
214
 
 
215
 
 
216
 
// ===================================================================
217
 
 
218
 
CopyingInputStream::~CopyingInputStream() {}
219
 
 
220
 
int CopyingInputStream::Skip(int count) {
221
 
  char junk[4096];
222
 
  int skipped = 0;
223
 
  while (skipped < count) {
224
 
    int bytes = Read(junk, min(count - skipped,
225
 
                               implicit_cast<int>(sizeof(junk))));
226
 
    if (bytes <= 0) {
227
 
      // EOF or read error.
228
 
      return skipped;
229
 
    }
230
 
    skipped += bytes;
231
 
  }
232
 
  return skipped;
233
 
}
234
 
 
235
 
CopyingInputStreamAdaptor::CopyingInputStreamAdaptor(
236
 
    CopyingInputStream* copying_stream, int block_size)
237
 
  : copying_stream_(copying_stream),
238
 
    owns_copying_stream_(false),
239
 
    failed_(false),
240
 
    position_(0),
241
 
    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
242
 
    buffer_used_(0),
243
 
    backup_bytes_(0) {
244
 
}
245
 
 
246
 
CopyingInputStreamAdaptor::~CopyingInputStreamAdaptor() {
247
 
  if (owns_copying_stream_) {
248
 
    delete copying_stream_;
249
 
  }
250
 
}
251
 
 
252
 
bool CopyingInputStreamAdaptor::Next(const void** data, int* size) {
253
 
  if (failed_) {
254
 
    // Already failed on a previous read.
255
 
    return false;
256
 
  }
257
 
 
258
 
  AllocateBufferIfNeeded();
259
 
 
260
 
  if (backup_bytes_ > 0) {
261
 
    // We have data left over from a previous BackUp(), so just return that.
262
 
    *data = buffer_.get() + buffer_used_ - backup_bytes_;
263
 
    *size = backup_bytes_;
264
 
    backup_bytes_ = 0;
265
 
    return true;
266
 
  }
267
 
 
268
 
  // Read new data into the buffer.
269
 
  buffer_used_ = copying_stream_->Read(buffer_.get(), buffer_size_);
270
 
  if (buffer_used_ <= 0) {
271
 
    // EOF or read error.  We don't need the buffer anymore.
272
 
    if (buffer_used_ < 0) {
273
 
      // Read error (not EOF).
274
 
      failed_ = true;
275
 
    }
276
 
    FreeBuffer();
277
 
    return false;
278
 
  }
279
 
  position_ += buffer_used_;
280
 
 
281
 
  *size = buffer_used_;
282
 
  *data = buffer_.get();
283
 
  return true;
284
 
}
285
 
 
286
 
void CopyingInputStreamAdaptor::BackUp(int count) {
287
 
  GOOGLE_CHECK(backup_bytes_ == 0 && buffer_.get() != NULL)
288
 
    << " BackUp() can only be called after Next().";
289
 
  GOOGLE_CHECK_LE(count, buffer_used_)
290
 
    << " Can't back up over more bytes than were returned by the last call"
291
 
       " to Next().";
292
 
  GOOGLE_CHECK_GE(count, 0)
293
 
    << " Parameter to BackUp() can't be negative.";
294
 
 
295
 
  backup_bytes_ = count;
296
 
}
297
 
 
298
 
bool CopyingInputStreamAdaptor::Skip(int count) {
299
 
  GOOGLE_CHECK_GE(count, 0);
300
 
 
301
 
  if (failed_) {
302
 
    // Already failed on a previous read.
303
 
    return false;
304
 
  }
305
 
 
306
 
  // First skip any bytes left over from a previous BackUp().
307
 
  if (backup_bytes_ >= count) {
308
 
    // We have more data left over than we're trying to skip.  Just chop it.
309
 
    backup_bytes_ -= count;
310
 
    return true;
311
 
  }
312
 
 
313
 
  count -= backup_bytes_;
314
 
  backup_bytes_ = 0;
315
 
 
316
 
  int skipped = copying_stream_->Skip(count);
317
 
  position_ += skipped;
318
 
  return skipped == count;
319
 
}
320
 
 
321
 
int64 CopyingInputStreamAdaptor::ByteCount() const {
322
 
  return position_ - backup_bytes_;
323
 
}
324
 
 
325
 
void CopyingInputStreamAdaptor::AllocateBufferIfNeeded() {
326
 
  if (buffer_.get() == NULL) {
327
 
    buffer_.reset(new uint8[buffer_size_]);
328
 
  }
329
 
}
330
 
 
331
 
void CopyingInputStreamAdaptor::FreeBuffer() {
332
 
  GOOGLE_CHECK_EQ(backup_bytes_, 0);
333
 
  buffer_used_ = 0;
334
 
  buffer_.reset();
335
 
}
336
 
 
337
 
// ===================================================================
338
 
 
339
 
CopyingOutputStream::~CopyingOutputStream() {}
340
 
 
341
 
CopyingOutputStreamAdaptor::CopyingOutputStreamAdaptor(
342
 
    CopyingOutputStream* copying_stream, int block_size)
343
 
  : copying_stream_(copying_stream),
344
 
    owns_copying_stream_(false),
345
 
    failed_(false),
346
 
    position_(0),
347
 
    buffer_size_(block_size > 0 ? block_size : kDefaultBlockSize),
348
 
    buffer_used_(0) {
349
 
}
350
 
 
351
 
CopyingOutputStreamAdaptor::~CopyingOutputStreamAdaptor() {
352
 
  WriteBuffer();
353
 
  if (owns_copying_stream_) {
354
 
    delete copying_stream_;
355
 
  }
356
 
}
357
 
 
358
 
bool CopyingOutputStreamAdaptor::Flush() {
359
 
  return WriteBuffer();
360
 
}
361
 
 
362
 
bool CopyingOutputStreamAdaptor::Next(void** data, int* size) {
363
 
  if (buffer_used_ == buffer_size_) {
364
 
    if (!WriteBuffer()) return false;
365
 
  }
366
 
 
367
 
  AllocateBufferIfNeeded();
368
 
 
369
 
  *data = buffer_.get() + buffer_used_;
370
 
  *size = buffer_size_ - buffer_used_;
371
 
  buffer_used_ = buffer_size_;
372
 
  return true;
373
 
}
374
 
 
375
 
void CopyingOutputStreamAdaptor::BackUp(int count) {
376
 
  GOOGLE_CHECK_GE(count, 0);
377
 
  GOOGLE_CHECK_EQ(buffer_used_, buffer_size_)
378
 
    << " BackUp() can only be called after Next().";
379
 
  GOOGLE_CHECK_LE(count, buffer_used_)
380
 
    << " Can't back up over more bytes than were returned by the last call"
381
 
       " to Next().";
382
 
 
383
 
  buffer_used_ -= count;
384
 
}
385
 
 
386
 
int64 CopyingOutputStreamAdaptor::ByteCount() const {
387
 
  return position_ + buffer_used_;
388
 
}
389
 
 
390
 
bool CopyingOutputStreamAdaptor::WriteBuffer() {
391
 
  if (failed_) {
392
 
    // Already failed on a previous write.
393
 
    return false;
394
 
  }
395
 
 
396
 
  if (buffer_used_ == 0) return true;
397
 
 
398
 
  if (copying_stream_->Write(buffer_.get(), buffer_used_)) {
399
 
    position_ += buffer_used_;
400
 
    buffer_used_ = 0;
401
 
    return true;
402
 
  } else {
403
 
    failed_ = true;
404
 
    FreeBuffer();
405
 
    return false;
406
 
  }
407
 
}
408
 
 
409
 
void CopyingOutputStreamAdaptor::AllocateBufferIfNeeded() {
410
 
  if (buffer_ == NULL) {
411
 
    buffer_.reset(new uint8[buffer_size_]);
412
 
  }
413
 
}
414
 
 
415
 
void CopyingOutputStreamAdaptor::FreeBuffer() {
416
 
  buffer_used_ = 0;
417
 
  buffer_.reset();
418
 
}
419
74
 
420
75
// ===================================================================
421
76