~verterok/ubuntu/lucid/protobuf/2.4.0a-backport

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2011-05-31 14:41:47 UTC
  • mfrom: (2.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20110531144147-s41g5fozgvyo462l
Tags: 2.4.0a-2ubuntu1
* Merge with Debian; remaining changes:
  - Fix linking with -lpthread.

Show diffs side-by-side

added added

removed removed

Lines of Context:
70
70
from google.protobuf.internal import wire_format
71
71
 
72
72
 
 
73
# This will overflow and thus become IEEE-754 "infinity".  We would use
 
74
# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
 
75
_POS_INF = 1e10000
 
76
_NEG_INF = -_POS_INF
 
77
 
 
78
 
73
79
def _VarintSize(value):
74
80
  """Compute the size of a varint value."""
75
81
  if value <= 0x7f: return 1
502
508
  return SpecificEncoder
503
509
 
504
510
 
 
511
def _FloatingPointEncoder(wire_type, format):
 
512
  """Return a constructor for an encoder for float fields.
 
513
 
 
514
  This is like StructPackEncoder, but catches errors that may be due to
 
515
  passing non-finite floating-point values to struct.pack, and makes a
 
516
  second attempt to encode those values.
 
517
 
 
518
  Args:
 
519
      wire_type:  The field's wire type, for encoding tags.
 
520
      format:  The format string to pass to struct.pack().
 
521
  """
 
522
 
 
523
  value_size = struct.calcsize(format)
 
524
  if value_size == 4:
 
525
    def EncodeNonFiniteOrRaise(write, value):
 
526
      # Remember that the serialized form uses little-endian byte order.
 
527
      if value == _POS_INF:
 
528
        write('\x00\x00\x80\x7F')
 
529
      elif value == _NEG_INF:
 
530
        write('\x00\x00\x80\xFF')
 
531
      elif value != value:           # NaN
 
532
        write('\x00\x00\xC0\x7F')
 
533
      else:
 
534
        raise
 
535
  elif value_size == 8:
 
536
    def EncodeNonFiniteOrRaise(write, value):
 
537
      if value == _POS_INF:
 
538
        write('\x00\x00\x00\x00\x00\x00\xF0\x7F')
 
539
      elif value == _NEG_INF:
 
540
        write('\x00\x00\x00\x00\x00\x00\xF0\xFF')
 
541
      elif value != value:                         # NaN
 
542
        write('\x00\x00\x00\x00\x00\x00\xF8\x7F')
 
543
      else:
 
544
        raise
 
545
  else:
 
546
    raise ValueError('Can\'t encode floating-point values that are '
 
547
                     '%d bytes long (only 4 or 8)' % value_size)
 
548
 
 
549
  def SpecificEncoder(field_number, is_repeated, is_packed):
 
550
    local_struct_pack = struct.pack
 
551
    if is_packed:
 
552
      tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
 
553
      local_EncodeVarint = _EncodeVarint
 
554
      def EncodePackedField(write, value):
 
555
        write(tag_bytes)
 
556
        local_EncodeVarint(write, len(value) * value_size)
 
557
        for element in value:
 
558
          # This try/except block is going to be faster than any code that
 
559
          # we could write to check whether element is finite.
 
560
          try:
 
561
            write(local_struct_pack(format, element))
 
562
          except SystemError:
 
563
            EncodeNonFiniteOrRaise(write, element)
 
564
      return EncodePackedField
 
565
    elif is_repeated:
 
566
      tag_bytes = TagBytes(field_number, wire_type)
 
567
      def EncodeRepeatedField(write, value):
 
568
        for element in value:
 
569
          write(tag_bytes)
 
570
          try:
 
571
            write(local_struct_pack(format, element))
 
572
          except SystemError:
 
573
            EncodeNonFiniteOrRaise(write, element)
 
574
      return EncodeRepeatedField
 
575
    else:
 
576
      tag_bytes = TagBytes(field_number, wire_type)
 
577
      def EncodeField(write, value):
 
578
        write(tag_bytes)
 
579
        try:
 
580
          write(local_struct_pack(format, value))
 
581
        except SystemError:
 
582
          EncodeNonFiniteOrRaise(write, value)
 
583
      return EncodeField
 
584
 
 
585
  return SpecificEncoder
 
586
 
 
587
 
505
588
# ====================================================================
506
589
# Here we declare an encoder constructor for each field type.  These work
507
590
# very similarly to sizer constructors, described earlier.
525
608
Fixed64Encoder  = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
526
609
SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
527
610
SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
528
 
FloatEncoder    = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<f')
529
 
DoubleEncoder   = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<d')
 
611
FloatEncoder    = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f')
 
612
DoubleEncoder   = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
530
613
 
531
614
 
532
615
def BoolEncoder(field_number, is_repeated, is_packed):