netmsgs  1.2.2
RoadNarrows Robotics Network Messaging Package
nmLibPackITV.c
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: netmsgs
4 //
5 // Library: libnetmsgs
6 //
7 // File: nmLibPackIVT.c
8 //
9 /*! \file
10  *
11  * $LastChangedDate: 2010-07-31 08:48:56 -0600 (Sat, 31 Jul 2010) $
12  * $Rev: 521 $
13  *
14  * \brief Identifier-Type-Value (ITV) 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 Interface
64 // ---------------------------------------------------------------------------
65 
66 //
67 // Forward Declarations
68 //
71 static int nmPackITVStream(const NMMsgDef_T *pMsgDef, void *pStruct,
72  byte_t buf[], size_t bufSize, NMEndian_T eEndian,
73  NMCtl_T *pCtl);
74 static int nmUnpackITVStream(const NMMsgDef_T *pMsgDef, byte_t buf[],
75  size_t uMsgLen, size_t uCount, void *pStruct,
76  NMEndian_T eEndian, NMCtl_T *pCtl);
77 
78 
79 // ...........................................................................
80 // Private Packing Interface
81 // ...........................................................................
82 
83 /*!
84  * \brief Pack simple field type ITV header.
85  *
86  * \param p Pointer to message field definition.
87  * \param [out] buf Output message buffer.
88  * \param n Size of output buffer.
89  * \param ctl Internal control.
90  *
91  * \copydoc doc_return_pack_std
92  */
93 #define ITVPACK_SIMPLE_HDR(p, buf, n, ctl) \
94  ((ctl)->m_bNoHdr? 0: nmPackITVHdrSimple(p, buf, n))
95 
96 /*!
97  * \brief Pack ITV simple header.
98  *
99  * \param pFieldDef Pointer to message field definition.
100  * \param [out] buf Output message buffer.
101  * \param bufSize Size of output buffer.
102  *
103  * \copydoc doc_return_pack_std
104  */
105 static int nmPackITVHdrSimple(const NMFieldDef_T *pFieldDef,
106  byte_t buf[],
107  size_t bufSize)
108 {
109  // pack simple ITV header
110  if( NMITV_FHDR_SIZE_SIMPLE <= bufSize )
111  {
112  buf[0] = (byte_t)(pFieldDef->m_eFId & 0xff);
113  buf[1] = (byte_t)(pFieldDef->m_eFType & 0xff);
114  return NMITV_FHDR_SIZE_SIMPLE;
115  }
116 
117  // no more space in buffer for header
118  else
119  {
121  "buf_size=%zu < fhdr_size=%u", bufSize, NMITV_FHDR_SIZE_STRING);
122  }
123 }
124 
125 /*!
126  * \brief Pack ITV String header.
127  *
128  * \param pFieldDef Pointer to message field definition.
129  * \param uCount Number of character bytes in string.
130  * \param [out] buf Output message buffer.
131  * \param bufSize Size of output buffer.
132  *
133  * \copydoc doc_return_pack_std
134  */
135 static int nmPackITVHdrString(const NMFieldDef_T *pFieldDef,
136  size_t uCount,
137  byte_t buf[],
138  size_t bufSize)
139 {
140  // pack string ITV header
141  if( NMITV_FHDR_SIZE_STRING <= bufSize )
142  {
143  buf[0] = (byte_t)(pFieldDef->m_eFId & 0xff);
144  buf[1] = (byte_t)(pFieldDef->m_eFType & 0xff);
145  buf[2] = (byte_t)(uCount & 0xff);
146  return NMITV_FHDR_SIZE_STRING;
147  }
148 
149  // no more space in buffer for header
150  else
151  {
153  "buf_size=%zu < fhdr_size=%u", bufSize, NMITV_FHDR_SIZE_STRING);
154  }
155 }
156 
157 /*!
158  * \brief Pack ITV Struct header.
159  *
160  * \param pFieldDef Pointer to message field definition.
161  * \param [out] buf Output message buffer.
162  * \param bufSize Size of output buffer.
163  *
164  * \copydoc doc_return_pack_std
165  */
166 static int nmPackITVHdrStruct(const NMFieldDef_T *pFieldDef,
167  byte_t buf[],
168  size_t bufSize)
169 {
170  // pack struct ITV header
171  if( NMITV_FHDR_SIZE_STRUCT <= bufSize )
172  {
173  buf[0] = (byte_t)(pFieldDef->m_eFId & 0xff);
174  buf[1] = (byte_t)(pFieldDef->m_eFType & 0xff);
175  buf[2] = (byte_t)pFieldDef->m_this.m_struct->m_uCount;
176  return NMITV_FHDR_SIZE_STRUCT;
177  }
178 
179  // no more space in buffer for header
180  else
181  {
183  "buf_size=%zu < fhdr_size=%zu", bufSize, NMITV_FHDR_SIZE_STRUCT);
184  }
185 }
186 
187 /*!
188  * \brief Pack ITV Vector header.
189  *
190  * \param pFieldDef Pointer to message field definition.
191  * \param uCount Number of vector elements.
192  * \param [out] buf Output message buffer.
193  * \param bufSize Size of output buffer.
194  *
195  * \copydoc doc_return_pack_std
196  */
197 static int nmPackITVHdrVector(const NMFieldDef_T *pFieldDef,
198  size_t uCount,
199  byte_t buf[],
200  size_t bufSize)
201 {
202  // pack vector ITV header
203  if( NMITV_FHDR_SIZE_VECTOR <= bufSize )
204  {
205  buf[0] = (byte_t)(pFieldDef->m_eFId & 0xff);
206  buf[1] = (byte_t)(pFieldDef->m_eFType & 0xff);
207  buf[2] = (byte_t)(uCount & 0xff);
208  buf[3] = (byte_t)pFieldDef->m_this.m_vector.m_pThisElem->m_eFType;
209  return NMITV_FHDR_SIZE_VECTOR;
210  }
211 
212  // no more space in buffer for header
213  else
214  {
216  "buf_size=%zu < fhdr_size=%u", bufSize, NMITV_FHDR_SIZE_VECTOR);
217  }
218 }
219 
220 /*!
221  * \brief Pack pad bytes into the message buffer.
222  *
223  * \copydoc doc_params_pack_fdef
224  * \copydoc doc_return_pack_std
225  */
226 static int nmPackITVPad(const NMFieldDef_T *pFieldDef,
227  void *pVal,
228  byte_t buf[],
229  size_t bufSize,
230  NMEndian_T eEndian,
231  NMCtl_T *pCtl)
232 {
233  size_t uCount = pFieldDef->m_this.m_pad.m_uCount;
234 
235  // pack pad bytes
236  if( uCount <= bufSize )
237  {
238  memset(buf, NMFVAL_PAD, uCount);
239  NMLIB_TRACE_FIELD(NULL, buf, uCount, pCtl, "pad(%u)", pFieldDef->m_eFId);
240  return (int)uCount;
241  }
242 
243  // no more space in buffer for pad bytes
244  else
245  {
247  "buf_size=%zu < pad_count=%zu", bufSize, uCount);
248  }
249 }
250 
251 /*!
252  * \brief Pack a boolean into an 8-bit ITV field into the message buffer.
253  *
254  * \copydoc doc_params_pack_fdef
255  * \copydoc doc_return_pack_std
256  */
257 static int nmPackITVBool(const NMFieldDef_T *pFieldDef,
258  void *pVal,
259  byte_t buf[],
260  size_t bufSize,
261  NMEndian_T eEndian,
262  NMCtl_T *pCtl)
263 {
264  bool_t val; // constrained field value
265  int n; // byte count/error code
266  int k; // subbyte count/error code
267 
268  val = *((bool_t *)pVal);
269 
270  // try to pack header
271  if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
272  {
273  return n;
274  }
275 
276  // try to pack field value
277  else if( (k = nmPackBool(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
278  {
279  return k;
280  }
281 
282  // success
283  else
284  {
285  n += k;
286 
287  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%s", (val? "true": "false"));
288 
289  return n;
290  }
291 }
292 
293 /*!
294  * \brief Pack an unsigned 8-bit ITV field into the message buffer.
295  *
296  * \copydoc doc_params_pack_fdef
297  * \copydoc doc_return_pack_std
298  */
299 static int nmPackITVU8(const NMFieldDef_T *pFieldDef,
300  void *pVal,
301  byte_t buf[],
302  size_t bufSize,
303  NMEndian_T eEndian,
304  NMCtl_T *pCtl)
305 {
306  byte_t val; // constrained field value
307  int n; // byte count/error code
308  int k; // subbyte count/error code
309 
310  // try to set field value
311  if( (n = nmSetU8(pFieldDef, pVal, &val)) != NM_OK )
312  {
313  return n;
314  }
315 
316  // try to pack header
317  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
318  {
319  return n;
320  }
321 
322  // try to pack field value
323  else if( (k = nmPackU8(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
324  {
325  return k;
326  }
327 
328  // success
329  else
330  {
331  n += k;
332 
333  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhu", val);
334 
335  return n;
336  }
337 }
338 
339 /*!
340  * \brief Pack a signed 8-bit ITV field into the message buffer.
341  *
342  * \copydoc doc_params_pack_fdef
343  * \copydoc doc_return_pack_std
344  */
345 static int nmPackITVS8(const NMFieldDef_T *pFieldDef,
346  void *pVal,
347  byte_t buf[],
348  size_t bufSize,
349  NMEndian_T eEndian,
350  NMCtl_T *pCtl)
351 {
352  signed char val; // constrained field value
353  int n; // byte count/error code
354  int k; // subbyte count/error code
355 
356  // try to set field value
357  if( (n = nmSetS8(pFieldDef, pVal, &val)) != NM_OK )
358  {
359  return n;
360  }
361 
362  // try to pack header
363  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
364  {
365  return n;
366  }
367 
368  // try to pack field value
369  else if( (k = nmPackS8(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
370  {
371  return k;
372  }
373 
374  // success
375  else
376  {
377  n += k;
378 
379  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhd", val);
380 
381  return n;
382  }
383 }
384 
385 /*!
386  * \brief Pack an unsigned 16-bit ITV field into the message buffer.
387  *
388  * \copydoc doc_params_pack_fdef
389  * \copydoc doc_return_pack_std
390  */
391 static int nmPackITVU16(const NMFieldDef_T *pFieldDef,
392  void *pVal,
393  byte_t buf[],
394  size_t bufSize,
395  NMEndian_T eEndian,
396  NMCtl_T *pCtl)
397 {
398  ushort_t val; // constrained field value
399  int n; // byte count/error code
400  int k; // subbyte count/error code
401 
402  // try to set field value
403  if( (n = nmSetU16(pFieldDef, pVal, &val)) != NM_OK )
404  {
405  return n;
406  }
407 
408  // try to pack header
409  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
410  {
411  return n;
412  }
413 
414  // try to pack field value
415  else if( (k = nmPackU16(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
416  {
417  return k;
418  }
419 
420  // success
421  else
422  {
423  n += k;
424 
425  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hu", val);
426 
427  return n;
428  }
429 }
430 
431 /*!
432  * \brief Pack a signed 16-bit ITV field into the message buffer.
433  *
434  * \copydoc doc_params_pack_fdef
435  * \copydoc doc_return_pack_std
436  */
437 static int nmPackITVS16(const NMFieldDef_T *pFieldDef,
438  void *pVal,
439  byte_t buf[],
440  size_t bufSize,
441  NMEndian_T eEndian,
442  NMCtl_T *pCtl)
443 {
444  short val; // constrained field value
445  int n; // byte count/error code
446  int k; // subbyte count/error code
447 
448  // try to set field value
449  if( (n = nmSetS16(pFieldDef, pVal, &val)) != NM_OK )
450  {
451  return n;
452  }
453 
454  // try to pack header
455  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
456  {
457  return n;
458  }
459 
460  // try to pack field value
461  else if( (k = nmPackS16(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0)
462  {
463  return k;
464  }
465 
466  // success
467  else
468  {
469  n += k;
470 
471  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hd", val);
472 
473  return n;
474  }
475 }
476 
477 /*!
478  * \brief Pack an unsigned 32-bit ITV field into the message buffer.
479  *
480  * \copydoc doc_params_pack_fdef
481  * \copydoc doc_return_pack_std
482  */
483 static int nmPackITVU32(const NMFieldDef_T *pFieldDef,
484  void *pVal,
485  byte_t buf[],
486  size_t bufSize,
487  NMEndian_T eEndian,
488  NMCtl_T *pCtl)
489 {
490  uint_t val; // constrained field value
491  int n; // byte count/error code
492  int k; // subbyte count/error code
493 
494  // try to set field value
495  if( (n = nmSetU32(pFieldDef, pVal, &val)) != NM_OK )
496  {
497  return n;
498  }
499 
500  // try to pack header
501  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
502  {
503  return n;
504  }
505 
506  // try to pack field value
507  else if( (k = nmPackU32(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
508  {
509  return k;
510  }
511 
512  // success
513  else
514  {
515  n += k;
516 
517  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%u", val);
518 
519  return n;
520  }
521 }
522 
523 /*!
524  * \brief Pack a signed 32-bit ITV field into the message buffer.
525  *
526  * \copydoc doc_params_pack_fdef
527  * \copydoc doc_return_pack_std
528  */
529 static int nmPackITVS32(const NMFieldDef_T *pFieldDef,
530  void *pVal,
531  byte_t buf[],
532  size_t bufSize,
533  NMEndian_T eEndian,
534  NMCtl_T *pCtl)
535 {
536  int val; // constrained field value
537  int n; // byte count/error code
538  int k; // subbyte count/error code
539 
540  // try to set field value
541  if( (n = nmSetS32(pFieldDef, pVal, &val)) != NM_OK )
542  {
543  return n;
544  }
545 
546  // try to pack header
547  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
548  {
549  return n;
550  }
551 
552  // try to pack field value
553  else if( (k = nmPackS32(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
554  {
555  return k;
556  }
557 
558  // success
559  else
560  {
561  n += k;
562 
563  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%d", val);
564 
565  return n;
566  }
567 }
568 
569 /*!
570  * \brief Pack an unsigned 64-bit ITV field into the message buffer.
571  *
572  * \copydoc doc_params_pack_fdef
573  * \copydoc doc_return_pack_std
574  */
575 static int nmPackITVU64(const NMFieldDef_T *pFieldDef,
576  void *pVal,
577  byte_t buf[],
578  size_t bufSize,
579  NMEndian_T eEndian,
580  NMCtl_T *pCtl)
581 {
582  ulonglong_t val; // constrained field value
583  int n; // byte count/error code
584  int k; // subbyte count/error code
585 
586  // try to set field value
587  if( (n = nmSetU64(pFieldDef, pVal, &val)) != NM_OK )
588  {
589  return n;
590  }
591 
592  // try to pack header
593  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
594  {
595  return n;
596  }
597 
598  // try to pack field value
599  else if( (k = nmPackU64(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
600  {
601  return k;
602  }
603 
604  // success
605  else
606  {
607  n += k;
608 
609  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%llu", val);
610 
611  return n;
612  }
613 }
614 
615 /*!
616  * \brief Pack a signed 64-bit ITV field into the message buffer.
617  *
618  * \copydoc doc_params_pack_fdef
619  * \copydoc doc_return_pack_std
620  */
621 static int nmPackITVS64(const NMFieldDef_T *pFieldDef,
622  void *pVal,
623  byte_t buf[],
624  size_t bufSize,
625  NMEndian_T eEndian,
626  NMCtl_T *pCtl)
627 {
628  long long val; // constrained field value
629  int n; // byte count/error code
630  int k; // subbyte count/error code
631 
632  // try to set field value
633  if( (n = nmSetS64(pFieldDef, pVal, &val)) != NM_OK )
634  {
635  return n;
636  }
637 
638  // try to pack header
639  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
640  {
641  return n;
642  }
643 
644  // try to pack field value
645  else if( (k = nmPackS64(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
646  {
647  return k;
648  }
649 
650  // success
651  else
652  {
653  n += k;
654 
655  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%lld", val);
656 
657  return n;
658  }
659 }
660 
661 /*!
662  * \brief Pack a 32-bit floating-point number ITV field into the message buffer.
663  *
664  * \copydoc doc_params_pack_fdef
665  * \copydoc doc_return_pack_std
666  */
667 static int nmPackITVF32(const NMFieldDef_T *pFieldDef,
668  void *pVal,
669  byte_t buf[],
670  size_t bufSize,
671  NMEndian_T eEndian,
672  NMCtl_T *pCtl)
673 {
674  float val; // constrained field value
675  int n; // byte count/error code
676  int k; // subbyte count/error code
677 
678  // try to set field value
679  if( (n = nmSetF32(pFieldDef, pVal, &val)) != NM_OK )
680  {
681  return n;
682  }
683 
684  // try to pack header
685  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
686  {
687  return n;
688  }
689 
690  // try to pack field value
691  else if( (k = nmPackF32(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
692  {
693  return k;
694  }
695 
696  // success
697  else
698  {
699  n += k;
700 
701  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%f", val);
702 
703  return n;
704  }
705 }
706 
707 /*!
708  * \brief Pack a 64-bit floating-point number ITV field into the message buffer.
709  *
710  * \copydoc doc_params_pack_fdef
711  * \copydoc doc_return_pack_std
712  */
713 static int nmPackITVF64(const NMFieldDef_T *pFieldDef,
714  void *pVal,
715  byte_t buf[],
716  size_t bufSize,
717  NMEndian_T eEndian,
718  NMCtl_T *pCtl)
719 {
720  double val; // constrained field value
721  int n; // byte count/error code
722  int k; // subbyte count/error code
723 
724  // try to set field value
725  if( (n = nmSetF64(pFieldDef, pVal, &val)) != NM_OK )
726  {
727  return n;
728  }
729 
730  // try to pack header
731  else if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
732  {
733  return n;
734  }
735 
736  // try to pack field value
737  else if( (k = nmPackF64(val, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
738  {
739  return k;
740  }
741 
742  // success
743  else
744  {
745  n += k;
746 
747  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%e", val);
748 
749  return n;
750  }
751 }
752 
753 /*!
754  * \brief Pack a 32-bit pointer ITV field into the message buffer.
755  *
756  * \copydoc doc_params_pack_fdef
757  * \copydoc doc_return_pack_std
758  */
759 static int nmPackITVP32(const NMFieldDef_T *pFieldDef,
760  void *pVal,
761  byte_t buf[],
762  size_t bufSize,
763  NMEndian_T eEndian,
764  NMCtl_T *pCtl)
765 {
766  int n; // byte count/error code
767  int k; // subbyte count/error code
768 
769  // try to pack header
770  if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
771  {
772  return n;
773  }
774 
775  // try to pack field value
776  else if( (k = nmPackP32(pVal, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
777  {
778  return k;
779  }
780 
781  // success
782  else
783  {
784  n += k;
785 
786  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
787 
788  return n;
789  }
790 }
791 
792 /*!
793  * \brief Pack a 64-bit pointer ITV field into the message buffer.
794  *
795  * \copydoc doc_params_pack_fdef
796  * \copydoc doc_return_pack_std
797  */
798 static int nmPackITVP64(const NMFieldDef_T *pFieldDef,
799  void *pVal,
800  byte_t buf[],
801  size_t bufSize,
802  NMEndian_T eEndian,
803  NMCtl_T *pCtl)
804 {
805  int n; // byte count/error code
806  int k; // subbyte count/error code
807 
808  // try to pack header
809  if( (n = ITVPACK_SIMPLE_HDR(pFieldDef, buf, bufSize, pCtl)) < 0 )
810  {
811  return n;
812  }
813 
814  // try to pack field value
815  else if( (k = nmPackP64(pVal, &buf[n], bufSize-(size_t)n, eEndian)) < 0 )
816  {
817  return k;
818  }
819 
820  // success
821  else
822  {
823  n += k;
824 
825  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
826 
827  return n;
828  }
829 }
830 
831 /*!
832  * \brief Pack null-terminated, variable length string ITV field into the
833  * message buffer.
834  *
835  * \note The null character is not packed.
836  *
837  * \copydoc doc_params_pack_fdef
838  * \copydoc doc_return_pack_std
839  */
840 static int nmPackITVString(const NMFieldDef_T *pFieldDef,
841  void *pVal,
842  byte_t buf[],
843  size_t bufSize,
844  NMEndian_T eEndian,
845  NMCtl_T *pCtl)
846 {
847  const char *sVal;
848  const char *sConst;
849  size_t uMaxCount;
850  size_t uCount;
851  int n = 0;
852 
853  sVal = (const char *)pVal; // override value pointer type
854  sConst = pFieldDef->m_this.m_string.m_sConst;
855  uMaxCount = pFieldDef->m_this.m_string.m_uMaxCount;
856 
857  if( sConst != NULL )
858  {
859  sVal = sConst;
860  }
861 
862  uCount = strlen(sVal); // string length w/o null
863 
864  // string length exceeds maximum
865  if( uCount > uMaxCount )
866  {
868  "char_count=%zu > max_count=%zu.", uCount, uMaxCount);
869  }
870 
871  // try to pack ITV header
872  if( (n = nmPackITVHdrString(pFieldDef, uCount, buf, bufSize)) < 0 )
873  {
874  return n;
875  }
876 
877  // no more space in buffer for string
878  else if( uCount > bufSize-(size_t)n )
879  {
881  "buf_size=%zu < str_len=%zu.", bufSize, uCount);
882  }
883 
884  // copy string field value
885  else
886  {
887  memcpy(&buf[n], sVal, uCount);
888 
889  n += (int)uCount;
890 
891  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "'%s'", sVal);
892 
893  return n;
894  }
895 }
896 
897 /*!
898  * \brief Pack a structure ITV field into the message buffer.
899  *
900  * \copydoc doc_params_pack_fdef
901  * \copydoc doc_return_pack_std
902  */
903 static int nmPackITVStruct(const NMFieldDef_T *pFieldDef,
904  void *pVal,
905  byte_t buf[],
906  size_t bufSize,
907  NMEndian_T eEndian,
908  NMCtl_T *pCtl)
909 {
910  const NMMsgDef_T *pStructDef;
911  int n = 0;
912  int k;
913 
914  pStructDef = pFieldDef->m_this.m_struct;
915 
916  // try to pack ITV header
917  if( (n = nmPackITVHdrStruct(pFieldDef, buf, bufSize)) < 0 )
918  {
919  return n;
920  }
921 
922  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "structdef %s, member_count=%zu",
923  pStructDef->m_sMsgName, pStructDef->m_uCount);
924 
925  pCtl->m_uDepth++;
926 
927  // copy struct field value
928  k = nmPackITVStream(pStructDef, pVal, &buf[n], bufSize-(size_t)n, eEndian,
929  pCtl);
930 
931  pCtl->m_uDepth--;
932 
933  return k>=0? n+k: k;
934 }
935 
936 /*!
937  * \brief Pack variable length vector ITV field into the message buffer.
938  *
939  * A vector is a one-dimension array of the given type.
940  *
941  * \copydoc doc_params_pack_fdef
942  * \copydoc doc_return_pack_std
943  */
944 static int nmPackITVVector(const NMFieldDef_T *pFieldDef,
945  void *pVal,
946  byte_t buf[],
947  size_t bufSize,
948  NMEndian_T eEndian,
949  NMCtl_T *pCtl)
950 {
951  size_t uMaxCount;
952  size_t uElemSize;
953  const NMFieldDef_T *pElemDef;
954  NMVec_T *pVec;
955  size_t uCount;
956  byte_t *pItem;
957  NMPackFunc_T fnPack = NULL;
958  int n = 0;
959  int k;
960  size_t i;
961 
962  uMaxCount = pFieldDef->m_this.m_vector.m_uMaxCount;
963  uElemSize = pFieldDef->m_this.m_vector.m_uElemSize;
964  pElemDef = pFieldDef->m_this.m_vector.m_pThisElem;
965  pVec = (NMVec_T *)pVal; // generalized vector overlay
966  uCount = pVec->m_uCount; // number of vector items
967  pItem = (byte_t *)(pVec) + memberoffset(NMVec_T, u.m_buf);
968  fnPack = nmLookupITVPacker(pElemDef->m_eFType);
969 
970  if( fnPack == NULL )
971  {
973  "vector_elem_ftype='%c'(0x%02x)",
974  NMLIB_ASCII_FTYPE(pElemDef->m_eFType), pElemDef->m_eFType);
975  }
976 
977  // exceeds maximum
978  else if( uCount > uMaxCount )
979  {
981  "vector_count=%zu > max_count=%zu.", uCount, uMaxCount);
982  }
983 
984  // try to pack ITV header
985  else if( (n = nmPackITVHdrVector(pFieldDef, uCount, buf, bufSize)) < 0 )
986  {
987  return n;
988  }
989 
990  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%c:vector[%zu]",
991  pElemDef->m_eFType, uCount);
992 
993  // no header for simple vector element types
994  if( NMFTYPE_IS_SIMPLE(pElemDef->m_eFType) )
995  {
996  pCtl->m_bNoHdr = true;
997  }
998 
999  pCtl->m_uDepth++;
1000 
1001  // copy vector field value
1002  for(i=0; i<uCount; ++i)
1003  {
1004  k = fnPack(pElemDef, pItem, &buf[n], bufSize-(size_t)n, eEndian, pCtl);
1005 
1006  if( k < 0 )
1007  {
1008  return k;
1009  }
1010 
1011  n += k;
1012 
1013  pItem += uElemSize;
1014  }
1015 
1016  pCtl->m_uDepth--;
1017  pCtl->m_bNoHdr = false;
1018 
1019  return n;
1020 }
1021 
1022 /*!
1023  * \brief Pack a ITV message.
1024  *
1025  * \param pMsgDef Pointer to message definition.
1026  * \param [in] pStruct Pointer to the associated, populated message
1027  * structure.
1028  * \param [out] buf Output message buffer.
1029  * \param bufSize Size of output buffer.
1030  * \param eEndian Packing order. See \ref NMEndian_T.
1031  * \param pCtl Pointer to Internal control.
1032  *
1033  * \copydoc doc_return_pack_std
1034  */
1035 static int nmPackITVStream(const NMMsgDef_T *pMsgDef,
1036  void *pStruct,
1037  byte_t buf[],
1038  size_t bufSize,
1039  NMEndian_T eEndian,
1040  NMCtl_T *pCtl)
1041 {
1042  size_t uFieldNum;
1043  const NMFieldDef_T *pFieldDef;
1044  NMPackFunc_T fnPack = NULL;
1045  void *pVal;
1046  int n = 0;
1047  int k;
1048 
1049  //
1050  // Pack message fields
1051  //
1052  for(uFieldNum=0, pFieldDef=pMsgDef->m_pFields;
1053  uFieldNum < pMsgDef->m_uCount;
1054  ++uFieldNum, ++pFieldDef)
1055  {
1056  if( n < bufSize )
1057  {
1058  if( pFieldDef->m_eFType == NMFTypePad )
1059  {
1060  pVal = NULL;
1061  }
1062 
1063  else
1064  {
1065  pVal = pStruct + pFieldDef->m_uOffset;
1066  }
1067 
1068  fnPack = nmLookupITVPacker(pFieldDef->m_eFType);
1069 
1070  if( fnPack == NULL )
1071  {
1073  "ftype='%c'(0x%02x).",
1074  NMLIB_ASCII_FTYPE(pFieldDef->m_eFType), pFieldDef->m_eFType);
1075  }
1076 
1077  k = fnPack(pFieldDef, pVal, &buf[n], bufSize-(size_t)n, eEndian, pCtl);
1078 
1079  if( k < 0 )
1080  {
1081  return k;
1082  }
1083  }
1084 
1085  else
1086  {
1088  "buf_size=%zu, msgid=%u", bufSize, pMsgDef->m_eMsgId);
1089  }
1090 
1091  n += k;
1092  }
1093 
1094  return n;
1095 }
1096 
1097 
1098 // ...........................................................................
1099 // Private Unpacking Interface
1100 // ...........................................................................
1101 
1102 /*!
1103  * \brief Move parse cursor position past current field in message stream field.
1104  *
1105  * No unpacking field into an output variable is executed.
1106  *
1107  * \param pFieldDef Pointer to message field definition.
1108  * \param [in] buf Input message buffer.
1109  * \param bufSize Size of input buffer.
1110  * \param uFLen Length of field (bytes).
1111  * \param pCtl Pointer to Internal control.
1112  *
1113  * \copydoc doc_return_unpack_std
1114  */
1115 static int nmUnpackITVNoExec(const NMFieldDef_T *pFieldDef,
1116  byte_t buf[],
1117  size_t bufSize,
1118  size_t uFLen,
1119  NMCtl_T *pCtl)
1120 {
1121  if( uFLen > bufSize )
1122  {
1124  "buf_size=%zu < flen=%zu", bufSize, uFLen);
1125  }
1126 
1127  NMLIB_TRACE_FIELD(pFieldDef, buf, uFLen, pCtl, "ignore");
1128 
1129  return (int)uFLen;
1130 }
1131 
1132 /*!
1133  * \brief Unpack pad byte from the message buffer.
1134  *
1135  * \copydoc doc_params_unpack_fdef
1136  * \copydoc doc_return_unpack_std
1137  */
1138 static int nmUnpackITVPad(const NMFieldDef_T *pFieldDef,
1139  byte_t buf[],
1140  size_t bufSize,
1141  void *pVal,
1142  NMEndian_T eEndian,
1143  NMCtl_T *pCtl)
1144 {
1145  int n = 0;
1146 
1147  // skip over all pad bytes
1148  while( (buf[n] == NMFVAL_PAD) && (n < bufSize) )
1149  {
1150  ++n;
1151  }
1152 
1153  NMLIB_TRACE_FIELD(NULL, buf, n, pCtl, "pad");
1154 
1155  return n;
1156 }
1157 
1158 /*!
1159  * \brief Unpack an unsigned 8-bit boolean ITV field from the message buffer.
1160  *
1161  * \copydoc doc_params_unpack_fdef
1162  * \copydoc doc_return_unpack_std
1163  */
1164 static int nmUnpackITVBool(const NMFieldDef_T *pFieldDef,
1165  byte_t buf[],
1166  size_t bufSize,
1167  void *pVal,
1168  NMEndian_T eEndian,
1169  NMCtl_T *pCtl)
1170 {
1171  int n; // byte count/error code
1172  int k; // subbyte count/error code
1173 
1174  // header size
1175  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1176 
1177  // not enough input buffer for header
1178  if( n > bufSize )
1179  {
1181  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1182  }
1183 
1184  // ignore this field
1185  else if( pCtl->m_bNoExec )
1186  {
1187  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_U8,
1188  pCtl);
1189  }
1190 
1191  // try to unpack value
1192  else if( (k = nmUnpackBool(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1193  {
1194  return k;
1195  }
1196 
1197  // success
1198  else
1199  {
1200  n += k;
1201 
1202  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%s",
1203  (*((bool_t *)pVal)? "true": "false"));
1204 
1205  return n;
1206  }
1207 }
1208 
1209 /*!
1210  * \brief Unpack an unsigned 8-bit ITV field from the message buffer.
1211  *
1212  * \copydoc doc_params_unpack_fdef
1213  * \copydoc doc_return_unpack_std
1214  */
1215 static int nmUnpackITVU8(const NMFieldDef_T *pFieldDef,
1216  byte_t buf[],
1217  size_t bufSize,
1218  void *pVal,
1219  NMEndian_T eEndian,
1220  NMCtl_T *pCtl)
1221 {
1222  int n; // byte count/error code
1223  int k; // subbyte count/error code
1224 
1225  // header size
1226  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1227 
1228  // not enough input buffer for header
1229  if( n > bufSize )
1230  {
1232  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1233  }
1234 
1235  // ignore this field
1236  else if( pCtl->m_bNoExec )
1237  {
1238  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_U8,
1239  pCtl);
1240  }
1241 
1242  // try to unpack value
1243  else if( (k = nmUnpackU8(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1244  {
1245  return k;
1246  }
1247 
1248  // success
1249  else
1250  {
1251  n += k;
1252 
1253  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhu", *((byte_t *)pVal));
1254 
1255  return n;
1256  }
1257 }
1258 
1259 /*!
1260  * \brief Unpack a signed 8-bit ITV field from the message buffer.
1261  *
1262  * \copydoc doc_params_unpack_fdef
1263  * \copydoc doc_return_unpack_std
1264  */
1265 static int nmUnpackITVS8(const NMFieldDef_T *pFieldDef,
1266  byte_t buf[],
1267  size_t bufSize,
1268  void *pVal,
1269  NMEndian_T eEndian,
1270  NMCtl_T *pCtl)
1271 {
1272  int n; // byte count/error code
1273  int k; // subbyte count/error code
1274 
1275  // header size
1276  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1277 
1278  // not enough input buffer for header
1279  if( n > bufSize )
1280  {
1282  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1283  }
1284 
1285  // ignore this field
1286  else if( pCtl->m_bNoExec )
1287  {
1288  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_S8,
1289  pCtl);
1290  }
1291 
1292  // try to unpack value
1293  else if( (k = nmUnpackS8(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1294  {
1295  return k;
1296  }
1297 
1298  // success
1299  else
1300  {
1301  n += k;
1302 
1303  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hhd",
1304  *((signed char *)pVal));
1305 
1306  return n;
1307  }
1308 }
1309 
1310 /*!
1311  * \brief Unpack an unsigned 16-bit ITV field from the message buffer.
1312  *
1313  * \copydoc doc_params_unpack_fdef
1314  * \copydoc doc_return_unpack_std
1315  */
1316 static int nmUnpackITVU16(const NMFieldDef_T *pFieldDef,
1317  byte_t buf[],
1318  size_t bufSize,
1319  void *pVal,
1320  NMEndian_T eEndian,
1321  NMCtl_T *pCtl)
1322 {
1323  int n; // byte count/error code
1324  int k; // subbyte count/error code
1325 
1326  // header size
1327  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1328 
1329  // not enough input buffer for header
1330  if( n > bufSize )
1331  {
1333  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1334  }
1335 
1336  // ignore this field
1337  else if( pCtl->m_bNoExec )
1338  {
1339  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_U16,
1340  pCtl);
1341  }
1342 
1343  // try to unpack value
1344  else if( (k = nmUnpackU16(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1345  {
1346  return k;
1347  }
1348 
1349  // success
1350  else
1351  {
1352  n += k;
1353 
1354  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hu", *((ushort_t *)pVal));
1355 
1356  return n;
1357  }
1358 }
1359 
1360 /*!
1361  * \brief Unpack a signed 16-bit ITV field from the message buffer.
1362  *
1363  * \copydoc doc_params_unpack_fdef
1364  * \copydoc doc_return_unpack_std
1365  */
1366 static int nmUnpackITVS16(const NMFieldDef_T *pFieldDef,
1367  byte_t buf[],
1368  size_t bufSize,
1369  void *pVal,
1370  NMEndian_T eEndian,
1371  NMCtl_T *pCtl)
1372 {
1373  int n; // byte count/error code
1374  int k; // subbyte count/error code
1375 
1376  // header size
1377  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1378 
1379  // not enough input buffer for header
1380  if( n > bufSize )
1381  {
1383  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1384  }
1385 
1386  // ignore this field
1387  else if( pCtl->m_bNoExec )
1388  {
1389  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_S16,
1390  pCtl);
1391  }
1392 
1393  // try to unpack value
1394  else if( (k = nmUnpackS16(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1395  {
1396  return k;
1397  }
1398 
1399  // success
1400  else
1401  {
1402  n += k;
1403 
1404  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%hd", *((short *)pVal));
1405 
1406  return n;
1407  }
1408 }
1409 
1410 /*!
1411  * \brief Unpack an unsigned 32-bit ITV field from the message buffer.
1412  *
1413  * \copydoc doc_params_unpack_fdef
1414  * \copydoc doc_return_unpack_std
1415  */
1416 static int nmUnpackITVU32(const NMFieldDef_T *pFieldDef,
1417  byte_t buf[],
1418  size_t bufSize,
1419  void *pVal,
1420  NMEndian_T eEndian,
1421  NMCtl_T *pCtl)
1422 {
1423  int n; // byte count/error code
1424  int k; // subbyte count/error code
1425 
1426  // header size
1427  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1428 
1429  // not enough input buffer for header
1430  if( n > bufSize )
1431  {
1433  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1434  }
1435 
1436  // ignore this field
1437  else if( pCtl->m_bNoExec )
1438  {
1439  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_U32,
1440  pCtl);
1441  }
1442 
1443  // try to unpack value
1444  else if( (k = nmUnpackU32(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1445  {
1446  return k;
1447  }
1448 
1449  // success
1450  else
1451  {
1452  n += k;
1453 
1454  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%u", *((uint_t *)pVal));
1455 
1456  return n;
1457  }
1458 }
1459 
1460 /*!
1461  * \brief Unpack a signed 32-bit ITV field from the message buffer.
1462  *
1463  * \copydoc doc_params_unpack_fdef
1464  * \copydoc doc_return_unpack_std
1465  */
1466 static int nmUnpackITVS32(const NMFieldDef_T *pFieldDef,
1467  byte_t buf[],
1468  size_t bufSize,
1469  void *pVal,
1470  NMEndian_T eEndian,
1471  NMCtl_T *pCtl)
1472 {
1473  int n; // byte count/error code
1474  int k; // subbyte count/error code
1475 
1476  // header size
1477  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1478 
1479  // not enough input buffer for header
1480  if( n > bufSize )
1481  {
1483  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1484  }
1485 
1486  // ignore this field
1487  else if( pCtl->m_bNoExec )
1488  {
1489  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_S32,
1490  pCtl);
1491  }
1492 
1493  // try to unpack value
1494  else if( (k = nmUnpackS32(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1495  {
1496  return k;
1497  }
1498 
1499  // success
1500  else
1501  {
1502  n += k;
1503 
1504  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%d", *((int *)pVal));
1505 
1506  return n;
1507  }
1508 }
1509 
1510 /*!
1511  * \brief Unpack an unsigned 64-bit ITV field from the message buffer.
1512  *
1513  * \copydoc doc_params_unpack_fdef
1514  * \copydoc doc_return_unpack_std
1515  */
1516 static int nmUnpackITVU64(const NMFieldDef_T *pFieldDef,
1517  byte_t buf[],
1518  size_t bufSize,
1519  void *pVal,
1520  NMEndian_T eEndian,
1521  NMCtl_T *pCtl)
1522 {
1523  int n; // byte count/error code
1524  int k; // subbyte count/error code
1525 
1526  // header size
1527  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1528 
1529  // not enough input buffer for header
1530  if( n > bufSize )
1531  {
1533  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1534  }
1535 
1536  // ignore this field
1537  else if( pCtl->m_bNoExec )
1538  {
1539  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_U64,
1540  pCtl);
1541  }
1542 
1543  // try to unpack value
1544  else if( (k = nmUnpackU64(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1545  {
1546  return k;
1547  }
1548 
1549  // success
1550  else
1551  {
1552  n += k;
1553 
1554  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%llu",
1555  *((ulonglong_t *)pVal));
1556 
1557  return n;
1558  }
1559 }
1560 
1561 /*!
1562  * \brief Unpack a signed 64-bit ITV field from the message buffer.
1563  *
1564  * \copydoc doc_params_unpack_fdef
1565  * \copydoc doc_return_unpack_std
1566  */
1567 static int nmUnpackITVS64(const NMFieldDef_T *pFieldDef,
1568  byte_t buf[],
1569  size_t bufSize,
1570  void *pVal,
1571  NMEndian_T eEndian,
1572  NMCtl_T *pCtl)
1573 {
1574  int n; // byte count/error code
1575  int k; // subbyte count/error code
1576 
1577  // header size
1578  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1579 
1580  // not enough input buffer for header
1581  if( n > bufSize )
1582  {
1584  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1585  }
1586 
1587  // ignore this field
1588  else if( pCtl->m_bNoExec )
1589  {
1590  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_S64,
1591  pCtl);
1592  }
1593 
1594  // try to unpack value
1595  else if( (k = nmUnpackS64(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1596  {
1597  return k;
1598  }
1599 
1600  // success
1601  else
1602  {
1603  n += k;
1604 
1605  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%lld", *((long long *)pVal));
1606 
1607  return n;
1608  }
1609 }
1610 
1611 /*!
1612  * \brief Unpack a 32-bit floating-point number ITV field from the message
1613  * buffer.
1614  *
1615  * \copydoc doc_params_unpack_fdef
1616  * \copydoc doc_return_unpack_std
1617  */
1618 static int nmUnpackITVF32(const NMFieldDef_T *pFieldDef,
1619  byte_t buf[],
1620  size_t bufSize,
1621  void *pVal,
1622  NMEndian_T eEndian,
1623  NMCtl_T *pCtl)
1624 {
1625  int n; // byte count/error code
1626  int k; // subbyte count/error code
1627 
1628  // header size
1629  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1630 
1631  // not enough input buffer for header
1632  if( n > bufSize )
1633  {
1635  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1636  }
1637 
1638  // ignore this field
1639  else if( pCtl->m_bNoExec )
1640  {
1641  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_F32,
1642  pCtl);
1643  }
1644 
1645  // try to unpack value
1646  else if( (k = nmUnpackF32(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1647  {
1648  return k;
1649  }
1650 
1651  // success
1652  else
1653  {
1654  n += k;
1655 
1656  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%f", *((float *)pVal));
1657 
1658  return n;
1659  }
1660 }
1661 
1662 /*!
1663  * \brief Unpack a 64-bit floating-point number ITV field from the message
1664  * buffer.
1665  *
1666  * \copydoc doc_params_unpack_fdef
1667  * \copydoc doc_return_unpack_std
1668  */
1669 static int nmUnpackITVF64(const NMFieldDef_T *pFieldDef,
1670  byte_t buf[],
1671  size_t bufSize,
1672  void *pVal,
1673  NMEndian_T eEndian,
1674  NMCtl_T *pCtl)
1675 {
1676  int n; // byte count/error code
1677  int k; // subbyte count/error code
1678 
1679  // header size
1680  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1681 
1682  // not enough input buffer for header
1683  if( n > bufSize )
1684  {
1686  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1687  }
1688 
1689  // ignore this field
1690  else if( pCtl->m_bNoExec )
1691  {
1692  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_F64,
1693  pCtl);
1694  }
1695 
1696  // try to unpack value
1697  else if( (k = nmUnpackF64(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1698  {
1699  return k;
1700  }
1701 
1702  // success
1703  else
1704  {
1705  n += k;
1706 
1707  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%e", *((double *)pVal));
1708 
1709  return n;
1710  }
1711 }
1712 
1713 /*!
1714  * \brief Unpack a 32-bit pointer ITV field from the message buffer.
1715  *
1716  * \copydoc doc_params_unpack_fdef
1717  * \copydoc doc_return_unpack_std
1718  */
1719 static int nmUnpackITVP32(const NMFieldDef_T *pFieldDef,
1720  byte_t buf[],
1721  size_t bufSize,
1722  void *pVal,
1723  NMEndian_T eEndian,
1724  NMCtl_T *pCtl)
1725 {
1726  int n; // byte count/error code
1727  int k; // subbyte count/error code
1728 
1729  // header size
1730  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1731 
1732  // not enough input buffer for header
1733  if( n > bufSize )
1734  {
1736  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1737  }
1738 
1739  // ignore this field
1740  else if( pCtl->m_bNoExec )
1741  {
1742  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_P32,
1743  pCtl);
1744  }
1745 
1746  // try to unpack value
1747  else if( (k = nmUnpackP32(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1748  {
1749  return k;
1750  }
1751 
1752  // success
1753  else
1754  {
1755  n += k;
1756 
1757  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
1758 
1759  return n;
1760  }
1761 }
1762 
1763 /*!
1764  * \brief Unpack a 64-bit pointer ITV field from the message buffer.
1765  *
1766  * \copydoc doc_params_unpack_fdef
1767  * \copydoc doc_return_unpack_std
1768  */
1769 static int nmUnpackITVP64(const NMFieldDef_T *pFieldDef,
1770  byte_t buf[],
1771  size_t bufSize,
1772  void *pVal,
1773  NMEndian_T eEndian,
1774  NMCtl_T *pCtl)
1775 {
1776  int n; // byte count/error code
1777  int k; // subbyte count/error code
1778 
1779  // header size
1780  n = pCtl->m_bNoHdr? 0: NMITV_FHDR_SIZE_SIMPLE;
1781 
1782  // not enough input buffer for header
1783  if( n > bufSize )
1784  {
1786  "buf_size=%zu < fhdr_size=%u", bufSize, n);
1787  }
1788 
1789  // ignore this field
1790  else if( pCtl->m_bNoExec )
1791  {
1792  return nmUnpackITVNoExec(pFieldDef, buf, bufSize, (size_t)n+NMFVAL_LEN_P64,
1793  pCtl);
1794  }
1795 
1796  // try to unpack value
1797  else if( (k = nmUnpackP64(&buf[n], bufSize-(size_t)n, pVal, eEndian)) < 0 )
1798  {
1799  return k;
1800  }
1801 
1802  // success
1803  else
1804  {
1805  n += k;
1806 
1807  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "%p", *((ulong_t *)pVal));
1808 
1809  return n;
1810  }
1811 }
1812 
1813 /*!
1814  * \brief Unpack variable length string ITV field from the message buffer.
1815  *
1816  * \note The null character is appended to the end of the unpacked value.
1817  *
1818  * \copydoc doc_params_unpack_fdef
1819  * \copydoc doc_return_unpack_std
1820  */
1821 static int nmUnpackITVString(const NMFieldDef_T *pFieldDef,
1822  byte_t buf[],
1823  size_t bufSize,
1824  void *pVal,
1825  NMEndian_T eEndian,
1826  NMCtl_T *pCtl)
1827 {
1828  size_t uCount;
1829  size_t uMaxCount;
1830  size_t uFSize;
1831  char *sVal;
1832  int n;
1833 
1835 
1836  if( n > bufSize )
1837  {
1839  "buf_size=%zu, fhdr_size=%u", bufSize, n);
1840  }
1841 
1842  // string subheader
1843  uCount = (size_t)buf[2];
1844 
1845  // field definition and derived values
1846  uMaxCount = pFieldDef->m_this.m_string.m_uMaxCount;
1847  uFSize = (size_t)n + uCount;
1848  sVal = (char *)pVal;
1849 
1850  // exceeds maximum string length (sans null)
1851  if( uCount > uMaxCount )
1852  {
1854  "string_count=%zu > max_count=%zu.", uCount, uMaxCount);
1855  }
1856 
1857  // not enough space in buffer for string
1858  else if( uFSize > bufSize )
1859  {
1861  "buf_size=%zu < fsize=%zu", bufSize, uFSize);
1862  }
1863 
1864  // success
1865  else
1866  {
1867  memcpy(sVal, buf+n, uCount);
1868  sVal[uCount] = 0;
1869 
1870  NMLIB_TRACE_FIELD(pFieldDef, buf, uFSize, pCtl, "'%s'", sVal);
1871 
1872  return (int)uFSize;
1873  }
1874 }
1875 
1876 
1877 /*!
1878  * \brief Unpack structure ITV field from the message buffer.
1879  *
1880  * \copydoc doc_params_unpack_fdef
1881  * \copydoc doc_return_unpack_std
1882  */
1883 static int nmUnpackITVStruct(const NMFieldDef_T *pFieldDef,
1884  byte_t buf[],
1885  size_t bufSize,
1886  void *pVal,
1887  NMEndian_T eEndian,
1888  NMCtl_T *pCtl)
1889 {
1890  const NMMsgDef_T *pStructDef; // structure definition
1891  size_t uCount; // struct field count
1892  int n; // byte count/error code
1893  int k; // subbyte count/error code
1894 
1896 
1897  if( n > bufSize )
1898  {
1900  "buf_size=%zu, fhdr_size=%u", bufSize, n);
1901  }
1902 
1903  // number of fields in struct
1904  uCount = (size_t)buf[2]; // fix
1905 
1906  pStructDef = pFieldDef->m_this.m_struct;
1907 
1908  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl, "structdef %s, member_count=%u",
1909  pStructDef->m_sMsgName, buf[2]); //pStructDef->m_uCount);
1910 
1911  pCtl->m_uDepth++;
1912 
1913  // copy struct field value
1914  k = nmUnpackITVStream(pStructDef, &buf[n], bufSize-(size_t)n, uCount,
1915  pVal, eEndian, pCtl);
1916 
1917  pCtl->m_uDepth--;
1918 
1919  return k>=0? n+k: k;
1920 }
1921 
1922 /*!
1923  * \brief Unpack variable length vector ITV field from the message buffer.
1924  *
1925  * A vector is a one-dimension array of the given type.
1926  *
1927  * \copydoc doc_params_unpack_fdef
1928  * \copydoc doc_return_unpack_std
1929  */
1930 static int nmUnpackITVVector(const NMFieldDef_T *pFieldDef,
1931  byte_t buf[],
1932  size_t bufSize,
1933  void *pVal,
1934  NMEndian_T eEndian,
1935  NMCtl_T *pCtl)
1936 {
1937  size_t uCount;
1938  byte_t byElemFType;
1939  size_t uMaxCount;
1940  size_t uElemSize;
1941  const NMFieldDef_T *pElemDef;
1942  NMVec_T *pVec;
1943  void *pItem;
1944  NMUnpackFunc_T fnUnpack = NULL;
1945  int n = NMITV_FHDR_SIZE_VECTOR;
1946  int k;
1947  size_t i;
1948 
1950 
1951  if( n > bufSize )
1952  {
1954  "buf_size=%zu, fhdr_size=%u", bufSize, n);
1955  }
1956 
1957  // vector subheader
1958  uCount = (size_t)buf[2];
1959  byElemFType = (byte_t)buf[3];
1960 
1961  // field definition and derived values
1962  uMaxCount = pFieldDef->m_this.m_vector.m_uMaxCount;
1963  uElemSize = pFieldDef->m_this.m_vector.m_uElemSize;
1964  pElemDef = pFieldDef->m_this.m_vector.m_pThisElem;
1965  pVec = (NMVec_T *)pVal; // generalized vector overlay
1966  pItem = (byte_t *)(pVec) + memberoffset(NMVec_T, u.m_buf);
1967  fnUnpack = nmLookupITVUnpacker(pElemDef->m_eFType);
1968 
1969  // received vector type mismatch with definition
1970  if( byElemFType != (byte_t)pElemDef->m_eFType )
1971  {
1973  "vector_elem_ftype='%c'(0x%02x) != rcv'd ftype='%c'(0x%02x).",
1974  NMLIB_ASCII_FTYPE(pElemDef->m_eFType), pElemDef->m_eFType,
1975  NMLIB_ASCII_FTYPE(byElemFType), byElemFType);
1976  }
1977 
1978  // exceeds maximum
1979  else if( uCount > uMaxCount )
1980  {
1982  "vector_count=%zu > max_count=%zu.", uCount, uMaxCount);
1983  }
1984 
1985  // no unpacker
1986  else if( fnUnpack == NULL )
1987  {
1989  "vector_elem_ftype='%c'(0x%02x).",
1990  NMLIB_ASCII_FTYPE(pElemDef->m_eFType), pElemDef->m_eFType);
1991  }
1992 
1993  NMLIB_TRACE_FIELD(pFieldDef, buf, n, pCtl,
1994  "vector_count=%zu, vector_elem_ftype='%c'(0x%02x)",
1995  uCount, NMLIB_ASCII_FTYPE(byElemFType), byElemFType);
1996 
1997  // no header for simple vector element types
1998  if( NMFTYPE_IS_SIMPLE(pElemDef->m_eFType) )
1999  {
2000  pCtl->m_bNoHdr = true;
2001  }
2002 
2003  pCtl->m_uDepth++;
2004 
2005  // unpack field into vector field
2006  for(i=0; i<uCount; ++i)
2007  {
2008  k = fnUnpack(pElemDef, &buf[n], bufSize-(size_t)n, pItem, eEndian, pCtl);
2009 
2010  if( k < 0 )
2011  {
2012  return k;
2013  }
2014 
2015  n += k;
2016 
2017  pItem += uElemSize;
2018  }
2019 
2020  pCtl->m_uDepth--;
2021  pCtl->m_bNoHdr = false;
2022 
2023  // actual number of vector items
2024  pVec->m_uCount = n>0? uCount: 0;
2025 
2026  return n;
2027 }
2028 
2029 /*!
2030  * \brief Unpack an ITV byte stream.
2031  *
2032  * \param pMsgDef Pointer to message definition.
2033  * \param [in] buf Input message buffer.
2034  * \param uMsgLen Length of message (bytes) in input buffer.
2035  * \param [out] pStruct Pointer to the associated message
2036  * structure to populate.
2037  * \param uCount Received message/struct field count
2038  * \param eEndian Unpacking order. See \ref NMEndian_T.
2039  * \param pCtl Pointer to Internal control.
2040  *
2041  * \copydoc doc_return_unpack_std
2042  */
2043 static int nmUnpackITVStream(const NMMsgDef_T *pMsgDef,
2044  byte_t buf[],
2045  size_t uMsgLen,
2046  size_t uCount,
2047  void *pStruct,
2048  NMEndian_T eEndian,
2049  NMCtl_T *pCtl)
2050 {
2051  const NMFieldDef_T *pFieldDef;
2052  NMUnpackFunc_T fnUnpack = NULL;
2053  byte_t bNoExec;
2054  byte_t byFId;
2055  byte_t byFType;
2056  void *pVal;
2057  int n = 0;
2058  int k;
2059 
2060  bNoExec = pCtl->m_bNoExec;
2061 
2062  while( (uCount > 0) && (n+NMITV_FID_SIZE < uMsgLen) )
2063  {
2064  byFId = buf[n]; // field id
2065 
2066  // Padding (reserved packed id)
2067  if( byFId == NMFTypePadTr )
2068  {
2069  byFType = (byte_t)NMFTypePad; // internal pad field type
2070  pFieldDef = NULL;
2071  pVal = NULL;
2072  }
2073 
2074  // ITV field
2075  else
2076  {
2077  if( n+NMITV_FHDR_SIZE_BASE >= uMsgLen )
2078  {
2080  "msg_len=%zu, msg_id=%u", uMsgLen, pMsgDef->m_eMsgId);
2081  }
2082 
2083  byFType = buf[n+1]; // field type
2084 
2085  if( (pFieldDef = nmFindFieldDef(pMsgDef, byFId)) == NULL )
2086  {
2087  pCtl->m_bNoExec = true;
2088  pVal = NULL;
2089  NMLIB_WARNING("Unknown fid=%u @byte=%d - ignoring.", (uint_t)byFId, n);
2090  }
2091  else if( pFieldDef->m_eFType != (NMFType_T)byFType )
2092  {
2094  "Field definition ftype='%c'(0x%02x) != receive ftype='%c'(0x%02x).",
2095  NMLIB_ASCII_FTYPE(pFieldDef->m_eFType), pFieldDef->m_eFType,
2096  NMLIB_ASCII_FTYPE(byFType), byFType);
2097  }
2098 
2099  pVal = pStruct + pFieldDef->m_uOffset;
2100  }
2101 
2102  fnUnpack = nmLookupITVUnpacker(byFType);
2103 
2104  if( fnUnpack == NULL )
2105  {
2107  "ftype='%c'(0x%02x).",
2108  NMLIB_ASCII_FTYPE(pFieldDef->m_eFType), pFieldDef->m_eFType);
2109  }
2110 
2111  k = fnUnpack(pFieldDef, &buf[n], uMsgLen-(size_t)n, pVal, eEndian, pCtl);
2112 
2113  if( k < 0 )
2114  {
2115  return k;
2116  }
2117 
2118  n += k;
2119 
2120  pCtl->m_bNoExec = bNoExec;
2121 
2122  uCount--;
2123  }
2124 
2125  if( uCount > 0 )
2126  {
2128  "%s(%u): %u field(s) left unparsed - no more message",
2129  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, uCount);
2130  }
2131 
2132  return n;
2133 }
2134 
2135 
2136 // ...........................................................................
2137 // Private Support Functions
2138 // ...........................................................................
2139 
2140 /*!
2141  * ITV Info Lookup Table
2142  *
2143  * \warning Keep in asending order by ftype.
2144  */
2146 {
2147  {NMFTypeBool, nmPackITVBool, nmUnpackITVBool}, // [0] '?'
2148  {NMFTypeU8, nmPackITVU8, nmUnpackITVU8}, // [1] 'B'
2149  {NMFTypeF64, nmPackITVF64, nmUnpackITVF64}, // [2] 'F'
2150  {NMFTypeU16, nmPackITVU16, nmUnpackITVU16}, // [3] 'H'
2151  {NMFTypeU32, nmPackITVU32, nmUnpackITVU32}, // [4] 'I'
2152  {NMFTypeP64, nmPackITVP64, nmUnpackITVP64}, // [5] 'P'
2153  {NMFTypeU64, nmPackITVU64, nmUnpackITVU64}, // [6] 'Q'
2155  {NMFTypeS8, nmPackITVS8, nmUnpackITVS8}, // [8] 'b'
2156  {NMFTypeChar, nmPackITVU8, nmUnpackITVU8}, // [9] 'c'
2157  {NMFTypeF32, nmPackITVF32, nmUnpackITVF32}, // [10] 'f'
2158  {NMFTypeS16, nmPackITVS16, nmUnpackITVS16}, // [11] 'h'
2159  {NMFTypeS32, nmPackITVS32, nmUnpackITVS32}, // [12] 'i'
2160  {NMFTypeP32, nmPackITVP32, nmUnpackITVP32}, // [13] 'p'
2161  {NMFTypeS64, nmPackITVS64, nmUnpackITVS64}, // [14] 'q'
2163  {NMFTypePad, nmPackITVPad, nmUnpackITVPad}, // [16] 'x'
2165 };
2166 
2167 /*!
2168  * \brief Lookup ITV packer function, given the message field type.
2169  *
2170  * \param eFType Message field type.
2171  *
2172  * \return Returns packer function on success, NULL on failure.
2173  */
2175 {
2176  int idx;
2177 
2178  idx = NMHashFType(eFType);
2179 
2180  if( (idx != NMHashNoIdx) && (idx < arraysize(NMITVLookupTbl)) )
2181  {
2182  if( NMITVLookupTbl[idx].m_eFType == eFType )
2183  {
2184  return NMITVLookupTbl[idx].m_fnPack;
2185  }
2186  else
2187  {
2189  "hashed eFtype='%c'(0x%02x) != tbl[%d].m_eFType='%c'(0x%02x)",
2190  NMLIB_ASCII_FTYPE(eFType), eFType,
2191  idx, NMLIB_ASCII_FTYPE(NMITVLookupTbl[idx].m_eFType),
2192  NMITVLookupTbl[idx].m_eFType);
2193  return NULL;
2194  }
2195  }
2196  else
2197  {
2198  return NULL;
2199  }
2200 }
2201 
2202 /*!
2203  * \brief Lookup ITV unpacker function, given the message field type.
2204  *
2205  * \param eFType Message field type.
2206  *
2207  * \return Returns unpacker function on success, NULL on failure.
2208  */
2210 {
2211  int idx;
2212 
2213  idx = NMHashFType(eFType);
2214 
2215  if( (idx != NMHashNoIdx) && (idx < arraysize(NMITVLookupTbl)) )
2216  {
2217  if( NMITVLookupTbl[idx].m_eFType == eFType )
2218  {
2219  return NMITVLookupTbl[idx].m_fnUnpack;
2220  }
2221  else
2222  {
2224  "hashed eFtype='%c'(0x%02x) != tbl[%d].m_eFType='%c'(0x%02x)",
2225  NMLIB_ASCII_FTYPE(eFType), eFType,
2226  idx, NMLIB_ASCII_FTYPE(NMITVLookupTbl[idx].m_eFType),
2227  NMITVLookupTbl[idx].m_eFType);
2228  return NULL;
2229  }
2230  }
2231  else
2232  {
2233  return NULL;
2234  }
2235 }
2236 
2237 
2238 // ---------------------------------------------------------------------------
2239 // Public Interface
2240 // ---------------------------------------------------------------------------
2241 
2242 /*!
2243  * \brief Pack an ITV message.
2244  *
2245  * \param pMsgDef Pointer to message definition.
2246  * \param [in] pStruct Pointer to the associated, populated message
2247  * structure.
2248  * \param [out] buf Output message buffer.
2249  * \param bufSize Size of output buffer.
2250  * \param eEndian Packing order. See \ref NMEndian_T.
2251  *
2252  * \copydoc doc_return_pack_std
2253  */
2254 int nmPackITVMsg(const NMMsgDef_T *pMsgDef,
2255  void *pStruct,
2256  byte_t buf[],
2257  size_t bufSize,
2258  NMEndian_T eEndian)
2259 {
2260  NMCtl_T ctl = NMCTL_INIT_DECL;
2261  int n; // byte count/error code
2262  int k; // subbyte count/error code
2263 
2264  // too small
2265  if( bufSize < NMITV_MSGHDR_SIZE )
2266  {
2267  NMLIB_RAISE_ERROR(NM_ECODE_NOMEM, "%s(%u): msg_len=%u, hdr_size=%u",
2268  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, bufSize, NMITV_MSGHDR_SIZE);
2269  }
2270 
2271  // pack message id
2272  if( (n = nmPackU16((ushort)(pMsgDef->m_eMsgId), buf, bufSize, eEndian)) < 0 )
2273  {
2274  return n;
2275  }
2276 
2277  // pack field count
2278  buf[n++] = (byte_t)pMsgDef->m_uCount;
2279 
2280  // pack stream
2281  k = nmPackITVStream(pMsgDef, pStruct, &buf[n], bufSize-(size_t)n, eEndian,
2282  &ctl);
2283 
2284  return k >= 0? n+k: k;
2285 }
2286 
2287 /*!
2288  * \brief Pack an ITV message, tracing message packing to stderr.
2289  *
2290  * \param pMsgDef Pointer to message definition.
2291  * \param [in] pStruct Pointer to the associated, populated message
2292  * structure.
2293  * \param [out] buf Output message buffer.
2294  * \param bufSize Size of output buffer.
2295  * \param eEndian Packing order. See \ref NMEndian_T.
2296  *
2297  * \copydoc doc_return_pack_std
2298  */
2299 int nmPackITVMsgDebug(const NMMsgDef_T *pMsgDef,
2300  void *pStruct,
2301  byte_t buf[],
2302  size_t bufSize,
2303  NMEndian_T eEndian)
2304 {
2305  NMCtl_T ctl = NMCTL_INIT_DECL;
2306  int n; // byte count/error code
2307  int k; // subbyte count/error code
2308 
2309  ctl.m_bTrace = true;
2310 
2311  // too small
2312  if( bufSize < NMITV_MSGHDR_SIZE )
2313  {
2314  NMLIB_RAISE_ERROR(NM_ECODE_NOMEM, "%s(%u): msg_len=%u, hdr_size=%u",
2315  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, bufSize, NMITV_MSGHDR_SIZE);
2316  }
2317 
2318  // pack message id
2319  if( (n = nmPackU16((ushort)(pMsgDef->m_eMsgId), buf, bufSize, eEndian)) < 0 )
2320  {
2321  return n;
2322  }
2323 
2324  // pack field count
2325  buf[n++] = (byte_t)pMsgDef->m_uCount;
2326 
2327  // trace
2328  fprintf(stderr, "\n--- Packing ITV Message %s(%u): field_count=%zu\n",
2329  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, pMsgDef->m_uCount);
2330 
2331  // pack stream
2332  k = nmPackITVStream(pMsgDef, pStruct, &buf[n], bufSize-(size_t)n, eEndian,
2333  &ctl);
2334 
2335  if( k < 0 )
2336  {
2337  return k;
2338  }
2339 
2340  n += k;
2341 
2342  // trace final buffer
2343  fprintf(stderr, "Output Buffer (%zu bytes):\n", (size_t)n);
2344  nmPrintBuf(stderr, NULL, buf, (size_t)n, 16, 0);
2345  fprintf(stderr, "\n");
2346 
2347  return n;
2348 }
2349 
2350 /*!
2351  * \brief Unpack a ITV message.
2352  *
2353  * \param pMsgDef Pointer to message definition.
2354  * \param [in] buf Input message buffer.
2355  * \param uMsgLen Length of message (bytes) in input buffer.
2356  * \param [out] pStruct Pointer to the associated message
2357  * structure to populate.
2358  * \param eEndian Unpacking order. See \ref NMEndian_T.
2359  *
2360  * \returns
2361  * On success, returns the number of bytes unpacked.
2362  * On error, returns \h_lt 0.
2363  */
2364 int nmUnpackITVMsg(const NMMsgDef_T *pMsgDef,
2365  byte_t buf[],
2366  size_t uMsgLen,
2367  void *pStruct,
2368  NMEndian_T eEndian)
2369 {
2370  NMCtl_T ctl = NMCTL_INIT_DECL;
2371  ushort_t eMsgId; // message id in buffer
2372  size_t uCount; // field count in buffer
2373  int n; // byte count/error code
2374  int k; // subbyte count/error code
2375 
2376  // too small
2377  if( uMsgLen < NMITV_MSGHDR_SIZE )
2378  {
2379  NMLIB_RAISE_ERROR(NM_ECODE_NOMEM, "%s(%u): msg_len=%u, hdr_size=%u",
2380  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, uMsgLen, NMITV_MSGHDR_SIZE);
2381  }
2382 
2383  // unpack message id
2384  if( (n = nmUnpackU16(buf, uMsgLen, &eMsgId, eEndian)) < 0 )
2385  {
2386  return n;
2387  }
2388 
2389  // field count
2390  uCount = (size_t)buf[n++];
2391 
2392  // mismatch error
2393  if( (uint_t)(pMsgDef->m_eMsgId) != (uint_t)eMsgId )
2394  {
2395  NMLIB_RAISE_ERROR(NM_ECODE_MSGID, "%s(%u): rcv'd msgid=%u != msgdef's",
2396  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, eMsgId);
2397  }
2398 
2399  // unpack stream
2400  k = nmUnpackITVStream(pMsgDef, &buf[n], uMsgLen-(size_t)n, uCount,
2401  pStruct, eEndian, &ctl);
2402 
2403  // return code
2404  return k>=0? n+k: k;
2405 }
2406 
2407 /*!
2408  * \brief Unpack a ITV message, tracing unpacking to stderr.
2409  *
2410  * \param pMsgDef Pointer to message definition.
2411  * \param [in] buf Input message buffer.
2412  * \param uMsgLen Length of message (bytes) in input buffer.
2413  * \param [out] pStruct Pointer to the associated message
2414  * structure to populate.
2415  * \param eEndian Unpacking order. See \ref NMEndian_T.
2416  *
2417  * \copydoc doc_return_unpack_std
2418  */
2419 int nmUnpackITVMsgDebug(const NMMsgDef_T *pMsgDef,
2420  byte_t buf[],
2421  size_t uMsgLen,
2422  void *pStruct,
2423  NMEndian_T eEndian)
2424 {
2425  NMCtl_T ctl = NMCTL_INIT_DECL;
2426  ushort_t eMsgId; // message id in buffer
2427  size_t uCount; // field count in buffer
2428  int n; // byte count/error code
2429  int k; // subbyte count/error code
2430 
2431  ctl.m_bTrace = true;
2432 
2433  // too small
2434  if( uMsgLen < NMITV_MSGHDR_SIZE )
2435  {
2436  NMLIB_RAISE_ERROR(NM_ECODE_NOMEM, "%s(%u): msg_len=%u, hdr_size=%u",
2437  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, uMsgLen, NMITV_MSGHDR_SIZE);
2438  }
2439 
2440  // unpack message id
2441  if( (n = nmUnpackU16(buf, uMsgLen, &eMsgId, eEndian)) < 0 )
2442  {
2443  return n;
2444  }
2445 
2446  // field count
2447  uCount = (size_t)buf[n++];
2448 
2449  // mismatch error
2450  if( (uint_t)(pMsgDef->m_eMsgId) != (uint_t)eMsgId )
2451  {
2452  NMLIB_RAISE_ERROR(NM_ECODE_MSGID, "%s(%u): rcv'd msgid=%u != msgdef's",
2453  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, eMsgId);
2454  }
2455 
2456  // trace
2457  fprintf(stderr, "\n--- Unpacking ITV Message %s(%u): field_count=%zu\n",
2458  pMsgDef->m_sMsgName, pMsgDef->m_eMsgId, uCount);
2459  fprintf(stderr, "Input Buffer (%zu bytes):\n", uMsgLen);
2460  nmPrintBuf(stderr, NULL, buf, uMsgLen, 16, 0);
2461  fprintf(stderr, "\n");
2462 
2463  // unpack stream
2464  k = nmUnpackITVStream(pMsgDef, &buf[n], uMsgLen-(size_t)n, uCount,
2465  pStruct, eEndian, &ctl);
2466 
2467  // return code
2468  return k>=0? n+k: k;
2469 }
2470 
2471 /*!
2472  * \brief Get ITV message id from input buffer.
2473  *
2474  * \param [in] buf Input message buffer.
2475  * \param uMsgLen Length of message (bytes) in input buffer.
2476  * \param eEndian Unpacking order. See \ref NMEndian_T.
2477  *
2478  * \return
2479  * On success, returns unpacked message id.\n
2480  * On error, returns \ref NMMSG_ID_NONE (0).
2481  */
2482 uint_t nmGetITVMsgId(byte_t buf[], size_t uMsgLen, NMEndian_T eEndian)
2483 {
2484  ushort_t eMsgId; // message id in buffer
2485  int n;
2486 
2487  // too small
2488  if( uMsgLen < NMITV_MSGHDR_SIZE )
2489  {
2490  return (uint_t)NMMSG_ID_NONE;
2491  }
2492 
2493  // unpack message id
2494  else if( (n = nmUnpackU16(buf, uMsgLen, &eMsgId, eEndian)) < 0 )
2495  {
2496  return (uint_t)NMMSG_ID_NONE;
2497  }
2498 
2499  else
2500  {
2501  return (uint_t)eMsgId;
2502  }
2503 }
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
static int nmUnpackITVP32(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a 32-bit pointer ITV field from the message buffer.
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
#define NMFVAL_LEN_U64
unsigned 64-bit field value length
Definition: netmsgs.h:179
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 nmPackITVU16(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 16-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:391
#define NMFVAL_LEN_S8
signed 8-bit field value length
Definition: netmsgs.h:173
static NMPackFunc_T nmLookupITVPacker(NMFType_T eFType)
Lookup ITV packer function, given the message field type.
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.
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 nmUnpackITVStruct(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack structure ITV field from the message buffer.
#define NMFVAL_LEN_S32
signed 32-bit field value length
Definition: netmsgs.h:178
#define NMITV_FHDR_SIZE_STRING
Definition: netmsgs.h:231
static int nmPackITVHdrVector(const NMFieldDef_T *pFieldDef, size_t uCount, byte_t buf[], size_t bufSize)
Pack ITV Vector header.
Definition: nmLibPackITV.c:197
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
const int NMHashNoIdx
hash no index value
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
static int nmPackITVS64(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 64-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:621
static int nmUnpackITVU32(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 32-bit ITV field from the message buffer.
NMFieldThisString_T m_string
string field specific info
Definition: netmsgs.h:371
static int nmUnpackITVS64(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 64-bit ITV field from the message buffer.
#define NMITV_FID_SIZE
1 byte field id size
Definition: netmsgs.h:217
static int nmUnpackITVU16(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 16-bit ITV field from the message buffer.
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
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
#define NMFVAL_LEN_F64
64-bit floating-point number field val len
Definition: netmsgs.h:182
#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
static int nmUnpackITVStream(const NMMsgDef_T *pMsgDef, byte_t buf[], size_t uMsgLen, size_t uCount, void *pStruct, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an ITV byte stream.
#define NM_OK
not an error, success
Definition: netmsgs.h:70
uint_t m_eMsgId
message id (globally unique)
Definition: netmsgs.h:407
static int nmPackITVS16(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 16-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:437
static int nmPackITVHdrSimple(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize)
Pack ITV simple header.
Definition: nmLibPackITV.c:105
static int nmUnpackITVNoExec(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, size_t uFLen, NMCtl_T *pCtl)
Move parse cursor position past current field in message stream field.
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 NM_ECODE_EMSG
bad message
Definition: netmsgs.h:77
static NMUnpackFunc_T nmLookupITVUnpacker(NMFType_T eFType)
Lookup ITV unpacker function, given the message field type.
#define NMFVAL_LEN_S16
signed 16-bit field value length
Definition: netmsgs.h:176
#define NMLIB_RAISE_ERROR(ecode, fmt,...)
Raise libnetmsgs error (i.e. return from calling function).
static int nmPackITVP32(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a 32-bit pointer ITV field into the message buffer.
Definition: nmLibPackITV.c:759
#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.
#define NM_ECODE_MSGID
bad/unknown message id
Definition: netmsgs.h:78
static int nmPackITVPad(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: nmLibPackITV.c:226
static int nmUnpackITVString(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack variable length string ITV field from the message buffer.
8-bit ASCII characters char
Definition: netmsgs.h:133
translated pad type for packed stream
Definition: netmsgs.h:113
static int nmPackITVS8(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 8-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:345
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
#define NMLIB_WARNING(fmt,...)
Log libnetmsgs warning.
Definition: nmLibInternal.h:80
NMFieldThis_T m_this
specific field information
Definition: netmsgs.h:385
uint_t nmGetITVMsgId(byte_t buf[], size_t uMsgLen, NMEndian_T eEndian)
Get ITV message id from input buffer.
static int nmPackITVU32(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 32-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:483
8-bit bool 0/1 bool_t
Definition: netmsgs.h:117
static int nmUnpackITVU8(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 8-bit ITV field from the message buffer.
static int nmUnpackITVPad(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.
#define NMITV_FHDR_SIZE_STRUCT
Definition: netmsgs.h:234
int nmSetS8(const NMFieldDef_T *pFieldDef, void *pValIn, signed char *pValOut)
Helper function to set a signed 8-bit integer.
const NMFieldDef_T * nmFindFieldDef(const NMMsgDef_T *pMsgDef, byte_t byFId)
Find the field definition in the message definition, given the field id.
Definition: nmLibUtils.c:235
static int nmPackITVU8(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 8-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:299
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.
static int nmUnpackITVS16(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 16-bit ITV field from the message buffer.
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 nmPackITVP64(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a 64-bit pointer ITV field into the message buffer.
Definition: nmLibPackITV.c:798
#define NMFVAL_LEN_F32
32-bit floating-point number field val len
Definition: netmsgs.h:181
static int nmPackITVU64(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack an unsigned 64-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:575
static int nmPackITVString(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack null-terminated, variable length string ITV field into the message buffer.
Definition: nmLibPackITV.c:840
size_t m_uMaxCount
maximum number of characters sans null char
Definition: netmsgs.h:339
static int nmUnpackITVU64(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 64-bit ITV field from the message buffer.
static int nmUnpackITVF32(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 ITV field from the message buffer.
64-bit pointer (overloaded) void*
Definition: netmsgs.h:126
static int nmPackITVF64(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 ITV field into the message buffer.
Definition: nmLibPackITV.c:713
byte_t m_bNoExec
do [not] execute assignment of value
static int nmPackITVHdrString(const NMFieldDef_T *pFieldDef, size_t uCount, byte_t buf[], size_t bufSize)
Pack ITV String header.
Definition: nmLibPackITV.c:135
#define NMITV_FHDR_SIZE_VECTOR
Definition: netmsgs.h:237
#define ITVPACK_SIMPLE_HDR(p, buf, n, ctl)
Pack simple field type ITV header.
Definition: nmLibPackITV.c:93
#define NMITV_FHDR_SIZE_SIMPLE
Definition: netmsgs.h:228
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
int nmUnpackITVMsgDebug(const NMMsgDef_T *pMsgDef, byte_t buf[], size_t uMsgLen, void *pStruct, NMEndian_T eEndian)
Unpack a ITV message, tracing unpacking to stderr.
#define NMFVAL_LEN_P32
32-bit pointer field value length
Definition: netmsgs.h:183
static int nmPackITVVector(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack variable length vector ITV field into the message buffer.
Definition: nmLibPackITV.c:944
#define NM_ECODE_NOMEM
not enough buffer memory available
Definition: netmsgs.h:73
int nmPackITVMsgDebug(const NMMsgDef_T *pMsgDef, void *pStruct, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an ITV message, tracing message packing to stderr.
size_t m_uCount
number of pad bytes
Definition: netmsgs.h:265
NMFType_T
Definition: netmsgs.h:110
#define NMFVAL_LEN_U16
unsigned 16-bit field value length
Definition: netmsgs.h:175
NMEndian_T
Definition: netmsgs.h:100
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 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 nmPackITVStream(const NMMsgDef_T *pMsgDef, void *pStruct, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a ITV message.
const NMFieldDef_T * m_pFields
pointer to array of msg field definitions
Definition: netmsgs.h:409
static int nmPackITVS32(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a signed 32-bit ITV field into the message buffer.
Definition: nmLibPackITV.c:529
static int nmUnpackITVF64(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 ITV field from the message buffer.
int nmSetS32(const NMFieldDef_T *pFieldDef, void *pValIn, int *pValOut)
Helper function to set a signed 32-bit integer.
static int nmUnpackITVS32(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 32-bit ITV field from the message buffer.
#define NMFVAL_LEN_U32
unsigned 32-bit field value length
Definition: netmsgs.h:177
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 nmUnpackITVVector(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack variable length vector ITV field from the message buffer.
static int nmPackITVHdrStruct(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize)
Pack ITV Struct header.
Definition: nmLibPackITV.c:166
size_t m_uElemSize
vector element storage size
Definition: netmsgs.h:355
#define NM_ECODE_INTERNAL
internal inconsistency or bug
Definition: netmsgs.h:80
#define NMITV_MSGHDR_SIZE
Definition: netmsgs.h:222
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
static int nmPackITVBool(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 ITV field into the message buffer.
Definition: nmLibPackITV.c:257
unsigned 32-bit integer unsigned int
Definition: netmsgs.h:124
pad internal field type
Definition: netmsgs.h:145
#define NMFVAL_LEN_P64
64-bit pointer field value length
Definition: netmsgs.h:184
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
#define NMITV_FHDR_SIZE_BASE
Definition: netmsgs.h:225
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 nmPackITVF32(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 ITV field into the message buffer.
Definition: nmLibPackITV.c:667
static int nmUnpackITVBool(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack an unsigned 8-bit boolean ITV field from the message buffer.
#define NMFVAL_LEN_U8
unsigned 8-bit field value length
Definition: netmsgs.h:172
Network Messaging declarations.
#define NMMSG_ID_NONE
no message id (reserved)
Definition: netmsgs.h:210
NMFieldThisPad_T m_pad
pad field specific info
Definition: netmsgs.h:364
static int nmUnpackITVP64(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a 64-bit pointer ITV field from the message buffer.
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
#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
#define NMFVAL_LEN_S64
signed 64-bit field value length
Definition: netmsgs.h:180
static int nmPackITVStruct(const NMFieldDef_T *pFieldDef, void *pVal, byte_t buf[], size_t bufSize, NMEndian_T eEndian, NMCtl_T *pCtl)
Pack a structure ITV field into the message buffer.
Definition: nmLibPackITV.c:903
int nmUnpackITVMsg(const NMMsgDef_T *pMsgDef, byte_t buf[], size_t uMsgLen, void *pStruct, NMEndian_T eEndian)
Unpack a ITV message.
static NMLookupTblEntry_T NMITVLookupTbl[]
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
static int nmUnpackITVS8(const NMFieldDef_T *pFieldDef, byte_t buf[], size_t bufSize, void *pVal, NMEndian_T eEndian, NMCtl_T *pCtl)
Unpack a signed 8-bit ITV field from the message buffer.
byte_t * m_buf
the vector
Definition: netmsgs.h:397
int nmPackITVMsg(const NMMsgDef_T *pMsgDef, void *pStruct, byte_t buf[], size_t bufSize, NMEndian_T eEndian)
Pack an ITV message.
Internal Control Structure.
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