netmsgs  1.2.2
RoadNarrows Robotics Network Messaging Package
nmLibPackFlat.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: botsense
4 //
5 // Library: libBotSense
6 //
7 // File: bsLibPackFlat.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2010-02-16 08:12:53 -0700 (Tue, 16 Feb 2010) $
12  * $Rev: 248 $
13  *
14  * \brief Flat message packing/unpacking definitions.
15  *
16  * \author Robin Knight (robin.knight@roadnarrows.com)
17  *
18  * \copyright
19  * \h_copy 2009-2017. RoadNarrows LLC.\n
20  * http://www.roadnarrows.com\n
21  * All Rights Reserved
22  */
23 // Permission is hereby granted, without written agreement and without
24 // license or royalty fees, to use, copy, modify, and distribute this
25 // software and its documentation for any purpose, provided that
26 // (1) The above copyright notice and the following two paragraphs
27 // appear in all copies of the source code and (2) redistributions
28 // including binaries reproduces these notices in the supporting
29 // documentation. Substantial modifications to this software may be
30 // copyrighted by their authors and need not follow the licensing terms
31 // described here, provided that the new terms are clearly indicated in
32 // all files where they apply.
33 //
34 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
35 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
36 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
37 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
38 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
39 // THE POSSIBILITY OF SUCH DAMAGE.
40 //
41 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
42 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
43 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
44 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
45 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
46 //
47 ////////////////////////////////////////////////////////////////////////////////
48 
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <libgen.h>
52 #include <string.h>
53 
54 #include "rnr/rnrconfig.h"
55 #include "rnr/log.h"
56 
57 #include "rnr/netmsgs.h"
58 
59 #include "nmLibInternal.h"
60 
61 
62 // ...........................................................................
63 // Private Packing Interface
64 // ...........................................................................
65 
66 //
67 // Forward Declarations
68 //
71 static int nmPackFlatStream(const NMMsgDef_T *pMsgDef, void *pStruct,
72  byte_t buf[], size_t bufSize, NMEndian_T eEndian,
73  NMCtl_T *pCtl);
74 static int nmUnpackFlatStream(const NMMsgDef_T *pMsgDef, byte_t buf[],
75  size_t uMsgLen, void *pStruct,
76  NMEndian_T eEndian, NMCtl_T *pCtl);
77 
78 
79 // ...........................................................................
80 // Private Packing Interface
81 // ...........................................................................
82 
83 /*!
84  * \brief Pack pad bytes into the message buffer.
85  *
86  * \copydoc doc_params_pack_fdef
87  * \copydoc doc_return_pack_std
88  */
89 static int nmPackFlatPad(const NMFieldDef_T *pFieldDef,
90  void *pVal,
91  byte_t buf[],
92  size_t bufSize,
93  NMEndian_T eEndian,
94  NMCtl_T *pCtl)
95 {
96  size_t uCount = pFieldDef->m_this.m_pad.m_uCount;
97 
98  // pack pad bytes
99  if( uCount <= bufSize )
100  {
101  memset(buf, NMFVAL_PAD, uCount);
102  NMLIB_TRACE_FIELD(NULL, buf, uCount, pCtl, "pad(%u)", pFieldDef->m_eFId);
103  return (int)uCount;
104  }
105 
106  // no more space in buffer for pad bytes
107  else
108  {
110  "buf_size=%zu < pad_count=%zu", bufSize, uCount);
111  }
112 }
113 
114 /*!
115  * \brief Pack a boolean into an 8-bit Flat field into the message buffer.
116  *
117  * \copydoc doc_params_pack_fdef
118  * \copydoc doc_return_pack_std
119  */
120 static int nmPackFlatBool(const NMFieldDef_T *pFieldDef,
121  void *pVal,
122  byte_t buf[],
123  size_t bufSize,
124  NMEndian_T eEndian,
125  NMCtl_T *pCtl)
126 {
127  bool_t val; // constrained field value
128  int n; // byte count/error code
129 
130  val = *((bool_t *)pVal);
131 
132  // pack field value
133  n = nmPackBool(val, buf, bufSize, eEndian);
134 
135  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%s", (val? "true": "false"));
136 
137  return n;
138 }
139 
140 /*!
141  * \brief Pack an unsigned 8-bit Flat field into the message buffer.
142  *
143  * \copydoc doc_params_pack_fdef
144  * \copydoc doc_return_pack_std
145  */
146 static int nmPackFlatU8(const NMFieldDef_T *pFieldDef,
147  void *pVal,
148  byte_t buf[],
149  size_t bufSize,
150  NMEndian_T eEndian,
151  NMCtl_T *pCtl)
152 {
153  byte_t val; // constrained field value
154  int n; // byte count/error code
155 
156  // try to set field value
157  if( (n = nmSetU8(pFieldDef, pVal, &val)) != NM_OK )
158  {
159  return n;
160  }
161 
162  // pack field value
163  n = nmPackU8(val, buf, bufSize, eEndian);
164 
165  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhu", val);
166 
167  return n;
168 }
169 
170 /*!
171  * \brief Pack a signed 8-bit Flat field into the message buffer.
172  *
173  * \copydoc doc_params_pack_fdef
174  * \copydoc doc_return_pack_std
175  */
176 static int nmPackFlatS8(const NMFieldDef_T *pFieldDef,
177  void *pVal,
178  byte_t buf[],
179  size_t bufSize,
180  NMEndian_T eEndian,
181  NMCtl_T *pCtl)
182 {
183  signed char val; // constrained field value
184  int n; // byte count/error code
185 
186  // try to set field value
187  if( (n = nmSetS8(pFieldDef, pVal, &val)) != NM_OK )
188  {
189  return n;
190  }
191 
192  // pack field value
193  n = nmPackS8(val, buf, bufSize, eEndian);
194 
195  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhd", val);
196 
197  return n;
198 }
199 
200 /*!
201  * \brief Pack an unsigned 16-bit Flat field into the message buffer.
202  *
203  * \copydoc doc_params_pack_fdef
204  * \copydoc doc_return_pack_std
205  */
206 static int nmPackFlatU16(const NMFieldDef_T *pFieldDef,
207  void *pVal,
208  byte_t buf[],
209  size_t bufSize,
210  NMEndian_T eEndian,
211  NMCtl_T *pCtl)
212 {
213  ushort_t val; // constrained field value
214  int n; // byte count/error code
215 
216  // try to set field value
217  if( (n = nmSetU16(pFieldDef, pVal, &val)) != NM_OK )
218  {
219  return n;
220  }
221 
222  // pack field value
223  n = nmPackU16(val, buf, bufSize, eEndian);
224 
225  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hu", val);
226 
227  return n;
228 }
229 
230 /*!
231  * \brief Pack a signed 16-bit Flat field into the message buffer.
232  *
233  * \copydoc doc_params_pack_fdef
234  * \copydoc doc_return_pack_std
235  */
236 static int nmPackFlatS16(const NMFieldDef_T *pFieldDef,
237  void *pVal,
238  byte_t buf[],
239  size_t bufSize,
240  NMEndian_T eEndian,
241  NMCtl_T *pCtl)
242 {
243  short val; // constrained field value
244  int n; // byte count/error code
245 
246  // set field value
247  if( (n = nmSetS16(pFieldDef, pVal, &val)) != NM_OK )
248  {
249  return n;
250  }
251 
252  // pack field value
253  n = nmPackS16(val, buf, bufSize, eEndian);
254 
255  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hd", val);
256 
257  return n;
258 }
259 
260 /*!
261  * \brief Pack an unsigned 32-bit Flat field into the message buffer.
262  *
263  * \copydoc doc_params_pack_fdef
264  * \copydoc doc_return_pack_std
265  */
266 static int nmPackFlatU32(const NMFieldDef_T *pFieldDef,
267  void *pVal,
268  byte_t buf[],
269  size_t bufSize,
270  NMEndian_T eEndian,
271  NMCtl_T *pCtl)
272 {
273  uint_t val; // constrained field value
274  int n; // byte count/error code
275 
276  // set field value
277  if( (n = nmSetU32(pFieldDef, pVal, &val)) != NM_OK )
278  {
279  return n;
280  }
281 
282  // pack field value
283  n = nmPackU32(val, buf, bufSize, eEndian);
284 
285  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%u", val);
286 
287  return n;
288 }
289 
290 /*!
291  * \brief Pack a signed 32-bit Flat field into the message buffer.
292  *
293  * \copydoc doc_params_pack_fdef
294  * \copydoc doc_return_pack_std
295  */
296 static int nmPackFlatS32(const NMFieldDef_T *pFieldDef,
297  void *pVal,
298  byte_t buf[],
299  size_t bufSize,
300  NMEndian_T eEndian,
301  NMCtl_T *pCtl)
302 {
303  int val; // constrained field value
304  int n; // byte count/error code
305 
306  // set field value
307  if( (n = nmSetS32(pFieldDef, pVal, &val)) != NM_OK )
308  {
309  return n;
310  }
311 
312  // pack field value
313  n = nmPackS32(val, buf, bufSize, eEndian);
314 
315  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%d", val);
316 
317  return n;
318 }
319 
320 /*!
321  * \brief Pack an unsigned 64-bit Flat field into the message buffer.
322  *
323  * \copydoc doc_params_pack_fdef
324  * \copydoc doc_return_pack_std
325  */
326 static int nmPackFlatU64(const NMFieldDef_T *pFieldDef,
327  void *pVal,
328  byte_t buf[],
329  size_t bufSize,
330  NMEndian_T eEndian,
331  NMCtl_T *pCtl)
332 {
333  ulonglong_t val; // constrained field value
334  int n; // byte count/error code
335 
336  // set field value
337  if( (n = nmSetU64(pFieldDef, pVal, &val)) != NM_OK )
338  {
339  return n;
340  }
341 
342  // pack field value
343  n = nmPackU64(val, buf, bufSize, eEndian);
344 
345  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%llu", val);
346 
347  return n;
348 }
349 
350 /*!
351  * \brief Pack a signed 64-bit Flat field into the message buffer.
352  *
353  * \copydoc doc_params_pack_fdef
354  * \copydoc doc_return_pack_std
355  */
356 static int nmPackFlatS64(const NMFieldDef_T *pFieldDef,
357  void *pVal,
358  byte_t buf[],
359  size_t bufSize,
360  NMEndian_T eEndian,
361  NMCtl_T *pCtl)
362 {
363  long long val; // constrained field value
364  int n; // byte count/error code
365 
366  // set field value
367  if( (n = nmSetS64(pFieldDef, pVal, &val)) != NM_OK )
368  {
369  return n;
370  }
371 
372  // pack field value
373  n = nmPackS64(val, buf, bufSize, eEndian);
374 
375  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%lld", val);
376 
377  return n;
378 }
379 
380 /*!
381  * \brief Pack a 32-bit floating-point number Flat field into the message
382  * buffer.
383  *
384  * \copydoc doc_params_pack_fdef
385  * \copydoc doc_return_pack_std
386  */
387 static int nmPackFlatF32(const NMFieldDef_T *pFieldDef,
388  void *pVal,
389  byte_t buf[],
390  size_t bufSize,
391  NMEndian_T eEndian,
392  NMCtl_T *pCtl)
393 {
394  float val; // constrained field value
395  int n; // byte count/error code
396 
397  // set field value
398  if( (n = nmSetF32(pFieldDef, pVal, &val)) != NM_OK )
399  {
400  return n;
401  }
402 
403  // pack field value
404  n = nmPackF32(val, buf, bufSize, eEndian);
405 
406  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%f", val);
407 
408  return n;
409 }
410 
411 /*!
412  * \brief Pack a 64-bit floating-point number Flat field into the message
413  * buffer.
414  *
415  * \copydoc doc_params_pack_fdef
416  * \copydoc doc_return_pack_std
417  */
418 static int nmPackFlatF64(const NMFieldDef_T *pFieldDef,
419  void *pVal,
420  byte_t buf[],
421  size_t bufSize,
422  NMEndian_T eEndian,
423  NMCtl_T *pCtl)
424 {
425  double val; // constrained field value
426  int n; // byte count/error code
427 
428  // set field value
429  if( (n = nmSetF64(pFieldDef, pVal, &val)) != NM_OK )
430  {
431  return n;
432  }
433 
434  // pack field value
435  n = nmPackF64(val, buf, bufSize, eEndian);
436 
437  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%e", val);
438 
439  return n;
440 }
441 
442 /*!
443  * \brief Pack a 32-bit pointer Flat field into the message buffer.
444  *
445  * \copydoc doc_params_pack_fdef
446  * \copydoc doc_return_pack_std
447  */
448 static int nmPackFlatP32(const NMFieldDef_T *pFieldDef,
449  void *pVal,
450  byte_t buf[],
451  size_t bufSize,
452  NMEndian_T eEndian,
453  NMCtl_T *pCtl)
454 {
455  int n; // byte count/error code
456 
457  // pack field value
458  n = nmPackP32(pVal, buf, bufSize, eEndian);
459 
460  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
461 
462  return n;
463 }
464 
465 /*!
466  * \brief Pack a 64-bit pointer Flat field into the message buffer.
467  *
468  * \copydoc doc_params_pack_fdef
469  * \copydoc doc_return_pack_std
470  */
471 static int nmPackFlatP64(const NMFieldDef_T *pFieldDef,
472  void *pVal,
473  byte_t buf[],
474  size_t bufSize,
475  NMEndian_T eEndian,
476  NMCtl_T *pCtl)
477 {
478  int n; // byte count/error code
479 
480  // pack field value
481  n = nmPackP64(pVal, buf, bufSize, eEndian);
482 
483  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
484 
485  return n;
486 }
487 
488 /*!
489  * \brief Pack null-terminated, fixed length string Flat field into the
490  * message buffer.
491  *
492  * \note The null character is not packed.
493  *
494  * \copydoc doc_params_pack_fdef
495  * \copydoc doc_return_pack_std
496  */
497 static int nmPackFlatString(const NMFieldDef_T *pFieldDef,
498  void *pVal,
499  byte_t buf[],
500  size_t bufSize,
501  NMEndian_T eEndian,
502  NMCtl_T *pCtl)
503 {
504  const char *sVal; // string field value pointer
505  const char *sConst; // string constant value, if any
506  size_t uMaxCount; // string maximum packed size
507  size_t uCount; // string length
508 
509  sVal = (const char *)pVal; // override void *
510  sConst = pFieldDef->m_this.m_string.m_sConst;
511  uMaxCount = pFieldDef->m_this.m_string.m_uMaxCount;
512 
513  if( sConst != NULL )
514  {
515  sVal = sConst;
516  }
517 
518  uCount = strlen(sVal); // string length w/o null
519 
520  // string length exceeds maximum
521  if( uCount > uMaxCount )
522  {
524  "char_count=%zu > max_count=%zu.", uCount, uMaxCount);
525  }
526 
527  // no more space in buffer for string
528  else if( uMaxCount > bufSize )
529  {
531  "buf_size=%zu < str_max_len=%zu.", bufSize, uMaxCount);
532  }
533 
534  // copy string field value
535  memcpy(buf, sVal, uCount);
536 
537  // pad with zeros
538  if( uCount < uMaxCount )
539  {
540  memset(&buf[uCount], 0, uMaxCount-uCount);
541  }
542 
543  NMLIB_TRACE_FIELD(pFieldDef, buf, uMaxCount, pCtl, "'%s'", sVal);
544 
545  return (int)uMaxCount;
546 }
547 
548 /*!
549  * \brief Pack a structure Flat field into the message buffer.
550  *
551  * \copydoc doc_params_pack_fdef
552  * \copydoc doc_return_pack_std
553  */
554 static int nmPackFlatStruct(const NMFieldDef_T *pFieldDef,
555  void *pVal,
556  byte_t buf[],
557  size_t bufSize,
558  NMEndian_T eEndian,
559  NMCtl_T *pCtl)
560 {
561  const NMMsgDef_T *pStructDef; // pointer to structure message definition
562  int n; // byte count/error code
563 
564  pStructDef = pFieldDef->m_this.m_struct;
565 
566  NMLIB_TRACE_FIELD(pFieldDef, buf, 0, pCtl, "structdef %s, member_count=%zu",
567  pStructDef->m_sMsgName, pStructDef->m_uCount);
568 
569  pCtl->m_uDepth++;
570 
571  // copy struct field value
572  n = nmPackFlatStream(pStructDef, pVal, buf, bufSize, eEndian, pCtl);
573 
574  pCtl->m_uDepth--;
575 
576  return n;
577 }
578 
579 /*!
580  * \brief Pack variable length vector Flat field into the message buffer.
581  *
582  * A vector is a one-dimension array of the given type.
583  *
584  * \copydoc doc_params_pack_fdef
585  * \copydoc doc_return_pack_std
586  */
587 static int nmPackFlatVector(const NMFieldDef_T *pFieldDef,
588  void *pVal,
589  byte_t buf[],
590  size_t bufSize,
591  NMEndian_T eEndian,
592  NMCtl_T *pCtl)
593 {
594  size_t uMaxCount; // vector maximum number of elements
595  size_t uElemSize; // vector element size
596  const NMFieldDef_T *pElemDef; // vector element field definition
597  NMVec_T *pVec; // pointer to vector field template
598  size_t uCount; // number of vector items to pack
599  byte_t *pItem; // working vector item pointer
600  NMPackFunc_T fnPack; // vector item packing function
601  int n; // byte count/error code
602  int k; // subbyte count/error code
603  size_t i; // working vector index
604 
605  uMaxCount = pFieldDef->m_this.m_vector.m_uMaxCount;
606  uElemSize = pFieldDef->m_this.m_vector.m_uElemSize;
607  pElemDef = pFieldDef->m_this.m_vector.m_pThisElem;
608  pVec = (NMVec_T *)pVal; // generalized vector overlay
609  uCount = pVec->m_uCount; // number of vector items
610  pItem = (byte_t *)(pVec) + memberoffset(NMVec_T, u.m_buf);
611  fnPack = nmLookupFlatPacker(pElemDef->m_eFType);
612 
613  if( fnPack == NULL )
614  {
616  "vector_elem_ftype='%c'(0x%02x)",
617  NMLIB_ASCII_FTYPE(pElemDef->m_eFType), pElemDef->m_eFType);
618  }
619 
620  // exceeds maximum
621  else if( uCount > uMaxCount )
622  {
624  "vector_count=%zu > vector_max_count=%zu.", uCount, uMaxCount);
625  }
626 
627  NMLIB_TRACE_FIELD(pFieldDef, buf, 0, pCtl, "%c:vector[%zu], max_count=%zu",
628  pElemDef->m_eFType, uCount, uMaxCount);
629 
630  // no header for simple vector element types
631  if( NMFTYPE_IS_SIMPLE(pElemDef->m_eFType) )
632  {
633  pCtl->m_bNoHdr = true;
634  }
635 
636  pCtl->m_uDepth++;
637 
638  // copy vector field value
639  for(i=0, n=0; i<uCount; ++i)
640  {
641  k = fnPack(pElemDef, pItem, &buf[n], bufSize-(size_t)n, eEndian, pCtl);
642 
643  if( k < 0 )
644  {
645  return k;
646  }
647 
648  n += k;
649 
650  pItem += uElemSize;
651  }
652 
653  // pad out fixed size vector with zero's.
654  if( uCount < uMaxCount )
655  {
656  i = (uMaxCount - uCount) * uElemSize;
657 
658  if( i > bufSize-(size_t)n)
659  {
661  "buf_size=%zu < vector_pad_size=%zu", bufSize-(size_t)n, i);
662  }
663 
664  else
665  {
666  memset(&buf[n], 0, i);
667  n += (int)i;
668  }
669  }
670 
671  pCtl->m_uDepth--;
672  pCtl->m_bNoHdr = false;
673 
674  return n;
675 }
676 
677 /*!
678  * \brief Pack a Flat message.
679  *
680  * \param pMsgDef Pointer to message definition.
681  * \param [in] pStruct Pointer to the associated, populated message
682  * structure.
683  * \param [out] buf Output message buffer.
684  * \param bufSize Size of output buffer.
685  * \param eEndian Packing order. See \ref NMEndian_T.
686  * \param pCtl Pointer to Internal control.
687  *
688  * \copydoc doc_return_pack_std
689  */
690 static int nmPackFlatStream(const NMMsgDef_T *pMsgDef,
691  void *pStruct,
692  byte_t buf[],
693  size_t bufSize,
694  NMEndian_T eEndian,
695  NMCtl_T *pCtl)
696 {
697  size_t uFieldNum; // field instance number (not id)
698  const NMFieldDef_T *pFieldDef; // working field definition pointer
699  NMPackFunc_T fnPack; // field packing function
700  void *pVal; // pointer to field value
701  int n = 0; // byte count/error code
702  int k; // subbyte count/error code
703 
704  //
705  // Pack message fields
706  //
707  for(uFieldNum=0, pFieldDef=pMsgDef->m_pFields;
708  uFieldNum < pMsgDef->m_uCount;
709  ++uFieldNum, ++pFieldDef)
710  {
711  if( n < bufSize )
712  {
713  if( pFieldDef->m_eFType == NMFTypePad )
714  {
715  pVal = NULL;
716  }
717 
718  else
719  {
720  pVal = pStruct + pFieldDef->m_uOffset;
721  }
722 
723  fnPack = nmLookupFlatPacker(pFieldDef->m_eFType);
724 
725  if( fnPack == NULL )
726  {
728  "ftype='%c'(0x%02x).",
729  NMLIB_ASCII_FTYPE(pFieldDef->m_eFType), pFieldDef->m_eFType);
730  }
731 
732  k = fnPack(pFieldDef, pVal, &buf[n], bufSize-(size_t)n, eEndian, pCtl);
733 
734  if( k < 0 )
735  {
736  return k;
737  }
738  }
739 
740  else
741  {
743  "buf_size=%zu, msgid=%u", bufSize, pMsgDef->m_eMsgId);
744  }
745 
746  n += k;
747  }
748 
749  return n;
750 }
751 
752 
753 // ...........................................................................
754 // Private Unpacking Interface
755 // ...........................................................................
756 
757 /*!
758  * \brief Unpack pad byte from the message buffer.
759  *
760  * \copydoc doc_params_unpack_fdef
761  * \copydoc doc_return_unpack_std
762  */
763 static int nmUnpackFlatPad(const NMFieldDef_T *pFieldDef,
764  byte_t buf[],
765  size_t bufSize,
766  void *pVal,
767  NMEndian_T eEndian,
768  NMCtl_T *pCtl)
769 {
770  size_t uCount = pFieldDef->m_this.m_pad.m_uCount;
771 
772  // unpack pad bytes
773  if( uCount <= bufSize )
774  {
775  NMLIB_TRACE_FIELD(NULL, buf, uCount, pCtl, "pad(%u)", pFieldDef->m_eFId);
776  return (int)uCount;
777  }
778 
779  // no more space in buffer for pad bytes
780  else
781  {
783  "buf_size=%zu < pad_count=%zu", bufSize, uCount);
784  }
785 }
786 
787 /*!
788  * \brief Unpack an unsigned 8-bit boolean Flat field from the message buffer.
789  *
790  * \copydoc doc_params_unpack_fdef
791  * \copydoc doc_return_unpack_std
792  */
793 static int nmUnpackFlatBool(const NMFieldDef_T *pFieldDef,
794  byte_t buf[],
795  size_t bufSize,
796  void *pVal,
797  NMEndian_T eEndian,
798  NMCtl_T *pCtl)
799 {
800  int n; // byte count/error code
801 
802  // unpack value
803  n = nmUnpackBool(buf, bufSize, pVal, eEndian);
804 
805  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%s",
806  (*((bool_t *)pVal)? "true": "false"));
807 
808  return n;
809 }
810 
811 /*!
812  * \brief Unpack an unsigned 8-bit Flat field from the message buffer.
813  *
814  * \copydoc doc_params_unpack_fdef
815  * \copydoc doc_return_unpack_std
816  */
817 static int nmUnpackFlatU8(const NMFieldDef_T *pFieldDef,
818  byte_t buf[],
819  size_t bufSize,
820  void *pVal,
821  NMEndian_T eEndian,
822  NMCtl_T *pCtl)
823 {
824  int n; // byte count/error code
825 
826  // unpack value
827  n = nmUnpackU8(buf, bufSize, pVal, eEndian);
828 
829  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhu", *((byte_t *)pVal));
830 
831  return n;
832 }
833 
834 /*!
835  * \brief Unpack a signed 8-bit Flat field from the message buffer.
836  *
837  * \copydoc doc_params_unpack_fdef
838  * \copydoc doc_return_unpack_std
839  */
840 static int nmUnpackFlatS8(const NMFieldDef_T *pFieldDef,
841  byte_t buf[],
842  size_t bufSize,
843  void *pVal,
844  NMEndian_T eEndian,
845  NMCtl_T *pCtl)
846 {
847  int n; // byte count/error code
848 
849  // unpack value
850  n = nmUnpackS8(buf, bufSize, pVal, eEndian);
851 
852  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhd", *((signed char *)pVal));
853 
854  return n;
855 }
856 
857 /*!
858  * \brief Unpack an unsigned 16-bit Flat field from the message buffer.
859  *
860  * \copydoc doc_params_unpack_fdef
861  * \copydoc doc_return_unpack_std
862  */
863 static int nmUnpackFlatU16(const NMFieldDef_T *pFieldDef,
864  byte_t buf[],
865  size_t bufSize,
866  void *pVal,
867  NMEndian_T eEndian,
868  NMCtl_T *pCtl)
869 {
870  int n; // byte count/error code
871 
872  // unpack value
873  n = nmUnpackU16(buf, bufSize, pVal, eEndian);
874 
875  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hu", *((ushort_t *)pVal));
876 
877  return n;
878 }
879 
880 /*!
881  * \brief Unpack a signed 16-bit Flat field from the message buffer.
882  *
883  * \copydoc doc_params_unpack_fdef
884  * \copydoc doc_return_unpack_std
885  */
886 static int nmUnpackFlatS16(const NMFieldDef_T *pFieldDef,
887  byte_t buf[],
888  size_t bufSize,
889  void *pVal,
890  NMEndian_T eEndian,
891  NMCtl_T *pCtl)
892 {
893  int n; // byte count/error code
894 
895  // unpack value
896  n = nmUnpackS16(buf, bufSize, pVal, eEndian);
897 
898  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hd", *((short *)pVal));
899 
900  return n;
901 }
902 
903 /*!
904  * \brief Unpack an unsigned 32-bit Flat field from the message buffer.
905  *
906  * \copydoc doc_params_unpack_fdef
907  * \copydoc doc_return_unpack_std
908  */
909 static int nmUnpackFlatU32(const NMFieldDef_T *pFieldDef,
910  byte_t buf[],
911  size_t bufSize,
912  void *pVal,
913  NMEndian_T eEndian,
914  NMCtl_T *pCtl)
915 {
916  int n; // byte count/error code
917 
918  // unpack value
919  n = nmUnpackU32(buf, bufSize, pVal, eEndian);
920 
921  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%u", *((uint_t *)pVal));
922 
923  return n;
924 }
925 
926 /*!
927  * \brief Unpack a signed 32-bit Flat field from the message buffer.
928  *
929  * \copydoc doc_params_unpack_fdef
930  * \copydoc doc_return_unpack_std
931  */
932 static int nmUnpackFlatS32(const NMFieldDef_T *pFieldDef,
933  byte_t buf[],
934  size_t bufSize,
935  void *pVal,
936  NMEndian_T eEndian,
937  NMCtl_T *pCtl)
938 {
939  int n; // byte count/error code
940 
941  // unpack value
942  n = nmUnpackS32(buf, bufSize, pVal, eEndian);
943 
944  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%d", *((int *)pVal));
945 
946  return n;
947 }
948 
949 /*!
950  * \brief Unpack an unsigned 64-bit Flat field from the message buffer.
951  *
952  * \copydoc doc_params_unpack_fdef
953  * \copydoc doc_return_unpack_std
954  */
955 static int nmUnpackFlatU64(const NMFieldDef_T *pFieldDef,
956  byte_t buf[],
957  size_t bufSize,
958  void *pVal,
959  NMEndian_T eEndian,
960  NMCtl_T *pCtl)
961 {
962  int n; // byte count/error code
963 
964  // unpack value
965  n = nmUnpackU64(buf, bufSize, pVal, eEndian);
966 
967  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%llu", *((ulonglong_t *)pVal));
968 
969  return n;
970 }
971 
972 /*!
973  * \brief Unpack a signed 64-bit Flat field from the message buffer.
974  *
975  * \copydoc doc_params_unpack_fdef
976  * \copydoc doc_return_unpack_std
977  */
978 static int nmUnpackFlatS64(const NMFieldDef_T *pFieldDef,
979  byte_t buf[],
980  size_t bufSize,
981  void *pVal,
982  NMEndian_T eEndian,
983  NMCtl_T *pCtl)
984 {
985  int n; // byte count/error code
986 
987  // unpack value
988  n = nmUnpackS64(buf, bufSize, pVal, eEndian);
989 
990  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%lld", *((long long *)pVal));
991 
992  return n;
993 }
994 
995 /*!
996  * \brief Unpack a 32-bit floating-point number Flat field from the message
997  * buffer.
998  *
999  * \copydoc doc_params_unpack_fdef
1000  * \copydoc doc_return_unpack_std
1001  */
1002 static int nmUnpackFlatF32(const NMFieldDef_T *pFieldDef,
1003  byte_t buf[],
1004  size_t bufSize,
1005  void *pVal,
1006  NMEndian_T eEndian,
1007  NMCtl_T *pCtl)
1008 {
1009  int n; // byte count/error code
1010 
1011  // unpack value
1012  n = nmUnpackF32(buf, bufSize, pVal, eEndian);
1013 
1014  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%f", *((float *)pVal));
1015 
1016  return n;
1017 }
1018 
1019 /*!
1020  * \brief Unpack a 64-bit floating-point number Flat field from the message
1021  * buffer.
1022  *
1023  * \copydoc doc_params_unpack_fdef
1024  * \copydoc doc_return_unpack_std
1025  */
1026 static int nmUnpackFlatF64(const NMFieldDef_T *pFieldDef,
1027  byte_t buf[],
1028  size_t bufSize,
1029  void *pVal,
1030  NMEndian_T eEndian,
1031  NMCtl_T *pCtl)
1032 {
1033  int n; // byte count/error code
1034 
1035  // unpack value
1036  n = nmUnpackF64(buf, bufSize, pVal, eEndian);
1037 
1038  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%e", *((double *)pVal));
1039 
1040  return n;
1041 }
1042 
1043 /*!
1044  * \brief Unpack a 32-bit pointer Flat field from the message buffer.
1045  *
1046  * \copydoc doc_params_unpack_fdef
1047  * \copydoc doc_return_unpack_std
1048  */
1049 static int nmUnpackFlatP32(const NMFieldDef_T *pFieldDef,
1050  byte_t buf[],
1051  size_t bufSize,
1052  void *pVal,
1053  NMEndian_T eEndian,
1054  NMCtl_T *pCtl)
1055 {
1056  int n; // byte count/error code
1057 
1058  // unpack value
1059  n = nmUnpackP32(buf, bufSize, pVal, eEndian);
1060 
1061  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
1062 
1063  return n;
1064 }
1065 
1066 /*!
1067  * \brief Unpack a 64-bit pointer Flat field from the message buffer.
1068  *
1069  * \copydoc doc_params_unpack_fdef
1070  * \copydoc doc_return_unpack_std
1071  */
1072 static int nmUnpackFlatP64(const NMFieldDef_T *pFieldDef,
1073  byte_t buf[],
1074  size_t bufSize,
1075  void *pVal,
1076  NMEndian_T eEndian,
1077  NMCtl_T *pCtl)
1078 {
1079  int n; // byte count/error code
1080 
1081  // unpack value
1082  n = nmUnpackP64(buf, bufSize, pVal, eEndian);
1083 
1084  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
1085 
1086  return n;
1087 }
1088 
1089 /*!
1090  * \brief Unpack variable length string Flat field from the message buffer.
1091  *
1092  * \note The null character is appended to the end of the unpacked value.
1093  *
1094  * \copydoc doc_params_unpack_fdef
1095  * \copydoc doc_return_unpack_std
1096  */
1097 static int nmUnpackFlatString(const NMFieldDef_T *pFieldDef,
1098  byte_t buf[],
1099  size_t bufSize,
1100  void *pVal,
1101  NMEndian_T eEndian,
1102  NMCtl_T *pCtl)
1103 {
1104  size_t uMaxCount; // maximum string length
1105  char *sVal; // string pointer
1106 
1107  // field definition and derived values
1108  uMaxCount = pFieldDef->m_this.m_string.m_uMaxCount;
1109  sVal = (char *)pVal;
1110 
1111  if( uMaxCount > bufSize )
1112  {
1114  "buf_size=%zu, max_count=%zu", bufSize, uMaxCount);
1115  }
1116 
1117  memcpy(sVal, buf, uMaxCount);
1118  sVal[uMaxCount] = 0;
1119 
1120  NMLIB_TRACE_FIELD(pFieldDef, buf, uMaxCount, pCtl, "'%s'", sVal);
1121 
1122  return (int)uMaxCount;
1123 }
1124 
1125 
1126 /*!
1127  * \brief Unpack structure Flat field from the message buffer.
1128  *
1129  * \copydoc doc_params_unpack_fdef
1130  * \copydoc doc_return_unpack_std
1131  */
1132 static int nmUnpackFlatStruct(const NMFieldDef_T *pFieldDef,
1133  byte_t buf[],
1134  size_t bufSize,
1135  void *pVal,
1136  NMEndian_T eEndian,
1137  NMCtl_T *pCtl)
1138 {
1139  const NMMsgDef_T *pStructDef; // structure definition
1140  int n; // byte count/error code
1141 
1142  pStructDef = pFieldDef->m_this.m_struct;
1143 
1144  NMLIB_TRACE_FIELD(pFieldDef, buf, 0, pCtl, "structdef %s, member_count=%zu",
1145  pStructDef->m_sMsgName, pStructDef->m_uCount);
1146 
1147  pCtl->m_uDepth++;
1148 
1149  // copy struct field value
1150  n = nmUnpackFlatStream(pStructDef, buf, bufSize, pVal, eEndian, pCtl);
1151 
1152  pCtl->m_uDepth--;
1153 
1154  return n;
1155 }
1156 
1157 /*!
1158  * \brief Unpack variable length vector Flat field from the message buffer.
1159  *
1160  * A vector is a one-dimension array of the given type.
1161  *
1162  * \copydoc doc_params_unpack_fdef
1163  * \copydoc doc_return_unpack_std
1164  */
1165 static int nmUnpackFlatVector(const NMFieldDef_T *pFieldDef,
1166  byte_t buf[],
1167  size_t bufSize,
1168  void *pVal,
1169  NMEndian_T eEndian,
1170  NMCtl_T *pCtl)
1171 {
1172  size_t uMaxCount; // vector maximum number of elements
1173  size_t uElemSize; // vector element size
1174  const NMFieldDef_T *pElemDef; // vector element field definition
1175  NMVec_T *pVec; // pointer to vector field template
1176  byte_t *pItem; // working vector item pointer
1177  NMFType_T eVType; // vector itim field type
1178  NMUnpackFunc_T fnUnpack; // vector item unpacking function
1179  int n; // byte count/error code
1180  int k; // subbyte count/error code
1181  size_t i; // working vector index
1182 
1183  // field definition and derived values
1184  uMaxCount = pFieldDef->m_this.m_vector.m_uMaxCount;
1185  uElemSize = pFieldDef->m_this.m_vector.m_uElemSize;
1186  pElemDef = pFieldDef->m_this.m_vector.m_pThisElem;
1187  pVec = (NMVec_T *)pVal; // generalized vector overlay
1188  pItem = (byte_t *)(pVec) + memberoffset(NMVec_T, u.m_buf);
1189  eVType = pElemDef->m_eFType;
1190  fnUnpack = nmLookupFlatUnpacker(eVType);
1191 
1192  // no unpacker
1193  if( fnUnpack == NULL )
1194  {
1196  "vector_elem_ftype='%c'(0x%02x).",
1197  NMLIB_ASCII_FTYPE(pElemDef->m_eFType), eVType);
1198  }
1199 
1200  NMLIB_TRACE_FIELD(pFieldDef, buf, 0, pCtl,
1201  "vector_max_count=%zu, vector_elem_ftype='%c'(0x%02x)",
1202  uMaxCount, NMLIB_ASCII_FTYPE(eVType), eVType);
1203 
1204  pCtl->m_uDepth++;
1205 
1206  // unpack field into vector field
1207  for(i=0, n=0; i<uMaxCount; ++i)
1208  {
1209  k = fnUnpack(pElemDef, &buf[n], bufSize-(size_t)n, pItem, eEndian, pCtl);
1210 
1211  if( k < 0 )
1212  {
1213  return k;
1214  }
1215 
1216  n += k;
1217 
1218  pItem += uElemSize;
1219  }
1220 
1221  pCtl->m_uDepth--;
1222 
1223  return n;
1224 }
1225 
1226 /*!
1227  * \brief Unpack an Flat byte stream.
1228  *
1229  * \param pMsgDef Pointer to message definition.
1230  * \param [in] buf Input message buffer.
1231  * \param uMsgLen Length of message (bytes) in input buffer.
1232  * \param [out] pStruct Pointer to the associated message
1233  * structure to populate.
1234  * \param eEndian Unpacking order. See \ref NMEndian_T.
1235  * \param pCtl Pointer to Internal control.
1236  *
1237  * \copydoc doc_return_unpack_std
1238  */
1239 static int nmUnpackFlatStream(const NMMsgDef_T *pMsgDef,
1240  byte_t buf[],
1241  size_t uMsgLen,
1242  void *pStruct,
1243  NMEndian_T eEndian,
1244  NMCtl_T *pCtl)
1245 {
1246  size_t uFieldNum; // field instance number (not id)
1247  const NMFieldDef_T *pFieldDef; // working field definition pointer
1248  NMUnpackFunc_T fnUnpack; // field unpack function
1249  void *pVal; // pointer to field value
1250  int n = 0; // byte count/error code
1251  int k; // subbyte count/error code
1252 
1253  for(uFieldNum=0, pFieldDef=pMsgDef->m_pFields;
1254  uFieldNum < pMsgDef->m_uCount;
1255  ++uFieldNum, ++pFieldDef)
1256  {
1257  if( n < uMsgLen )
1258  {
1259  if( pFieldDef->m_eFType == NMFTypePad )
1260  {
1261  pVal = NULL;
1262  }
1263 
1264  else
1265  {
1266  pVal = pStruct + pFieldDef->m_uOffset;
1267  }
1268 
1269  fnUnpack = nmLookupFlatUnpacker(pFieldDef->m_eFType);
1270 
1271  if( fnUnpack == NULL )
1272  {
1274  "ftype='%c'(0x%02x).",
1275  NMLIB_ASCII_FTYPE(pFieldDef->m_eFType), pFieldDef->m_eFType);
1276  }
1277 
1278  k = fnUnpack(pFieldDef, &buf[n], uMsgLen-(size_t)n, pVal, eEndian, pCtl);
1279 
1280  if( k < 0 )
1281  {
1282  return k;
1283  }
1284  }
1285 
1286  else
1287  {
1289  "buf_size=%zu, msgid=%u", uMsgLen, pMsgDef->m_eMsgId);
1290  }
1291 
1292  n += k;
1293  }
1294 
1295  return n;
1296 }
1297 
1298 
1299 // ...........................................................................
1300 // Private Support Functions
1301 // ...........................................................................
1302 
1303 /*!
1304  * Flat Info Lookup Table
1305  *
1306  * \warning Keep in asending order by ftype.
1307  */
1309 {
1311  {NMFTypeU8, nmPackFlatU8, nmUnpackFlatU8}, // [1] 'B'
1312  {NMFTypeF64, nmPackFlatF64, nmUnpackFlatF64}, // [2] 'F'
1313  {NMFTypeU16, nmPackFlatU16, nmUnpackFlatU16}, // [3] 'H'
1314  {NMFTypeU32, nmPackFlatU32, nmUnpackFlatU32}, // [4] 'I'
1315  {NMFTypeP64, nmPackFlatP64, nmUnpackFlatP64}, // [5] 'P'
1316  {NMFTypeU64, nmPackFlatU64, nmUnpackFlatU64}, // [6] 'Q'
1318  {NMFTypeS8, nmPackFlatS8, nmUnpackFlatS8}, // [8] 'b'
1319  {NMFTypeChar, nmPackFlatU8, nmUnpackFlatU8}, // [9] 'c'
1320  {NMFTypeF32, nmPackFlatF32, nmUnpackFlatF32}, // [10] 'f'
1321  {NMFTypeS16, nmPackFlatS16, nmUnpackFlatS16}, // [11] 'h'
1322  {NMFTypeS32, nmPackFlatS32, nmUnpackFlatS32}, // [12] 'i'
1323  {NMFTypeP32, nmPackFlatP32, nmUnpackFlatP32}, // [13] 'p'
1324  {NMFTypeS64, nmPackFlatS64, nmUnpackFlatS64}, // [14] 'q'
1326  {NMFTypePad, nmPackFlatPad, nmUnpackFlatPad}, // [16] 'x'
1328 };
1329 
1330 /*!
1331  * \brief Lookup Flat packer function, given the message field type.
1332  *
1333  * \param eFType Message field type.
1334  *
1335  * \return Returns packer function on success, NULL on failure.
1336  */
1338 {
1339  int idx;
1340 
1341  idx = NMHashFType(eFType);
1342 
1343  if( (idx != NMHashNoIdx) && (idx < arraysize(NMFlatLookupTbl)) )
1344  {
1345  if( NMFlatLookupTbl[idx].m_eFType == eFType )
1346  {
1347  return NMFlatLookupTbl[idx].m_fnPack;
1348  }
1349  else
1350  {
1352  "hashed eFtype='%c'(0x%02x) != tbl[%d].m_eFType='%c'(0x%02x)",
1353  NMLIB_ASCII_FTYPE(eFType), eFType,
1354  idx, NMLIB_ASCII_FTYPE(NMFlatLookupTbl[idx].m_eFType),
1355  NMFlatLookupTbl[idx].m_eFType);
1356  return NULL;
1357  }
1358  }
1359  else
1360  {
1361  return NULL;
1362  }
1363 }
1364 
1365 /*!
1366  * \brief Lookup Flat unpacker function, given the message field type.
1367  *
1368  * \param eFType Message field type.
1369  *
1370  * \return Returns unpacker function on success, NULL on failure.
1371  */
1373 {
1374  int idx;
1375 
1376  idx = NMHashFType(eFType);
1377 
1378  if( (idx != NMHashNoIdx) && (idx < arraysize(NMFlatLookupTbl)) )
1379  {
1380  if( NMFlatLookupTbl[idx].m_eFType == eFType )
1381  {
1382  return NMFlatLookupTbl[idx].m_fnUnpack;
1383  }
1384  else
1385  {
1387  "hashed eFtype='%c'(0x%02x) != tbl[%d].m_eFType='%c'(0x%02x)",
1388  NMLIB_ASCII_FTYPE(eFType), eFType,
1389  idx, NMLIB_ASCII_FTYPE(NMFlatLookupTbl[idx].m_eFType),
1390  NMFlatLookupTbl[idx].m_eFType);
1391  return NULL;
1392  }
1393  }
1394  else
1395  {
1396  return NULL;
1397  }
1398 }
1399 
1400 
1401 // ---------------------------------------------------------------------------
1402 // Public Interface
1403 // ---------------------------------------------------------------------------
1404 
1405 /*!
1406  * \brief Pack an Flat message.
1407  *
1408  * \param pMsgDef Pointer to message definition.
1409  * \param [in] pStruct Pointer to the associated, populated message
1410  * structure.
1411  * \param [out] buf Output message buffer.
1412  * \param bufSize Size of output buffer.
1413  * \param eEndian Packing order. See \ref NMEndian_T.
1414  *
1415  * \copydoc doc_return_pack_std
1416  */
1417 int nmPackFlatMsg(const NMMsgDef_T *pMsgDef,
1418  void *pStruct,
1419  byte_t buf[],
1420  size_t bufSize,
1421  NMEndian_T eEndian)
1422 {
1423  NMCtl_T ctl = NMCTL_INIT_DECL;
1424  int n; // byte count/error code
1425 
1426  ctl.m_bNoHdr = true;
1427 
1428  // pack stream
1429  n = nmPackFlatStream(pMsgDef, pStruct, buf, bufSize, eEndian, &ctl);
1430 
1431  return n;
1432 }
1433 
1434 /*!
1435  * \brief Pack an Flat message, tracing message packing to stderr.
1436  *
1437  * \param pMsgDef Pointer to message definition.
1438  * \param [in] pStruct Pointer to the associated, populated message
1439  * structure.
1440  * \param [out] buf Output message buffer.
1441  * \param bufSize Size of output buffer.
1442  * \param eEndian Packing order. See \ref NMEndian_T.
1443  *
1444  * \copydoc doc_return_pack_std
1445  */
1446 int nmPackFlatMsgDebug(const NMMsgDef_T *pMsgDef,
1447  void *pStruct,
1448  byte_t buf[],
1449  size_t bufSize,
1450  NMEndian_T eEndian)
1451 {
1452  NMCtl_T ctl = NMCTL_INIT_DECL;
1453  int n; // byte count/error code
1454 
1455  ctl.m_bNoHdr = true;
1456  ctl.m_bTrace = true;
1457 
1458  // trace
1459  fprintf(stderr, "\n--- Packing Flat Message %s(%u): field_count=%zu\n",
1460  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, pMsgDef->m_uCount);
1461 
1462  // pack stream
1463  n = nmPackFlatStream(pMsgDef, pStruct, buf, bufSize, eEndian, &ctl);
1464 
1465  // trace final buffer
1466  if( n > 0 )
1467  {
1468  fprintf(stderr, "Output Buffer (%zu bytes):\n", (size_t)n);
1469  nmPrintBuf(stderr, NULL, buf, (size_t)n, 16, 0);
1470  fprintf(stderr, "\n");
1471  }
1472 
1473  return n;
1474 }
1475 
1476 /*!
1477  * \brief Unpack a Flat message.
1478  *
1479  * \param pMsgDef Pointer to message definition.
1480  * \param [in] buf Input message buffer.
1481  * \param uMsgLen Length of message (bytes) in input buffer.
1482  * \param [out] pStruct Pointer to the associated message
1483  * structure to populate.
1484  * \param eEndian Unpacking order. See \ref NMEndian_T.
1485  *
1486  * \returns
1487  * On success, returns the number of bytes unpacked.
1488  * On error, returns \h_lt 0.
1489  */
1490 int nmUnpackFlatMsg(const NMMsgDef_T *pMsgDef,
1491  byte_t buf[],
1492  size_t uMsgLen,
1493  void *pStruct,
1494  NMEndian_T eEndian)
1495 {
1496  NMCtl_T ctl = NMCTL_INIT_DECL;
1497  int n; // byte count/error code
1498 
1499  ctl.m_bNoHdr = true;
1500 
1501  // unpack stream
1502  n = nmUnpackFlatStream(pMsgDef, buf, uMsgLen, pStruct, eEndian, &ctl);
1503 
1504  // return code
1505  return n;
1506 }
1507 
1508 /*!
1509  * \brief Unpack a Flat message, tracing unpacking to stderr.
1510  *
1511  * \param pMsgDef Pointer to message definition.
1512  * \param [in] buf Input message buffer.
1513  * \param uMsgLen Length of message (bytes) in input buffer.
1514  * \param [out] pStruct Pointer to the associated message
1515  * structure to populate.
1516  * \param eEndian Unpacking order. See \ref NMEndian_T.
1517  *
1518  * \copydoc doc_return_unpack_std
1519  */
1521  byte_t buf[],
1522  size_t uMsgLen,
1523  void *pStruct,
1524  NMEndian_T eEndian)
1525 {
1526  NMCtl_T ctl = NMCTL_INIT_DECL;
1527  int n; // byte count/error code
1528 
1529  ctl.m_bNoHdr = true;
1530  ctl.m_bTrace = true;
1531 
1532  // trace
1533  fprintf(stderr, "\n--- Unpacking Flat Message %s(%u): field_count=%zu\n",
1534  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, pMsgDef->m_uCount);
1535  fprintf(stderr, "Input Buffer (%zu bytes):\n", uMsgLen);
1536  nmPrintBuf(stderr, NULL, buf, uMsgLen, 16, 0);
1537  fprintf(stderr, "\n");
1538 
1539  // unpack stream
1540  n = nmUnpackFlatStream(pMsgDef, buf, uMsgLen, pStruct, eEndian, &ctl);
1541 
1542  // return code
1543  return n;
1544 }
int nmPackP64(void *val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a 64-bit pointer into the message buffer.
Definition: nmLibPack.c:1160
byte_t m_bNoHdr
do [not] include field header in byte stream
int nmPackF32(float val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a 32-bit float into the message buffer.
Definition: nmLibPack.c:957
static int nmUnpackFlatString(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack variable length string Flat field from the message buffer.
int nmUnpackU16(byte_t buf[], size_t bufSize, ushort_t *pVal, NMEndian_T eEndian)
Unpack an unsigned 16-bit integer from the message buffer.
Definition: nmLibPack.c:1256
64-bit IEEE 754 FPN double
Definition: netmsgs.h:120
unsigned 8-bit integer unsigned char
Definition: netmsgs.h:118
static int nmUnpackFlatF32(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a 32-bit floating-point number Flat field from the message buffer.
static int nmUnpackFlatPad(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack pad byte from the message buffer.
static NMLookupTblEntry_T NMFlatLookupTbl[]
32-bit IEEE 754 FPN float
Definition: netmsgs.h:134
int nmSetU32(const NMFieldDef_T *pFieldDef, void *pValIn, uint_t *pValOut)
Helper function to set an unsigned 32-bit integer.
static int nmPackFlatS8(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 8-bit Flat field into the message buffer.
unsigned 64-bit integer unsigned long long
Definition: netmsgs.h:128
#define NMLIB_ERROR(ecode, fmt,...)
Log libnetmsgs error.
byte_t m_uDepth
structured message depth
structure struct T
Definition: netmsgs.h:146
size_t m_uMaxCount
maximum number of vector elements
Definition: netmsgs.h:354
static int nmPackFlatStream(const NMMsgDef_T *pMsgDef, void *pStruct, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a Flat message.
static int nmUnpackFlatStruct(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack structure Flat field from the message buffer.
NMFieldThisVector_T m_vector
vector field specific info
Definition: netmsgs.h:373
#define NM_ECODE_FTYPE
unknown field type
Definition: netmsgs.h:76
int nmUnpackF64(byte_t buf[], size_t bufSize, double *pVal, NMEndian_T eEndian)
Unpack a 64-bit float from the message buffer.
Definition: nmLibPack.c:1517
static int nmPackFlatPad(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack pad bytes into the message buffer.
Definition: nmLibPackFlat.c:89
const int NMHashNoIdx
hash no index value
static int nmPackFlatS16(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 16-bit Flat field into the message buffer.
INLINE_IN_H int nmUnpackS32(byte_t buf[], size_t bufSize, int *pVal, NMEndian_T eEndian)
Unpack a signed 32-bit integer from the message buffer.
Definition: netmsgs.h:771
NMFieldThisString_T m_string
string field specific info
Definition: netmsgs.h:371
static NMPackFunc_T nmLookupFlatPacker(NMFType_T eFType)
Lookup Flat packer function, given the message field type.
int nmPackU32(uint_t val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an unsigned 32-bit integer into the message buffer.
Definition: nmLibPack.c:791
static int nmPackFlatF32(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a 32-bit floating-point number Flat field into the message buffer.
int nmUnpackS64(byte_t buf[], size_t bufSize, long long *pVal, NMEndian_T eEndian)
Unpack an signed 64-bit integer from the message buffer.
Definition: nmLibPack.c:1391
byte_t m_bTrace
do [not] trace packing/unpacking
signed 32-bit integer int
Definition: netmsgs.h:138
int nmUnpackF32(byte_t buf[], size_t bufSize, float *pVal, NMEndian_T eEndian)
Unpack a 32-bit float from the message buffer.
Definition: nmLibPack.c:1472
static int nmUnpackFlatS16(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 16-bit Flat field from the message buffer.
#define NMLIB_TRACE_FIELD(p, buf, n, ctl, fmt,...)
Trace field.
INLINE_IN_H int nmPackBool(bool_t val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a boolean value into the message buffer.
Definition: netmsgs.h:564
NMFType_T m_eFType
field type
Definition: netmsgs.h:383
string char[]
Definition: netmsgs.h:144
#define NM_OK
not an error, success
Definition: netmsgs.h:70
static int nmPackFlatString(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack null-terminated, fixed length string Flat field into the message buffer.
static int nmUnpackFlatP64(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a 64-bit pointer Flat field from the message buffer.
uint_t m_eMsgId
message id (globally unique)
Definition: netmsgs.h:407
static int nmUnpackFlatBool(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 8-bit boolean Flat field from the message buffer.
size_t m_uCount
number of message fields
Definition: netmsgs.h:408
int(* NMUnpackFunc_T)(const NMFieldDef_T *, byte_t[], size_t, void *, NMEndian_T, NMCtl_T *)
NMFieldThisStruct_T m_struct
struct field specific info
Definition: netmsgs.h:372
#define NMLIB_RAISE_ERROR(ecode, fmt,...)
Raise libnetmsgs error (i.e. return from calling function).
static int nmUnpackFlatStream(const NMMsgDef_T *pMsgDef, byte_t buf[], size_t uMsgLen, void *pStruct, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an Flat byte stream.
#define NMFVAL_PAD
pad field value same as tr id
Definition: netmsgs.h:208
int nmSetF64(const NMFieldDef_T *pFieldDef, void *pValIn, double *pValOut)
Helper function to set a 64-bit floating point number.
#define NMFTYPE_IS_SIMPLE(ft)
Returns true if field type is a simple type.
Definition: netmsgs.h:164
#define NMCTL_INIT_DECL
Default Internal control declartion list.
static int nmPackFlatStruct(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a structure Flat field into the message buffer.
int nmUnpackFlatMsgDebug(const NMMsgDef_T *pMsgDef, byte_t buf[], size_t uMsgLen, void *pStruct, NMEndian_T eEndian)
Unpack a Flat message, tracing unpacking to stderr.
static int nmPackFlatU8(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 8-bit Flat field into the message buffer.
static int nmUnpackFlatU64(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 64-bit Flat field from the message buffer.
static NMUnpackFunc_T nmLookupFlatUnpacker(NMFType_T eFType)
Lookup Flat unpacker function, given the message field type.
8-bit ASCII characters char
Definition: netmsgs.h:133
int nmUnpackU64(byte_t buf[], size_t bufSize, ulonglong_t *pVal, NMEndian_T eEndian)
Unpack an unsigned 64-bit integer from the message buffer.
Definition: nmLibPack.c:1320
signed 64-bit integer long long
Definition: netmsgs.h:142
NMFieldThis_T m_this
specific field information
Definition: netmsgs.h:385
int nmUnpackFlatMsg(const NMMsgDef_T *pMsgDef, byte_t buf[], size_t uMsgLen, void *pStruct, NMEndian_T eEndian)
Unpack a Flat message.
static int nmUnpackFlatU8(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 8-bit Flat field from the message buffer.
8-bit bool 0/1 bool_t
Definition: netmsgs.h:117
int nmSetS8(const NMFieldDef_T *pFieldDef, void *pValIn, signed char *pValOut)
Helper function to set a signed 8-bit integer.
int nmPackU8(byte_t val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an unsigned 8-bit byte into the message buffer.
Definition: nmLibPack.c:745
INLINE_IN_H int nmUnpackS8(byte_t buf[], size_t bufSize, signed char *pVal, NMEndian_T eEndian)
Unpack a signed 8-bit byte from the message buffer.
Definition: netmsgs.h:747
int nmSetU8(const NMFieldDef_T *pFieldDef, void *pValIn, byte_t *pValOut)
Helper function to set an unsigned 8-bit integer.
int nmSetF32(const NMFieldDef_T *pFieldDef, void *pValIn, float *pValOut)
Helper function to set a 32-bit floating point number.
32-bit pointer (overloaded) void*
Definition: netmsgs.h:140
INLINE_IN_H int nmUnpackBool(byte_t buf[], size_t bufSize, bool_t *pVal, NMEndian_T eEndian)
Unpack a boolean value from the message buffer.
Definition: netmsgs.h:823
static int nmUnpackFlatP32(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a 32-bit pointer Flat field from the message buffer.
static int nmUnpackFlatU16(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 16-bit Flat field from the message buffer.
size_t m_uMaxCount
maximum number of characters sans null char
Definition: netmsgs.h:339
64-bit pointer (overloaded) void*
Definition: netmsgs.h:126
static int nmPackFlatU16(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 16-bit Flat field into the message buffer.
static int nmUnpackFlatU32(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 32-bit Flat field from the message buffer.
static int nmPackFlatF64(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a 64-bit floating-point number Flat field into the message buffer.
int nmSetS16(const NMFieldDef_T *pFieldDef, void *pValIn, short *pValOut)
Helper function to set a signed 16-bit integer.
int nmPackS64(long long val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an signed 64-bit integer into the message buffer.
Definition: nmLibPack.c:885
#define NM_ECODE_NOMEM
not enough buffer memory available
Definition: netmsgs.h:73
size_t m_uCount
number of pad bytes
Definition: netmsgs.h:265
NMFType_T
Definition: netmsgs.h:110
static int nmUnpackFlatS64(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 64-bit Flat field from the message buffer.
NMEndian_T
Definition: netmsgs.h:100
static int nmPackFlatP64(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a 64-bit pointer Flat field into the message buffer.
signed 8-bit integer signed char
Definition: netmsgs.h:131
int(* NMPackFunc_T)(const NMFieldDef_T *, void *, byte_t[], size_t, NMEndian_T, NMCtl_T *)
const char * m_sMsgName
message/struct string name
Definition: netmsgs.h:406
const char * m_sConst
string constant value (NULL if no const)
Definition: netmsgs.h:340
int nmPackFlatMsgDebug(const NMMsgDef_T *pMsgDef, void *pStruct, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an Flat message, tracing message packing to stderr.
int nmPackU16(ushort_t val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an unsigned 16-bit integer into the message buffer.
Definition: nmLibPack.c:762
one dimensional array VType[]
Definition: netmsgs.h:130
INLINE_IN_H int nmPackS32(int val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a signed 32-bit integer into the message buffer.
Definition: netmsgs.h:512
NMFieldDef_P m_pThisElem
vector element specific info
Definition: netmsgs.h:356
static int nmPackFlatU32(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 32-bit Flat field into the message buffer.
static int nmUnpackFlatS32(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 32-bit Flat field from the message buffer.
const NMFieldDef_T * m_pFields
pointer to array of msg field definitions
Definition: netmsgs.h:409
int nmSetS32(const NMFieldDef_T *pFieldDef, void *pValIn, int *pValOut)
Helper function to set a signed 32-bit integer.
static int nmPackFlatP32(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a 32-bit pointer Flat field into the message buffer.
int nmPackF64(double val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a 64-bit float into the message buffer.
Definition: nmLibPack.c:1013
static int nmUnpackFlatS8(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 8-bit Flat field from the message buffer.
size_t m_uElemSize
vector element storage size
Definition: netmsgs.h:355
#define NM_ECODE_INTERNAL
internal inconsistency or bug
Definition: netmsgs.h:80
size_t m_uCount
number of items in vector
Definition: netmsgs.h:393
int nmUnpackU32(byte_t buf[], size_t bufSize, uint_t *pVal, NMEndian_T eEndian)
Unpack an unsigned 32-bit integer from the message buffer.
Definition: nmLibPack.c:1288
unsigned 32-bit integer unsigned int
Definition: netmsgs.h:124
pad internal field type
Definition: netmsgs.h:145
INLINE_IN_H int nmPackS8(signed char val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a signed 8-bit byte into the message buffer.
Definition: netmsgs.h:488
int nmSetS64(const NMFieldDef_T *pFieldDef, void *pValIn, long long *pValOut)
Helper function to set a signed 64-bit integer.
#define NMLIB_RAISE_FIELD_ERROR(ecode, p, fmt,...)
Raise libnetmsgs field error (i.e. return from calling function).
Internal intra-library declarations.
int nmUnpackP64(byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian)
Unpack a 64-bit pointer from the message buffer.
Definition: nmLibPack.c:1678
int nmSetU64(const NMFieldDef_T *pFieldDef, void *pValIn, ulonglong_t *pValOut)
Helper function to set an unsigned 64-bit integer.
void nmPrintBuf(FILE *fp, const char *sPreface, byte_t buf[], size_t uCount, size_t uNLFreq, uint_t uCol)
Pretty print buffer to opened file stream.
Definition: nmLibUtils.c:138
static int nmPackFlatU64(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 64-bit Flat field into the message buffer.
static int nmUnpackFlatVector(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack variable length vector Flat field from the message buffer.
int nmPackFlatMsg(const NMMsgDef_T *pMsgDef, void *pStruct, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an Flat message.
INLINE_IN_H int NMHashFType(NMFType_T eFType)
Field Type to Index hash function.
#define NMLIB_ASCII_FTYPE(ftype)
Printable ASCII Field Type.
static int nmPackFlatVector(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack variable length vector Flat field into the message buffer.
static int nmPackFlatS32(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 32-bit Flat field into the message buffer.
Network Messaging declarations.
NMFieldThisPad_T m_pad
pad field specific info
Definition: netmsgs.h:364
int nmUnpackU8(byte_t buf[], size_t bufSize, byte_t *pVal, NMEndian_T eEndian)
Unpack an unsigned 8-bit byte from the message buffer.
Definition: nmLibPack.c:1239
static int nmPackFlatS64(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 64-bit Flat field into the message buffer.
static int nmUnpackFlatF64(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a 64-bit floating-point number Flat field from the message buffer.
#define NM_ECODE_RANGE
field size or value out-of-range
Definition: netmsgs.h:75
INLINE_IN_H int nmUnpackS16(byte_t buf[], size_t bufSize, short *pVal, NMEndian_T eEndian)
Unpack a signed 16-bit integer from the message buffer.
Definition: netmsgs.h:759
int nmSetU16(const NMFieldDef_T *pFieldDef, void *pValIn, ushort_t *pValOut)
Helper function to set an unsigned 16-bit integer.
size_t m_uOffset
member offset in assoc msg structure
Definition: netmsgs.h:384
INLINE_IN_H int nmPackS16(short val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a signed 16-bit integer into the message buffer.
Definition: netmsgs.h:500
byte_t * m_buf
the vector
Definition: netmsgs.h:397
Internal Control Structure.
static int nmPackFlatBool(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a boolean into an 8-bit Flat field into the message buffer.
int nmPackU64(ulonglong_t val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an unsigned 64-bit integer into the message buffer.
Definition: nmLibPack.c:823
NMPackFunc_T m_fnPack
packer
unsigned 16-bit integer unsigned short
Definition: netmsgs.h:122
NMUnpackFunc_T m_fnUnpack
unpacker
signed 16-bit integer short
Definition: netmsgs.h:136
uint_t m_eFId
filed id (message/struct unique)
Definition: netmsgs.h:382
int nmUnpackP32(byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian)
Unpack a 32-bit pointer from the message buffer.
Definition: nmLibPack.c:1648
int nmPackP32(void *val, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack a 32-bit pointer into the message buffer.
Definition: nmLibPack.c:1113