netmsgs  1.2.2
RoadNarrows Robotics Network Messaging Package
NetMsgsLib.py
Go to the documentation of this file.
1 ###############################################################################
2 #
3 # Package: NetMsgs
4 #
5 # File: NetMsgsLib.py
6 #
7 
8 """
9 NetMsgs Run-Time Library Packing and Unpacking Base Module
10 """
11 
12 ## \file
13 ## \package NetMsgs.NetMsgsLib
14 ##
15 ## $LastChangedDate: 2010-08-04 15:07:55 -0600 (Wed, 04 Aug 2010) $
16 ## $Rev: 550 $
17 ##
18 ## \brief NetMsgs Run-Time Library Packing and Unpacking Base Module
19 ##
20 ## The NetsMsgsLib module provides basic packing and unpacking functions plus
21 ## some byte and bit utilities.
22 ##
23 ## \sa
24 ## \htmlonly
25 ## <a href="../pydoc/NetMsgs.NetMsgsLib.html">PyDoc Generated Documentation</a>
26 ## \endhtmlonly
27 ##
28 ## \author Robin Knight (robin.knight@roadnarrows.com)
29 ##
30 ## \copyright
31 ## \h_copy 2010-2017. RoadNarrows LLC.\n
32 ## http://www.roadnarrows.com\n
33 ## All Rights Reserved
34 ##
35 
36 # Permission is hereby granted, without written agreement and without
37 # license or royalty fees, to use, copy, modify, and distribute this
38 # software and its documentation for any purpose, provided that
39 # (1) The above copyright notice and the following two paragraphs
40 # appear in all copies of the source code and (2) redistributions
41 # including binaries reproduces these notices in the supporting
42 # documentation. Substantial modifications to this software may be
43 # copyrighted by their authors and need not follow the licensing terms
44 # described here, provided that the new terms are clearly indicated in
45 # all files where they apply.
46 #
47 # IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
48 # OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
49 # PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
50 # DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
51 # EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
52 # THE POSSIBILITY OF SUCH DAMAGE.
53 #
54 # THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
55 # INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
56 # FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
57 # "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
58 # PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
59 #
60 ###############################################################################
61 
62 import sys
63 import warnings
64 import struct
65 
66 import NetMsgsBase as nmBase
67 
68 #
69 # Set filter for warnings.
70 #
71 # DeprecationWarning:
72 # Issued by strut module. Convert deprecation warning to error since it is
73 # really an out-of-range error.
74 #
75 # RuntimeWarning:
76 # NetMsgs run-time warnings are printed.
77 #
78 warnings.simplefilter('error', DeprecationWarning)
79 warnings.simplefilter('always', RuntimeWarning)
80 
81 
82 #-----------------------------------------------------------------------------
83 # Globals
84 #-----------------------------------------------------------------------------
85 
86 #
87 # Error Messages
88 #
89 
90 ## bad integer identifier
91 EMsgBadId = "Identifier not an integer"
92 ## bad endian
93 EMsgEndian = "Invalid byte order value"
94 ## buffer too small
95 EMsgNoMem = "No space in buffer"
96 ## bad value type
97 EMsgFValType = "Invalid field value type"
98 ## value not defined
99 EMsgNoFVal = "Field value not defined"
100 ## bad range
101 EMsgRange = "Field value out-of-range"
102 ## bad integer range
103 EMsgIntRange = "Integer out-of-range"
104 ## bad FPN range
105 EMsgFPNRange = "Floating-point number out-of-range"
106 ## bad string length
107 EMsgStringRange = "String length out-of-range"
108 ## bad struct count
109 EMsgStructRange = "Message/Struct field count out-of-range"
110 ## bad vector length
111 EMsgVectorRange = "Vector length out-of-range"
112 ## bad buffer
113 EMsgBufType = "Invalid buffer type"
114 ## no msg definition
115 EMsgNoMsgDef = "Message definition not found"
116 ## missing keyword
117 EMsgReqKeyword = "Required definition keyword not found"
118 ## index out of range
119 EMsgNoIndex = "Required index out of range"
120 ## bad message
121 EMsgBadMsg = "Bad message format"
122 
123 
124 #-----------------------------------------------------------------------------
125 # Locals
126 #-----------------------------------------------------------------------------
127 
128 ## Message byte ordering type - struct module code equivalent
129 _EndianCode = {'big':'>', 'little':'<', 'native':'='}
130 
131 ## Native endianess
132 _EndianNative = None
133 
134 
135 #-----------------------------------------------------------------------------
136 # Utilities
137 #-----------------------------------------------------------------------------
138 
139 #--
141  """ Get the native byte order.
142 
143  Return:
144  'big' or 'little'
145  """
146  global _EndianNative
147  if not _EndianNative:
148  if PackU16(1, endian='native') == '\0x00\0x01':
149  _EndianNative = 'big'
150  else:
151  _EndianNative = 'little'
152  return _EndianNative
153 ##
154 
155 
156 #-----------------------------------------------------------------------------
157 # Base Packing Functions
158 #-----------------------------------------------------------------------------
159 
160 #--
161 def _PackException(ftype, val, endian, inst):
162  """ Parse raised exception during packing, and re-raise as NetMsgError.
163 
164  Parameters:
165  ftype - Readable field type where exception occurred.
166  val - Field value.
167  endian - Byte order.
168  inst - Exception instance.
169  """
170  exception = type(inst)
171 
172  # endian is the only key that can cause this exception
173  if exception == KeyError:
174  raise nmBase.NetMsgsError("pack endian=%s: %s" % \
175  (repr(endian), EMsgEndian))
176 
177  # field value is the wrong type
178  elif exception == TypeError:
179  raise nmBase.NetMsgsError("pack %s=%s: %s" % \
180  (ftype, repr(val), EMsgFValType))
181 
182  # struct warning format: "'X' format requires m <= number <= M"
183  elif exception == DeprecationWarning:
184  emsg = inst.args[0]
185  emsg = emsg.partition('format requires ')[2]
186  emsg = EMsgRange + ' ' + emsg
187  raise nmBase.NetMsgsError("pack %s=%s: %s" % (ftype, repr(val), emsg))
188 
189  # other exception
190  else:
191  raise nmBase.NetMsgsError("pack %s: %s" % (ftype, inst))
192 ##
193 
194 #--
195 def PackBool(val, endian='big'):
196  """ Pack boolean into 1 byte.
197 
198  Parameters:
199  val - Field value.
200  endian - Byte order.
201 
202  Return:
203  Binary string.
204  """
205  if val:
206  return PackU8(1, endian=endian)
207  else:
208  return PackU8(0, endian=endian)
209 ##
210 
211 #--
212 def PackChar(val, endian='big'):
213  """ Pack one 8-bit ASCII character into 1 byte.
214 
215  Parameters:
216  val - Field value.
217  endian - Byte order.
218 
219  Return:
220  Binary string.
221  """
222  try:
223  return struct.pack('c', val)
224  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
225  _PackException('char', val, endian, inst)
226 ##
227 
228 #--
229 def PackU8(val, endian='big'):
230  """ Pack an 8-bit unsigned integer into 1 byte.
231 
232  Parameters:
233  val - Field value.
234  endian - Byte order.
235 
236  Return:
237  Binary string.
238  """
239  if (type(val) == str) and len(val) == 1:
240  val = ord(val)
241  try:
242  return struct.pack(_EndianCode[endian]+'B', val)
243  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
244  _PackException('u8', val, endian, inst)
245 ##
246 
247 #--
248 def PackS8(val, endian='big'):
249  """ Pack an 8-bit signed integer into 1 byte.
250 
251  Parameters:
252  val - Field value.
253  endian - Byte order.
254 
255  Return:
256  Binary string.
257  """
258  if (type(val) == str) and len(val) == 1:
259  val = ord(val)
260  try:
261  return struct.pack(_EndianCode[endian]+'b', val)
262  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
263  _PackException('s8', val, endian, inst)
264 ##
265 
266 #--
267 def PackU16(val, endian='big'):
268  """ Pack a 16-bit unsigned integer into 2 bytes.
269 
270  Parameters:
271  val - Field value.
272  endian - Byte order.
273 
274  Return:
275  Binary string.
276  """
277  try:
278  return struct.pack(_EndianCode[endian]+'H', val)
279  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
280  _PackException('u16', val, endian, inst)
281 ##
282 
283 #--
284 def PackS16(val, endian='big'):
285  """ Pack a 16-bit signed integer into 2 bytes.
286 
287  Parameters:
288  val - Field value.
289  endian - Byte order.
290 
291  Return:
292  Binary string.
293  """
294  try:
295  return struct.pack(_EndianCode[endian]+'h', val)
296  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
297  _PackException('s16', val, endian, inst)
298 ##
299 
300 #--
301 def PackU32(val, endian='big'):
302  """ Pack a 32-bit unsigned integer into 4 bytes.
303 
304  Parameters:
305  val - Field value.
306  endian - Byte order.
307 
308  Return:
309  Binary string.
310  """
311  try:
312  return struct.pack(_EndianCode[endian]+'I', val)
313  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
314  _PackException('u32', val, endian, inst)
315 ##
316 
317 #--
318 def PackS32(val, endian='big'):
319  """ Pack a 32-bit signed integer into 4 bytes.
320 
321  Parameters:
322  val - Field value.
323  endian - Byte order.
324 
325  Return:
326  Binary string.
327  """
328  try:
329  return struct.pack(_EndianCode[endian]+'i', val)
330  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
331  _PackException('s32', val, endian, inst)
332 ##
333 
334 #--
335 def PackU64(val, endian='big'):
336  """ Pack a 64-bit unsigned integer into 8 bytes.
337 
338  If native architectures only support 4 byte long long's, then the 4 MSBs
339  are padded with zero's.
340 
341  Parameters:
342  val - Field value.
343  endian - Byte order.
344 
345  Return:
346  Binary string.
347  """
348  if struct.calcsize('Q') == 8:
349  try:
350  return struct.pack(_EndianCode[endian]+'Q', val)
351  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
352  _PackException('u64', val, endian, inst)
353  elif endian == 'big' or \
354  (endian == 'native' and GetNativeByteOrder() == 'big'):
355  return PackU32(0, endian='big') + PackU32(val, endian='big')
356  else: # little
357  return PackU32(val, endian='little') + PackU32(0, endian='little')
358 ##
359 
360 #--
361 def PackS64(val, endian='big'):
362  """ Pack a 64-bit signed integer into 8 bytes.
363 
364  If native architectures only support 4 byte long long's, then the 4 MSBs
365  are padded with zero's.
366 
367  Parameters:
368  val - Field value.
369  endian - Byte order.
370 
371  Return:
372  Binary string.
373  """
374  if struct.calcsize('q') == 8:
375  try:
376  return struct.pack(_EndianCode[endian]+'q', val)
377  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
378  _PackException('s64', val, endian, inst)
379  if val & 0x80000000:
380  msb = 0xffffffff # negative value, extend sign
381  else:
382  msb = 0 # positive value
383  if endian == 'big' or (endian == 'native' and GetNativeByteOrder() == 'big'):
384  return PackS32(msb, endian='big') + PackS32(val, endian='big')
385  else: # little
386  return PackS32(val, endian='little') + PackS32(msb, endian='little')
387 ##
388 
389 #--
390 def PackF32(val, endian='big'):
391  """ Pack a 32-bit floating-point number into 4 bytes.
392 
393  Is this guaranteed to be in IEEE 745 32-bit format?
394 
395  Parameters:
396  val - Field value.
397  endian - Byte order.
398 
399  Return:
400  Binary string.
401  """
402  try:
403  return struct.pack(_EndianCode[endian]+'f', val)
404  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
405  _PackException('f32', val, endian, inst)
406 ##
407 
408 #--
409 def PackF64(val, endian='big'):
410  """ Pack a 64-bit floating-point number into 8 bytes.
411 
412  Is this guaranteed to be in IEEE 745 64-bit format?
413  Will this pack into 8 bytes on 32-bit architectures?
414 
415  Parameters:
416  val - Field value.
417  endian - Byte order.
418 
419  Return:
420  Binary string.
421  """
422  try:
423  return struct.pack(_EndianCode[endian]+'d', val)
424  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
425  _PackException('f64', val, endian, inst)
426 ##
427 
428 #--
429 def PackP32(val, endian='big'):
430  """ Pack a 32-bit floating-point number into 4 bytes.
431 
432  Note:
433  Pointers are really foreign to python. However, a python application
434  may have a linked c library that requires it. And NetMsgs supports it.
435 
436  Note:
437  Pointers are always packed in native byte order.
438 
439  Parameters:
440  val - Field value.
441  endian - Byte order.
442 
443  Return:
444  Binary string.
445  """
446  if struct.calcsize('L') == 4:
447  try:
448  return struct.pack(_EndianCode['native']+'L', val)
449  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
450  _PackException('p32', val, endian, inst)
451  else:
452  msb = val >> 32
453  lsb = val & 0xffffffff
454  if msb != 0:
455  warnings.warn("pack p32=%u: non-zero 4 MSB's truncated" % (val),
456  RuntimeWarning)
457  try:
458  return struct.pack(_EndianCode['native']+'I', lsb)
459  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
460  _PackException('p32', val, endian, inst)
461 ##
462 
463 #--
464 def PackP64(val, endian='big'):
465  """ Pack a 64-bit floating-point number into 8 bytes.
466 
467  Note:
468  Pointers are really foreign to python. However, a python application
469  may have a linked c library that requires it. And NetMsgs supports it.
470 
471  Note:
472  Pointers are always packed in native byte order.
473 
474  Parameters:
475  val - Field value.
476  endian - Byte order.
477 
478  Return:
479  Binary string.
480  """
481  if struct.calcsize('L') == 8:
482  try:
483  return struct.pack(_EndianCode['native']+'Q', val)
484  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
485  _PackException('p64', val, endian, inst)
486  elif GetNativeByteOrder() == 'big':
487  return PackU32(0, endian='big') + PackU32(val, endian='big')
488  else: # little
489  return PackU32(val, endian='little') + PackU32(0, endian='little')
490 ##
491 
492 #--
493 def PackString(val, count=None):
494  """ Pack a string.
495 
496  The endianess is ignore.
497  The terminating Null is not packed.
498 
499  Parameters:
500  val - Field value.
501  count - Number of bytes to pack. None == all.
502 
503  Return:
504  Binary string.
505  """
506  try:
507  n = len(val)
508  if count is None:
509  count = n
510  elif count > n:
511  val += (count-n) * '\x00'
512  except (TypeError) as inst:
513  _PackException('string', val, endian, inst)
514  try:
515  return struct.pack("%us" % (count), val)
516  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
517  _PackException('string', val, endian, inst)
518 ##
519 
520 
521 #-----------------------------------------------------------------------------
522 # Base Unpacking Functions
523 #-----------------------------------------------------------------------------
524 
525 #--
526 def _UnpackException(ftype, offset, endian, inst):
527  """ Parse raised exception during unpacking, and re-raise as NetMsgError.
528 
529  Parameters:
530  ftype - Readable field type where exception occurred.
531  offset - Offset in buffer where error occurred.
532  endian - Byte order.
533  inst - Exception instance.
534  """
535  exception = type(inst)
536 
537  # endian is the only key that can cause this exception
538  if exception == KeyError:
539  raise nmBase.NetMsgsError("unpack endian=%s: %s" % \
540  (repr(endian), EMsgEndian))
541 
542  # field value is the wrong type
543  elif exception == TypeError:
544  raise nmBase.NetMsgsError("unpack %s: offset=%u: %s" % \
545  (ftype, offset, EMsgBufType))
546 
547  # struct error format: "unpack_from ... "
548  elif exception == struct.error:
549  emsg = inst.args[0]
550  emsg = emsg.partition('unpack_from ')[2]
551  emsg = 'Field ' + emsg
552  raise nmBase.NetMsgsError("unpack %s: offset=%u: %s" % \
553  (ftype, offset, emsg))
554 
555  # other exception
556  else:
557  raise nmBase.NetMsgsError("unpack %s: offset=%u: %s" % \
558  (ftype, offset, inst))
559 ##
560 
561 #--
562 def UnpackBool(buf, offset=0, endian='big'):
563  """ Unpack boolean into 1 byte.
564 
565  Parameters:
566  buf - Input packed buffer.
567  offset - Offset in buffer.
568  endian - Byte order.
569 
570  Return:
571  2-tuple of unpacked value, new buffer offset.
572  """
573  val, offset = UnpackU8(buf, offset=offset, endian=endian)
574  if val:
575  return True, offset
576  else:
577  return False, offset
578 ##
579 
580 #--
581 def UnpackChar(buf, offset=0, endian='big'):
582  """ Unpack one 8-bit ASCII character into 1 byte.
583 
584  Parameters:
585  buf - Input packed buffer.
586  offset - Offset in buffer.
587  endian - Byte order.
588 
589  Return:
590  2-tuple of unpacked value, new buffer offset.
591  """
592  try:
593  return (struct.unpack_from(_EndianCode[endian]+'c', buf, offset)[0],
594  offset+1)
595  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
596  _UnpackException('char', offset, endian, inst)
597 ##
598 
599 #--
600 def UnpackU8(buf, offset=0, endian='big'):
601  """ Unpack an 8-bit unsigned integer into 1 byte.
602 
603  Parameters:
604  buf - Input packed buffer.
605  offset - Offset in buffer.
606  endian - Byte order.
607 
608  Return:
609  2-tuple of unpacked value, new buffer offset.
610  """
611  try:
612  return (struct.unpack_from(_EndianCode[endian]+'B', buf, offset)[0],
613  offset+1)
614  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
615  _UnpackException('u8', offset, endian, inst)
616 ##
617 
618 #--
619 def UnpackS8(buf, offset=0, endian='big'):
620  """ Unpack an 8-bit signed integer into 1 byte.
621 
622  Parameters:
623  buf - Input packed buffer.
624  offset - Offset in buffer.
625  endian - Byte order.
626 
627  Return:
628  2-tuple of unpacked value, new buffer offset.
629  """
630  try:
631  return (struct.unpack_from(_EndianCode[endian]+'b', buf, offset)[0],
632  offset+1)
633  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
634  _UnpackException('s8', offset, endian, inst)
635 ##
636 
637 #--
638 def UnpackU16(buf, offset=0, endian='big'):
639  """ Unpack a 16-bit unsigned integer into 2 bytes.
640 
641  Parameters:
642  buf - Input packed buffer.
643  offset - Offset in buffer.
644  endian - Byte order.
645 
646  Return:
647  2-tuple of unpacked value, new buffer offset.
648  """
649  try:
650  return (struct.unpack_from(_EndianCode[endian]+'H', buf, offset)[0],
651  offset+2)
652  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
653  _UnpackException('u16', offset, endian, inst)
654 ##
655 
656 #--
657 def UnpackS16(buf, offset=0, endian='big'):
658  """ Unpack a 16-bit signed integer into 2 bytes.
659 
660  Parameters:
661  buf - Input packed buffer.
662  offset - Offset in buffer.
663  endian - Byte order.
664 
665  Return:
666  2-tuple of unpacked value, new buffer offset.
667  """
668  try:
669  return (struct.unpack_from(_EndianCode[endian]+'h', buf, offset)[0],
670  offset+2)
671  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
672  _UnpackException('s16', offset, endian, inst)
673 ##
674 
675 #--
676 def UnpackU32(buf, offset=0, endian='big'):
677  """ Unpack a 32-bit unsigned integer into 4 bytes.
678 
679  Parameters:
680  buf - Input packed buffer.
681  offset - Offset in buffer.
682  endian - Byte order.
683 
684  Return:
685  2-tuple of unpacked value, new buffer offset.
686  """
687  try:
688  return (struct.unpack_from(_EndianCode[endian]+'I', buf, offset)[0],
689  offset+4)
690  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
691  _UnpackException('u32', offset, endian, inst)
692 ##
693 
694 #--
695 def UnpackS32(buf, offset=0, endian='big'):
696  """ Unpack a 32-bit signed integer into 4 bytes.
697 
698  Parameters:
699  buf - Input packed buffer.
700  offset - Offset in buffer.
701  endian - Byte order.
702 
703  Return:
704  2-tuple of unpacked value, new buffer offset.
705  """
706  try:
707  return (struct.unpack_from(_EndianCode[endian]+'i', buf, offset)[0],
708  offset+4)
709  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
710  _UnpackException('s32', offset, endian, inst)
711 ##
712 
713 #--
714 def UnpackU64(buf, offset=0, endian='big'):
715  """ Unpack a 64-bit unsigned integer into 8 bytes.
716 
717  If native architectures only support 4 byte long long's, then the 4 MSBs
718  are padded with zero's.
719 
720  Parameters:
721  buf - Input packed buffer.
722  offset - Offset in buffer.
723  endian - Byte order.
724 
725  Return:
726  2-tuple of unpacked value, new buffer offset.
727  """
728  if struct.calcsize('Q') == 8:
729  try:
730  return (struct.unpack_from(_EndianCode[endian]+'Q', buf, offset)[0],
731  offset+8)
732  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
733  _UnpackException('u64', offset, endian, inst)
734  elif endian == 'big' or \
735  (endian == 'native' and GetNativeByteOrder() == 'big'):
736  msb, offset = UnpackU32(buf, offset=offset, endian='big')
737  lsb, offset = UnpackU32(buf, offset=offset, endian='big')
738  else: # little
739  lsb, offset = UnpackU32(buf, offset=offset, endian='little')
740  msb, offset = UnpackU32(buf, offset=offset, endian='little')
741  if msb != 0:
742  warnings.warn("unpack u64=0x%08x%08x: non-zero 4 MSB's truncated" % \
743  (msb, lsb), RuntimeWarning)
744  return (lsb, offset)
745 ##
746 
747 #--
748 def UnpackS64(buf, offset=0, endian='big'):
749  """ Unpack a 64-bit signed integer into 8 bytes.
750 
751  If native architectures only support 4 byte long long's, then the 4 MSBs
752  are padded with zero's.
753 
754  Parameters:
755  buf - Input packed buffer.
756  offset - Offset in buffer.
757  endian - Byte order.
758 
759  Return:
760  2-tuple of unpacked value, new buffer offset.
761  """
762  if struct.calcsize('q') == 8:
763  try:
764  return (struct.unpack_from(_EndianCode[endian]+'q', buf, offset)[0],
765  offset+8)
766  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
767  _UnpackException('s64', offset, endian, inst)
768  elif endian == 'big' or \
769  (endian == 'native' and GetNativeByteOrder() == 'big'):
770  msb, offset = UnpackU32(buf, offset=offset, endian='big')
771  lsb, offset = UnpackU32(buf, offset=offset, endian='big')
772  else: # little
773  lsb, offset = UnpackU32(buf, offset=offset, endian='little')
774  msb, offset = UnpackU32(buf, offset=offset, endian='little')
775  if (msb != 0) and (msb != 0xffffffff): # test zero or sign extended msb
776  warnings.warn("unpack s64=0x%08x%08x: non-zero 4 MSB's truncated" % \
777  (msb, lsb), RuntimeWarning)
778  return (lsb, offset)
779 ##
780 
781 #--
782 def UnpackF32(buf, offset=0, endian='big'):
783  """ Unpack a 32-bit floating-point number into 4 bytes.
784 
785  Is this guaranteed to be in IEEE 745 32-bit format?
786 
787  Parameters:
788  buf - Input packed buffer.
789  offset - Offset in buffer.
790  endian - Byte order.
791 
792  Return:
793  2-tuple of unpacked value, new buffer offset.
794  """
795  try:
796  return (struct.unpack_from(_EndianCode[endian]+'f', buf, offset)[0],
797  offset+4)
798  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
799  _UnpackException('f32', offset, endian, inst)
800 ##
801 
802 #--
803 def UnpackF64(buf, offset=0, endian='big'):
804  """ Unpack a 64-bit floating-point number into 8 bytes.
805 
806  Is this guaranteed to be in IEEE 745 64-bit format?
807  Will this pack into 8 bytes on 32-bit architectures?
808 
809  Parameters:
810  buf - Input packed buffer.
811  offset - Offset in buffer.
812  endian - Byte order.
813 
814  Return:
815  2-tuple of unpacked value, new buffer offset.
816  """
817  try:
818  return (struct.unpack_from(_EndianCode[endian]+'d', buf, offset)[0],
819  offset+8)
820  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
821  _UnpackException('f64', offset, endian, inst)
822 ##
823 
824 #--
825 def UnpackP32(buf, offset=0, endian='big'):
826  """ Unpack a 32-bit floating-point number into 4 bytes.
827 
828  Note:
829  Pointers are really foreign to python. However, a python application
830  may have a linked c library that requires it. And NetMsgs XML and
831  run-time C library supports it.
832 
833  Note:
834  Pointers are always unpacked in native byte order.
835 
836  Parameters:
837  buf - Input packed buffer.
838  offset - Offset in buffer.
839  endian - Byte order.
840 
841  Return:
842  2-tuple of unpacked value, new buffer offset.
843  """
844  try:
845  return (struct.unpack_from(_EndianCode['native']+'I', buf, offset)[0],
846  offset+4)
847  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
848  _UnpackException('p32', offset, endian, inst)
849 ##
850 
851 #--
852 def UnpackP64(buf, offset=0, endian='big'):
853  """ Unpack a 64-bit floating-point number into 8 bytes.
854 
855  Note:
856  Pointers are really foreign to python. However, a python application
857  may have a linked c library that requires it. And NetMsgs supports it.
858 
859  Note:
860  Pointers are always unpacked in native byte order.
861 
862  Parameters:
863  buf - Input packed buffer.
864  offset - Offset in buffer.
865  endian - Byte order.
866 
867  Return:
868  2-tuple of unpacked value, new buffer offset.
869  """
870  if struct.calcsize('L') == 8:
871  try:
872  return (struct.unpack_from(_EndianCode[endian]+'L', buf, offset)[0],
873  offset+8)
874  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
875  _UnpackException('u8', offset, endian, inst)
876  elif (endian == 'native') and (GetNativeByteOrder() == 'big'):
877  msb, offset = UnpackU32(buf, offset=offset, endian='big')
878  lsb, offset = UnpackU32(buf, offset=offset, endian='big')
879  else: # little
880  lsb, offset = UnpackU32(buf, offset=offset, endian='little')
881  msb, offset = UnpackU32(buf, offset=offset, endian='little')
882  if msb != 0:
883  warnings.warn("unpack p64=0x%08x%08x: non-zero 4 MSB's truncated" % \
884  (msb, lsb), RuntimeWarning)
885  return (lsb, offset)
886 ##
887 
888 #--
889 def UnpackString(buf, count, offset=0):
890  """ Unpack a string.
891 
892  The endianess is ignore.
893  The terminating Null is not packed.
894 
895  Parameters:
896  buf - Input packed buffer.
897  count - Number of bytes to unpack.
898  offset - Offset in buffer.
899 
900  Return:
901  2-tuple of unpacked value, new buffer offset.
902  """
903  try:
904  return (struct.unpack_from("%us" % (count), buf, offset)[0], offset+count)
905  except (KeyError, TypeError, DeprecationWarning, struct.error) as inst:
906  _UnpackException('string', offset, 'big', inst)
907 ##
def UnpackU8(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:600
def UnpackChar(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:581
def PackU64(val, endian='big')
Definition: NetMsgsLib.py:335
def UnpackBool(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:562
def PackF64(val, endian='big')
Definition: NetMsgsLib.py:409
def UnpackU32(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:676
def PackU16(val, endian='big')
Definition: NetMsgsLib.py:267
def UnpackF32(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:782
def GetNativeByteOrder()
Definition: NetMsgsLib.py:140
def UnpackString(buf, count, offset=0)
Definition: NetMsgsLib.py:889
def PackBool(val, endian='big')
Definition: NetMsgsLib.py:195
def UnpackS8(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:619
def UnpackF64(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:803
def PackU32(val, endian='big')
Definition: NetMsgsLib.py:301
def UnpackP32(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:825
def UnpackU16(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:638
def UnpackS64(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:748
def PackS32(val, endian='big')
Definition: NetMsgsLib.py:318
def UnpackU64(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:714
def PackP64(val, endian='big')
Definition: NetMsgsLib.py:464
def PackU8(val, endian='big')
Definition: NetMsgsLib.py:229
def PackString(val, count=None)
Definition: NetMsgsLib.py:493
def PackS8(val, endian='big')
Definition: NetMsgsLib.py:248
def UnpackS16(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:657
def PackChar(val, endian='big')
Definition: NetMsgsLib.py:212
def PackF32(val, endian='big')
Definition: NetMsgsLib.py:390
def UnpackS32(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:695
def PackS16(val, endian='big')
Definition: NetMsgsLib.py:284
def PackP32(val, endian='big')
Definition: NetMsgsLib.py:429
def UnpackP64(buf, offset=0, endian='big')
Definition: NetMsgsLib.py:852
def PackS64(val, endian='big')
Definition: NetMsgsLib.py:361