~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/pack.py

  • Committer: Andrew Bennetts
  • Date: 2007-10-19 08:37:14 UTC
  • mto: (2535.4.14 streaming-smart-fetch)
  • mto: This revision was merged to the branch mainline in revision 2981.
  • Revision ID: andrew.bennetts@canonical.com-20071019083714-h5k2lcltixga71kx
Initial implementation of a 'push' parser for the container format.

Show diffs side-by-side

added added

removed removed

Lines of Context:
355
355
                _check_name_encoding(name)
356
356
        read_bytes(None)
357
357
 
 
358
 
 
359
class ContainerPushParser(object):
 
360
 
 
361
    def __init__(self):
 
362
        self._buffer = ''
 
363
        self._state_handler = self._state_expecting_format_line
 
364
        self._parsed_records = []
 
365
        self._reset_current_record()
 
366
 
 
367
    def _reset_current_record(self):
 
368
        self._current_record_length = None
 
369
        self._current_record_names = []
 
370
 
 
371
    def accept_bytes(self, bytes):
 
372
        self._buffer += bytes
 
373
        # Keep iterating the state machine until it stops consuming bytes from
 
374
        # the buffer.
 
375
        buffer_length = None
 
376
        from bzrlib.trace import mutter
 
377
        while len(self._buffer) != buffer_length:
 
378
            mutter('state: %r, buffer: %r', self._buffer, self._state_handler)
 
379
            buffer_length = len(self._buffer)
 
380
            self._state_handler()
 
381
 
 
382
    def read_pending_records(self):
 
383
        records = self._parsed_records
 
384
        self._parsed_records = []
 
385
        return records
 
386
    
 
387
    def _consume_until_byte(self, byte):
 
388
        """Take all bytes up to the given out of the buffer, and return it.
 
389
 
 
390
        If the specified byte is not found in the buffer, the buffer is
 
391
        unchanged and this returns None instead.
 
392
        """
 
393
        newline_pos = self._buffer.find('\n')
 
394
        if newline_pos != -1:
 
395
            line = self._buffer[:newline_pos]
 
396
            self._buffer = self._buffer[newline_pos+1:]
 
397
            return line
 
398
        else:
 
399
            return None
 
400
 
 
401
    def _consume_line(self):
 
402
        return self._consume_until_byte('\n')
 
403
 
 
404
    def _state_expecting_format_line(self):
 
405
        line = self._consume_line()
 
406
        if line is not None:
 
407
            if line != FORMAT_ONE:
 
408
                raise errors.UnknownContainerFormatError(line)
 
409
            self._state_handler = self._state_expecting_record_type
 
410
 
 
411
    def _state_expecting_record_type(self):
 
412
        if len(self._buffer) >= 1:
 
413
            record_type = self._buffer[0]
 
414
            self._buffer = self._buffer[1:]
 
415
            if record_type != 'B':
 
416
                raise NotImplementedError('XXX')
 
417
            self._state_handler = self._state_expecting_length
 
418
 
 
419
    def _state_expecting_length(self):
 
420
        line = self._consume_line()
 
421
        if line is not None:
 
422
            try:
 
423
                self._current_record_length = int(line)
 
424
            except ValueError:
 
425
                raise errors.InvalidRecordError(
 
426
                    "%r is not a valid length." % (line,))
 
427
            self._state_handler = self._state_expecting_name
 
428
 
 
429
    def _state_expecting_name(self):
 
430
        encoded_name_parts = self._consume_line()
 
431
        if encoded_name_parts is not None:
 
432
            if encoded_name_parts == '':
 
433
                self._state_handler = self._state_expecting_body
 
434
            else:
 
435
                name_parts = tuple(encoded_name_parts.split('\x00'))
 
436
                for name_part in name_parts:
 
437
                    _check_name(name_part)
 
438
                self._current_record_names.append(name_parts)
 
439
            
 
440
    def _state_expecting_body(self):
 
441
        if len(self._buffer) >= self._current_record_length:
 
442
            body_bytes = self._buffer[:self._current_record_length]
 
443
            self._buffer = self._buffer[self._current_record_length:]
 
444
            record = (self._current_record_names, body_bytes)
 
445
            self._parsed_records.append(record)
 
446
            self._reset_current_record()
 
447
            self._state_handler = self._state_expecting_record_type
 
448
 
 
449