~ubuntu-branches/debian/experimental/protobuf/experimental

« back to all changes in this revision

Viewing changes to python/google/protobuf/internal/decoder.py

  • Committer: Package Import Robot
  • Author(s): Robert S. Edmonds
  • Date: 2014-09-02 16:57:20 UTC
  • mfrom: (1.3.2) (10.1.7 sid)
  • Revision ID: package-import@ubuntu.com-20140902165720-iafc3f2orkn6i76v
Tags: 2.6.0-1
* New upstream release.
* Upload to experimental.
* Switch to dh sequencer in debian/rules.
* Bump ABI version from 8 to 9.
* Drop all patches from debian/patches/:
  - arm_optimization.diff
      (Appears to be no longer needed.)
  - disable-setuptools-download.diff
      (Disable ez_setup entirely, rather than disabling the downloader
      component inside ez_setup.)
  - fix-ftbfs-gcc4.7-kfreebsd.patch
      (Fixed upstream.)
  - fix-ftbfs-upstream-issue-488.patch
      (Fixed upstream.)
  - revert_upstream_issue_388_about_rpath.diff
      (Fixed upstream.)
* Use dh-autoreconf. (Closes: #725976.)
* Enable the new C++-based Python extension module shipped in 2.6.0.
  See /usr/share/doc/python-protobuf/README.Debian for details.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
29
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
30
 
 
31
#PY25 compatible for GAE.
 
32
#
 
33
# Copyright 2009 Google Inc. All Rights Reserved.
 
34
 
31
35
"""Code for decoding protocol buffer primitives.
32
36
 
33
37
This code is very similar to encoder.py -- read the docs for that module first.
81
85
__author__ = 'kenton@google.com (Kenton Varda)'
82
86
 
83
87
import struct
 
88
import sys  ##PY25
 
89
_PY2 = sys.version_info[0] < 3  ##PY25
84
90
from google.protobuf.internal import encoder
85
91
from google.protobuf.internal import wire_format
86
92
from google.protobuf import message
98
104
_DecodeError = message.DecodeError
99
105
 
100
106
 
101
 
def _VarintDecoder(mask):
 
107
def _VarintDecoder(mask, result_type):
102
108
  """Return an encoder for a basic varint value (does not include tag).
103
109
 
104
110
  Decoded values will be bitwise-anded with the given mask before being
109
115
  """
110
116
 
111
117
  local_ord = ord
 
118
  py2 = _PY2  ##PY25
 
119
##!PY25  py2 = str is bytes
112
120
  def DecodeVarint(buffer, pos):
113
121
    result = 0
114
122
    shift = 0
115
123
    while 1:
116
 
      b = local_ord(buffer[pos])
 
124
      b = local_ord(buffer[pos]) if py2 else buffer[pos]
117
125
      result |= ((b & 0x7f) << shift)
118
126
      pos += 1
119
127
      if not (b & 0x80):
120
128
        result &= mask
 
129
        result = result_type(result)
121
130
        return (result, pos)
122
131
      shift += 7
123
132
      if shift >= 64:
125
134
  return DecodeVarint
126
135
 
127
136
 
128
 
def _SignedVarintDecoder(mask):
 
137
def _SignedVarintDecoder(mask, result_type):
129
138
  """Like _VarintDecoder() but decodes signed values."""
130
139
 
131
140
  local_ord = ord
 
141
  py2 = _PY2  ##PY25
 
142
##!PY25  py2 = str is bytes
132
143
  def DecodeVarint(buffer, pos):
133
144
    result = 0
134
145
    shift = 0
135
146
    while 1:
136
 
      b = local_ord(buffer[pos])
 
147
      b = local_ord(buffer[pos]) if py2 else buffer[pos]
137
148
      result |= ((b & 0x7f) << shift)
138
149
      pos += 1
139
150
      if not (b & 0x80):
142
153
          result |= ~mask
143
154
        else:
144
155
          result &= mask
 
156
        result = result_type(result)
145
157
        return (result, pos)
146
158
      shift += 7
147
159
      if shift >= 64:
148
160
        raise _DecodeError('Too many bytes when decoding varint.')
149
161
  return DecodeVarint
150
162
 
 
163
# We force 32-bit values to int and 64-bit values to long to make
 
164
# alternate implementations where the distinction is more significant
 
165
# (e.g. the C++ implementation) simpler.
151
166
 
152
 
_DecodeVarint = _VarintDecoder((1 << 64) - 1)
153
 
_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1)
 
167
_DecodeVarint = _VarintDecoder((1 << 64) - 1, long)
 
168
_DecodeSignedVarint = _SignedVarintDecoder((1 << 64) - 1, long)
154
169
 
155
170
# Use these versions for values which must be limited to 32 bits.
156
 
_DecodeVarint32 = _VarintDecoder((1 << 32) - 1)
157
 
_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1)
 
171
_DecodeVarint32 = _VarintDecoder((1 << 32) - 1, int)
 
172
_DecodeSignedVarint32 = _SignedVarintDecoder((1 << 32) - 1, int)
158
173
 
159
174
 
160
175
def ReadTag(buffer, pos):
168
183
  use that, but not in Python.
169
184
  """
170
185
 
 
186
  py2 = _PY2  ##PY25
 
187
##!PY25  py2 = str is bytes
171
188
  start = pos
172
 
  while ord(buffer[pos]) & 0x80:
 
189
  while (ord(buffer[pos]) if py2 else buffer[pos]) & 0x80:
173
190
    pos += 1
174
191
  pos += 1
175
192
  return (buffer[start:pos], pos)
284
301
  """
285
302
 
286
303
  local_unpack = struct.unpack
 
304
  b = (lambda x:x) if _PY2 else lambda x:x.encode('latin1')  ##PY25
287
305
 
288
306
  def InnerDecode(buffer, pos):
289
307
    # We expect a 32-bit value in little-endian byte order.  Bit 1 is the sign
294
312
    # If this value has all its exponent bits set, then it's non-finite.
295
313
    # In Python 2.4, struct.unpack will convert it to a finite 64-bit value.
296
314
    # To avoid that, we parse it specially.
297
 
    if ((float_bytes[3] in '\x7F\xFF')
298
 
        and (float_bytes[2] >= '\x80')):
 
315
    if ((float_bytes[3:4] in b('\x7F\xFF'))  ##PY25
 
316
##!PY25    if ((float_bytes[3:4] in b'\x7F\xFF')
 
317
        and (float_bytes[2:3] >= b('\x80'))):  ##PY25
 
318
##!PY25        and (float_bytes[2:3] >= b'\x80')):
299
319
      # If at least one significand bit is set...
300
 
      if float_bytes[0:3] != '\x00\x00\x80':
 
320
      if float_bytes[0:3] != b('\x00\x00\x80'):  ##PY25
 
321
##!PY25      if float_bytes[0:3] != b'\x00\x00\x80':
301
322
        return (_NAN, new_pos)
302
323
      # If sign bit is set...
303
 
      if float_bytes[3] == '\xFF':
 
324
      if float_bytes[3:4] == b('\xFF'):  ##PY25
 
325
##!PY25      if float_bytes[3:4] == b'\xFF':
304
326
        return (_NEG_INF, new_pos)
305
327
      return (_POS_INF, new_pos)
306
328
 
319
341
  """
320
342
 
321
343
  local_unpack = struct.unpack
 
344
  b = (lambda x:x) if _PY2 else lambda x:x.encode('latin1')  ##PY25
322
345
 
323
346
  def InnerDecode(buffer, pos):
324
347
    # We expect a 64-bit value in little-endian byte order.  Bit 1 is the sign
329
352
    # If this value has all its exponent bits set and at least one significand
330
353
    # bit set, it's not a number.  In Python 2.4, struct.unpack will treat it
331
354
    # as inf or -inf.  To avoid that, we treat it specially.
332
 
    if ((double_bytes[7] in '\x7F\xFF')
333
 
        and (double_bytes[6] >= '\xF0')
334
 
        and (double_bytes[0:7] != '\x00\x00\x00\x00\x00\x00\xF0')):
 
355
##!PY25    if ((double_bytes[7:8] in b'\x7F\xFF')
 
356
##!PY25        and (double_bytes[6:7] >= b'\xF0')
 
357
##!PY25        and (double_bytes[0:7] != b'\x00\x00\x00\x00\x00\x00\xF0')):
 
358
    if ((double_bytes[7:8] in b('\x7F\xFF'))  ##PY25
 
359
        and (double_bytes[6:7] >= b('\xF0'))  ##PY25
 
360
        and (double_bytes[0:7] != b('\x00\x00\x00\x00\x00\x00\xF0'))):  ##PY25
335
361
      return (_NAN, new_pos)
336
362
 
337
363
    # Note that we expect someone up-stack to catch struct.error and convert
342
368
  return _SimpleDecoder(wire_format.WIRETYPE_FIXED64, InnerDecode)
343
369
 
344
370
 
 
371
def EnumDecoder(field_number, is_repeated, is_packed, key, new_default):
 
372
  enum_type = key.enum_type
 
373
  if is_packed:
 
374
    local_DecodeVarint = _DecodeVarint
 
375
    def DecodePackedField(buffer, pos, end, message, field_dict):
 
376
      value = field_dict.get(key)
 
377
      if value is None:
 
378
        value = field_dict.setdefault(key, new_default(message))
 
379
      (endpoint, pos) = local_DecodeVarint(buffer, pos)
 
380
      endpoint += pos
 
381
      if endpoint > end:
 
382
        raise _DecodeError('Truncated message.')
 
383
      while pos < endpoint:
 
384
        value_start_pos = pos
 
385
        (element, pos) = _DecodeSignedVarint32(buffer, pos)
 
386
        if element in enum_type.values_by_number:
 
387
          value.append(element)
 
388
        else:
 
389
          if not message._unknown_fields:
 
390
            message._unknown_fields = []
 
391
          tag_bytes = encoder.TagBytes(field_number,
 
392
                                       wire_format.WIRETYPE_VARINT)
 
393
          message._unknown_fields.append(
 
394
              (tag_bytes, buffer[value_start_pos:pos]))
 
395
      if pos > endpoint:
 
396
        if element in enum_type.values_by_number:
 
397
          del value[-1]   # Discard corrupt value.
 
398
        else:
 
399
          del message._unknown_fields[-1]
 
400
        raise _DecodeError('Packed element was truncated.')
 
401
      return pos
 
402
    return DecodePackedField
 
403
  elif is_repeated:
 
404
    tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_VARINT)
 
