Changeset 5cfb358


Ignore:
Timestamp:
Mar 6, 2011, 4:07:23 PM (13 years ago)
Author:
Jessica B. Hamrick <jhamrick@…>
Branches:
no-cups
Children:
c269bc7
Parents:
ebf327d
git-author:
Jessica B. Hamrick <jhamrick@…> (03/06/11 16:07:23)
git-committer:
Jessica B. Hamrick <jhamrick@…> (03/06/11 16:07:23)
Message:

Change structure of ippvalue.Value to make it easier to manipulate.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • server/lib/ippvalue.py

    rebf327d r5cfb358  
    99class Value():
    1010    """
    11     An IPP value consists of a tag and a value, and optionally, a name.
     11    An IPP value consists of a tag and a value.
    1212
    1313    From RFC 2565:
     
    1515     |                   value-tag                 |   1 byte
    1616     -----------------------------------------------
    17      |               name-length  (value is u)     |   2 bytes
    18      -----------------------------------------------
    19      |                     name                    |   u bytes
     17     |            name-length  (value is 0x0000)   |   2 bytes
    2018     -----------------------------------------------
    2119     |              value-length  (value is v)     |   2 bytes
     
    2523    """
    2624
    27     def __init__(self, value_tag, value, unpack=True):
    28         """
    29         Initialize a Value:
     25    def __init__(self, value_tag=None, value=None, unpack=True):
     26        """
     27        Initialize a Value.  There are three different ways you can
     28        call this method:
     29
     30            Value() -- creates an empty Value instance
     31
     32            Value(value_tag, value) -- creates a Value instance from
     33            binary values
     34
     35            Value(value_tag, value, unpack=False) -- creates a Value
     36            instance from non-binary values
     37
     38        If you create an empty Value instance, once you have set
     39        value_tag and value, you should call pack(), or if you set
     40        value_tag and binary_value, call unpack().
    3041
    3142        Arguments:
     
    3344            value_tag -- one byte, identifying the type of value
    3445
    35             value -- variable size, containing the actual value
    36         """
    37 
    38         # make sure value_tag isn't empty
    39         assert value_tag is not None
    40         # make sure value isn't empty
    41         assert value is not None
    42 
    43         self.value_tag = value_tag
    44         self.value = value
    45 
    46         if not unpack: return
     46            value -- variable size, containing the actual value.  If
     47            unpack is True, then this should be a binary value,
     48            otherwise it should be a string or number.
     49
     50            unpack -- boolean which indicates whether the value passed
     51            in is binary (i.e., should be unpacked) or not (i.e., does
     52            not need to be unpacked)
     53        """
     54
     55        # make sure the arguments are valid
     56        if value_tag is not None:
     57            assert value is not None, \
     58                   "value must not be null because " + \
     59                   "value_tag is not null!"
     60        elif value_tag is None:
     61            assert value is None, \
     62                   "value must be null because value_tag is null!"
     63
     64        # initialize member variables
     65        self.value_tag    = None # one byte, the type of value
     66        self.value        = None # non-binary value of self.value
     67        self.value_size   = None # size of self.value
     68        self.binary_value = None # binary value of self.value
     69
     70        if value_tag is not None and value is not None:
     71            if unpack:
     72                self.value_tag = value_tag
     73                self.binary_value = value
     74                self.unpack()
     75                self.pack()
     76            else:
     77                self.value_tag = value_tag
     78                self.value = value
     79                self.pack()
     80                self.unpack()
     81
     82    def unpack(self):
     83        """
     84        Given self.value_tag and self.binary_value, unpack the binary
     85        value into either a string or number.  These values MUST NOT
     86        be null.  Furthermore, if self.value and self.value_size are
     87        set, this method will check to make sure that unpacking
     88        self.binary_value matches up.
     89
     90        Returns: tuple of (value_size, value)
     91        """
     92
     93        assert self.value_tag is not None, \
     94               "Cannot unpack values with unspecified value tag!"
     95        assert self.binary_value is not None, \
     96               "Cannot unpack null values!"
     97
     98        value_size = None
     99        value = None
    47100
    48101        # out-of-band value tags
     
    51104               self.value_tag == OutOfBandTags.UNKNOWN or \
    52105               self.value_tag == OutOfBandTags.NO_VALUE:
    53             self.value = ''
     106            value_size = 0
     107            value = ''
    54108
    55109        # integer value tags
    56         elif self.value_tag == IntegerTags.GENERIC:
    57             pass # not supported
    58110        elif self.value_tag == IntegerTags.INTEGER:
    59             self.value = struct.unpack('>i', value)[0]
     111            value_size = 4
     112            value = struct.unpack('>i', self.binary_value)[0]
    60113        elif self.value_tag == IntegerTags.BOOLEAN:
    61             self.value = struct.unpack('>?', value)[0]
     114            value_size = 1
     115            value = struct.unpack('>?', self.binary_value)[0]
    62116        elif self.value_tag == IntegerTags.ENUM:
    63             self.value = struct.unpack('>i', value)[0]
    64 
    65         # octet string value tags
    66         elif self.value_tag == OctetStringTags.UNSPECIFIED_OCTETSTRING:
    67             pass
     117            value_size = 4
     118            value = struct.unpack('>i', self.binary_value)[0]
     119
    68120       
    69121        elif self.value_tag == OctetStringTags.DATETIME:
     
    82134            #  10      11    minutes from UTC          0..59
    83135
    84             self.value = struct.unpack('>hbbbbbbcbb', value)[0]
     136            value_size = 11
     137            value = struct.unpack('>hbbbbbbcbb', self.binary_value)[0]
    85138           
    86139        elif self.value_tag == OctetStringTags.RESOLUTION:
     
    92145            # contains the units
    93146
    94             self.value = struct.unpack('>iib', value)
     147            value_size = 9
     148            value = struct.unpack('>iib', self.binary_value)
    95149           
    96150        elif self.value_tag == OctetStringTags.RANGE_OF_INTEGER:
     
    99153            # SIGNED-INTEGER contains the upper bound.
    100154
    101             self.value = struct.unpack('>ii', value)
     155            value_size = 8
     156            value = struct.unpack('>ii', self.binary_value)
    102157
    103158        elif self.value_tag == OctetStringTags.TEXT_WITH_LANGUAGE or \
    104159                 self.value_tag == OctetStringTags.NAME_WITH_LANGUAGE:
    105             a = struct.unpack('>h', value[:2])[0]
    106             b = struct.unpack('>%ss' % a, value[2:a+2])[0]
    107             c = struct.unpack('>h', value[a+2:a+4])[0]
    108             d = struct.unpack('>%ss' % c, value[a+4:][0])
    109             self.value = (a, b, c, d)
     160            a = struct.unpack('>h', self.binary_value[:2])[0]
     161            b = struct.unpack('>%ss' % a, self.binary_value[2:a+2])[0]
     162            c = struct.unpack('>h', self.binary_value[a+2:a+4])[0]
     163            d = struct.unpack('>%ss' % c, self.binary_value[a+4:][0])
     164            value_size = 4 + a + c
     165            value = (a, b, c, d)
    110166
    111167        # character string value tags
    112         elif self.value_tag == CharacterStringTags.TEXT_WITHOUT_LANGUAGE or \
    113                  self.value_tag == CharacterStringTags.NAME_WITHOUT_LANGUAGE:
    114             self.value = str(value)
     168        elif self.value_tag == \
     169                 CharacterStringTags.TEXT_WITHOUT_LANGUAGE or \
     170                 self.value_tag == \
     171                 CharacterStringTags.NAME_WITHOUT_LANGUAGE:
     172            value_size = len(str(self.binary_value))
     173            value = str(self.binary_value)
    115174        elif self.value_tag == CharacterStringTags.GENERIC or \
    116175                 self.value_tag == CharacterStringTags.KEYWORD or \
     
    120179                 self.value_tag == CharacterStringTags.NATURAL_LANGUAGE or \
    121180                 self.value_tag == CharacterStringTags.MIME_MEDIA_TYPE:
    122             self.value = str(value)
    123 
    124     def valueToBinary(self):
     181            value_size = len(str(self.binary_value))
     182            value = str(self.binary_value)
     183
     184        # anything else that we didn't handle
     185        else:
     186            if value_size is None and value is None:
     187                value_size = len(self.binary_value)
     188                value = self.binary_value
     189
     190        if self.value_size is not None:
     191            assert value_size == self.value_size, \
     192                   "unpacked value_size is not the same " + \
     193                   "as self.value_size!"
     194        if self.value is not None:
     195            assert value == self.value, \
     196                   "unpacked value is not the same as self.value!"
     197
     198        self.value_size = value_size
     199        self.value = value
     200       
     201        return value_size, value
     202
     203    def pack(self):
     204        """
     205        Given self.value_tag and self.value, pack the value into
     206        binary formo.  These values MUST NOT be null.  Furthermore, if
     207        self.binary_value and self.value_size are set, this method
     208        will check to make sure that packing self.value matches up.
     209
     210        Returns: tuple of (value_size, binary_value)
     211        """
     212       
     213        assert self.value_tag is not None, \
     214               "cannot pack value with null value tag!"
     215        assert self.value is not None, \
     216               "cannot pack null value!"
     217
     218        value_size = None
     219        binary_value = None
    125220
    126221        # out-of-band value tags
     
    129224               self.value_tag == OutOfBandTags.UNKNOWN or \
    130225               self.value_tag == OutOfBandTags.NO_VALUE:
    131             return (0, '')
     226            value_size = 0
     227            binary_value = ''
    132228
    133229        # integer value tags
    134         elif self.value_tag == IntegerTags.GENERIC:
    135             pass
    136230        elif self.value_tag == IntegerTags.INTEGER:
    137             return (4, struct.pack('>i', self.value))
     231            value_size = 4
     232            binary_value = struct.pack('>i', self.value)
    138233        elif self.value_tag == IntegerTags.BOOLEAN:
    139             return (1, struct.pack('>?', self.value))
     234            value_size = 1
     235            binary_value = struct.pack('>?', self.value)
    140236        elif self.value_tag == IntegerTags.ENUM:
    141             return (4, struct.pack('>i', self.value))
     237            value_size = 4
     238            binary_value = struct.pack('>i', self.value)
    142239
    143240        # octet string value tags
    144         elif self.value_tag == OctetStringTags.UNSPECIFIED_OCTETSTRING:
    145             pass
    146241        elif self.value_tag == OctetStringTags.DATETIME:
    147242            # field  octets  contents                  range
     
    158253            #   9      10    hours from UTC            0..11
    159254            #  10      11    minutes from UTC          0..59
    160            
    161             return (11, struct.pack('>hbbbbbbcbb', self.value))
     255
     256            value_size = 11
     257            binary_value = struct.pack('>hbbbbbbcbb', self.value)
    162258           
    163259        elif self.value_tag == OctetStringTags.RESOLUTION:
     
    168264            # the value of feed direction resolution. The SIGNED-BYTE
    169265            # contains the units
    170            
    171             return (9, struct.pack('>iib', self.value))
     266
     267            value_size = 9
     268            binary_value = truct.pack('>iib', self.value)
    172269           
    173270        elif self.value_tag == OctetStringTags.RANGE_OF_INTEGER:
     
    175272            # SIGNED-INTEGER contains the lower bound and the second
    176273            # SIGNED-INTEGER contains the upper bound.
    177            
    178             return (8, struct.pack('>ii', self.value))
     274
     275            value_size = 8
     276            binary_value = struct.pack('>ii', self.value)
    179277
    180278        elif self.value_tag == OctetStringTags.TEXT_WITH_LANGUAGE or \
    181279                 self.value_tag == OctetStringTags.NAME_WITH_LANGUAGE:
     280           
    182281            a_bin = struct.pack('>h', self.value[0])
    183282            b_bin = struct.pack('>%ss' % self.value[0], self.value[1])
    184283            c_bin = struct.pack('>h', self.value[2])
    185284            d_bin = struct.pack('>%ss' % self.value[2], self.value[3])
    186             return (4 + self.value[0] + self.value[2],
    187                     a_bin + b_bin + c_bin + d_bin)
     285
     286            value_size = 4 + self.value[0] + self.value[2]
     287            binary_value = a_bin + b_bin + c_bin + d_bin
    188288
    189289        # character string value tags
    190         elif self.value_tag == CharacterStringTags.TEXT_WITHOUT_LANGUAGE or \
    191                  self.value_tag == CharacterStringTags.NAME_WITHOUT_LANGUAGE:
    192             return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
     290        elif self.value_tag == \
     291                 CharacterStringTags.TEXT_WITHOUT_LANGUAGE or \
     292                 self.value_tag == \
     293                 CharacterStringTags.NAME_WITHOUT_LANGUAGE:
     294
     295            value_size = len(self.value)
     296            binary_value = struct.pack('>%ss' % len(self.value),
     297                                       self.value)
     298                   
    193299        elif self.value_tag == CharacterStringTags.GENERIC or \
    194300                 self.value_tag == CharacterStringTags.KEYWORD or \
     
    198304                 self.value_tag == CharacterStringTags.NATURAL_LANGUAGE or \
    199305                 self.value_tag == CharacterStringTags.MIME_MEDIA_TYPE:
    200             return (len(self.value), struct.pack('>%ss' % len(self.value), self.value))
    201 
    202         return len(self.value), self.value
     306           
     307            value_size = len(self.value)
     308            binary_value = struct.pack('>%ss' % len(self.value),
     309                                       self.value)
     310
     311        else:
     312            value_size = len(self.value)
     313            binary_value = self.value
     314
     315        if self.value_size is not None:
     316            assert value_size == self.value_size, \
     317                   "packed value size is not the same as " + \
     318                   "self.value_size!"
     319        if self.binary_value is not None:
     320            assert binary_value == self.binary_value, \
     321                   "packed binary value is not the same as " + \
     322                   "self.binary_value!"
     323
     324        self.value_size = value_size
     325        self.binary_value = binary_value
     326
     327        return value_size, binary_value
     328
     329    def verify(self):
     330        """
     331        Verifies that the binary and non-binary values for this Value
     332        instance line up.  All of self.value, self.binary_value,
     333        self.value_size, and self.value_tag must be defined.
     334
     335        This function will throw an assertion error if the Value
     336        instance is not valid.
     337        """
     338
     339        assert self.value is not None, \
     340               "value is null!"
     341        assert self.binary_value is not None, \
     342               "binary value is null!"
     343        assert self.value_size is not None, \
     344               "value size is unknown!"
     345        assert self.value_tag is not None, \
     346               "value type is unknown!"
     347
     348        self.pack()
     349        self.unpack()
     350
     351    def getValue(self):
     352        """
     353        Get the non-binary value.
     354        """
     355
     356        return self.value
     357
     358    def getBinaryValue(self):
     359        """
     360        Get the binary value.
     361        """
     362       
     363        return self.binary_value
     364
     365    def getValueTag(self):
     366        """
     367        Get the value tag (type of value). This is an integer
     368        corresponding to a value in ippconstants.
     369        """
     370       
     371        return self.value_tag
     372
     373    def getSize(self):
     374        """
     375        Get the size of the value in bytes.
     376        """
     377       
     378        return self.value_size
     379
     380    def setValue(self, value):
     381        """
     382        Set the non-binary value.
     383        """
     384       
     385        self.value = value
     386
     387    def setBinaryValue(self, binary_value):
     388        """
     389        Set the binary value.
     390        """
     391        self.binary_value = binary_value
     392
     393    def setValueTag(self, value_tag):
     394        """
     395        Set the type (tag) of the value.  This should correspond to an
     396        integer defined in ippconstants.
     397        """
     398       
     399        self.value_tag = value_tag
     400
     401    def setSize(self, size):
     402        """
     403        Set the size of the value in bytes.
     404        """
     405       
     406        self.value_size = size
     407
     408    def __str__(self):
     409        return self.value
Note: See TracChangeset for help on using the changeset viewer.