405
    tag_len = len(tag_bytes)
 
406
    def DecodeRepeatedField(buffer, pos, end, message, field_dict):
 
407
      value = field_dict.get(key)
 
408
      if value is None:
 
409
        value = field_dict.setdefault(key, new_default(message))
 
410
      while 1:
 
411
        (element, new_pos) = _DecodeSignedVarint32(buffer, pos)
 
412
        if element in enum_type.values_by_number:
 
413
          value.append(element)
 
414
        else:
 
415
          if not message._unknown_fields:
 
416
            message._unknown_fields = []
 
417
          message._unknown_fields.append(
 
418
              (tag_bytes, buffer[pos:new_pos]))
 
419
        # Predict that the next tag is another copy of the same repeated
 
420
        # field.
 
421
        pos = new_pos + tag_len
 
422
        if buffer[new_pos:pos] != tag_bytes or new_pos >= end:
 
423
          # Prediction failed.  Return.
 
424
          if new_pos > end:
 
425
            raise _DecodeError('Truncated message.')
 
426
          return new_pos
 
427
    return DecodeRepeatedField
 
428
  else:
 
429
    def DecodeField(buffer, pos, end, message, field_dict):
 
430
      value_start_pos = pos
 
431
      (enum_value, pos) = _DecodeSignedVarint32(buffer, pos)
 
432
      if pos > end:
 
433
        raise _DecodeError('Truncated message.')
 
434
      if enum_value in enum_type.values_by_number:
 
435
        field_dict[key] = enum_value
 
436
      else:
 
437
        if not message._unknown_fields:
 
438
          message._unknown_fields = []
 
439
        tag_bytes = encoder.TagBytes(field_number,
 
440
                                     wire_format.WIRETYPE_VARINT)
 
441
        message._unknown_fields.append(
 
442
          (tag_bytes, buffer[value_start_pos:pos]))
 
443
      return pos
 
444
    return DecodeField
 
445
 
 
446
 
345
447
# --------------------------------------------------------------------
346
448
 
347
449
 
348
 
Int32Decoder = EnumDecoder = _SimpleDecoder(
 
450
Int32Decoder = _SimpleDecoder(
349
451
    wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32)
350
452
 
351
453
Int64Decoder = _SimpleDecoder(
380
482
  local_DecodeVarint = _DecodeVarint
381
483
  local_unicode = unicode
382
484
 
 
485
  def _ConvertToUnicode(byte_str):
 
486
    try:
 
487
      return local_unicode(byte_str, 'utf-8')
 
488
    except UnicodeDecodeError, e:
 
489
      # add more information to the error message and re-raise it.
 
490
      e.reason = '%s in field: %s' % (e, key.full_name)
 
491
      raise
 
492
 
383
493
  assert not is_packed
384
494
  if is_repeated:
385
495
    tag_bytes = encoder.TagBytes(field_number,
394
504
        new_pos = pos + size
395
505
        if new_pos > end:
396
506
          raise _DecodeError('Truncated string.')
397
 
        value.append(local_unicode(buffer[pos:new_pos], 'utf-8'))
 
507
        value.append(_ConvertToUnicode(buffer[pos:new_pos]))
398
508
        # Predict that the next tag is another copy of the same repeated field.
399
509
        pos = new_pos + tag_len
400
510
        if buffer[new_pos:pos] != tag_bytes or new_pos == end:
407
517
      new_pos = pos + size
408
518
      if new_pos > end:
409
519
        raise _DecodeError('Truncated string.')
410
 
      field_dict[key] = local_unicode(buffer[pos:new_pos], 'utf-8')
 
520
      field_dict[key] = _ConvertToUnicode(buffer[pos:new_pos])
411
521
      return new_pos
412
522
    return DecodeField
413
523
 
631
741
 
632
742
def _SkipVarint(buffer, pos, end):
633
743
  """Skip a varint value.  Returns the new position."""
634
 
 
635
 
  while ord(buffer[pos]) & 0x80:
 
744
  # Previously ord(buffer[pos]) raised IndexError when pos is out of range.
 
745
  # With this code, ord(b'') raises TypeError.  Both are handled in
 
746
  # python_message.py to generate a 'Truncated message' error.
 
747
  while ord(buffer[pos:pos+1]) & 0x80:
636
748
    pos += 1
637
749
  pos += 1
638
750
  if pos > end:
699
811
      ]
700
812
 
701
813
  wiretype_mask = wire_format.TAG_TYPE_MASK
702
 
  local_ord = ord
703
814
 
704
815
  def SkipField(buffer, pos, end, tag_bytes):
705
816
    """Skips a field with the specified tag.
712
823
    """
713
824
 
714
825
    # The wire type is always in the first byte since varints are little-endian.
715
 
    wire_type = local_ord(tag_bytes[0]) & wiretype_mask
 
826
    wire_type = ord(tag_bytes[0:1]) & wiretype_mask
716
827
    return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, end)
717
828
 
718
829
  return SkipField