librnr  1.14.5
RoadNarrows Robotics Common Library 1
example_cpp.cxx
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////////////
2 //
3 // Package: RoadNarrows Robotics Common Library 1
4 //
5 // File: example_cpp.cxx
6 //
7 /*! \file
8  *
9  * $LastChangedDate$
10  * $Rev$
11  *
12  * \brief Nonsensical example that merely test compiling and linking a C++
13  * applciation agains librnr C library.
14  *
15  * \author Robin Knight (robin.knight@roadnarrows.com)
16  *
17  * \pkgcopyright{2010-2018,RoadNarrows LLC.,http://www.roadnarrows.com}
18  * \n All Rights Reserved
19  */
20 // Permission is hereby granted, without written agreement and without
21 // license or royalty fees, to use, copy, modify, and distribute this
22 // software and its documentation for any purpose, provided that
23 // (1) The above copyright notice and the following two paragraphs
24 // appear in all copies of the source code and (2) redistributions
25 // including binaries reproduces these notices in the supporting
26 // documentation. Substantial modifications to this software may be
27 // copyrighted by their authors and need not follow the licensing terms
28 // described here, provided that the new terms are clearly indicated in
29 // all files where they apply.
30 //
31 // IN NO EVENT SHALL THE AUTHOR, ROADNARROWS LLC, OR ANY MEMBERS/EMPLOYEES
32 // OF ROADNARROW LLC OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
33 // PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
34 // DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
35 // EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
36 // THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // THE AUTHOR AND ROADNARROWS LLC SPECIFICALLY DISCLAIM ANY WARRANTIES,
39 // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
40 // FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN
41 // "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO
42 // PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
43 //
44 ////////////////////////////////////////////////////////////////////////////////
45 
46 #include <iostream>
47 #include <string>
48 #include <libgen.h>
49 
50 #include "rnr/rnrconfig.h"
51 #include "rnr/log.h"
52 #include "rnr/opts.h"
53 
54 #include "version.h"
55 
56 using namespace std;
57 
58 //
59 // The command with option and argument values.
60 //
61 static char *Argv0; ///< the command
62 static int OptsTest = 1; ///< test option value
63 
64 
65 //.............................................................................
66 // Log and Options Validation
67 //.............................................................................
68 
69 /*!
70  * \brief Program information.
71  *
72  * \note The dot initialization of C is far superior to C++ fixed order for
73  * complex fixed structures.
74  */
76 {
77  // usage_args
78  NULL,
79 
80  // synopsis
81  "Example of C++ using librnr grab bag of goodies.",
82 
83  // long_desc
84  "The %P command demonstrates compiling-linking C++ with librnr facilities.",
85 
86  // diagnostic
87  NULL
88 };
89 
90 /*
91  * \brief Command line options information.
92  */
94 {
95  // -t, --test <test>
96  {
97  "test", // long_opt
98  't', // short_opt
99  required_argument, // has_arg
100  true, // has_default
101  &OptsTest, // opt_addr
102  OptsCvtArgInt, // fn_cvt
103  OptsFmtInt, // fn_fmt
104  "<test>", // arg_name
105  // opt_desc
106  "Set the logging test(s) to conduct.\n"
107  "%A is one of:\n"
108  " 0 - No tests.\n"
109  " 1 - Test #1.\n"
110  " 2 - Test #2.\n"
111  " 3 - All tests."
112  },
113 
114  {NULL, }
115 };
116 
117 /*!
118  * \brief Log test number 1.
119  *
120  * \param p Void pointer.
121  * \param sFruit Character pointer.
122  * \param n Integer.
123  * \param half Short.
124  * \param f Double.
125  * \param hex Integer in hex.
126  * \param bAreRipe Boolean.
127  */
128 static void logtest_num1(void *p, const char *sFruit, int n, int half,
129  double f, int hex, bool_t bAreRipe)
130 {
131  // test log function call diagnostics 1
132  LOGDIAG1CALL(_TPTR(p), _TSTR(sFruit), _TINT(n), _TSHORT(half), _TFLOAT(f),
133  _THEX(hex), _TBOOL(bAreRipe));
134 
135  // test diagnostic 2 test
136  if( bAreRipe )
137  {
138  LOGDIAG2("There are %d juicy %s in %s", n, sFruit, "Tuscany");
139  }
140  else
141  {
142  LOGDIAG2("There are %d green %s in %s", n, sFruit, "Utah");
143  }
144 }
145 
146 /*!
147  * \brief Log test number 2.
148  *
149  * \param count Count.
150  */
151 static int logtest_num2(int count)
152 {
153  FILE *fp;
154  const char *sFileName = "PackingShedOnStrike.newsflash";
155 
156  // test log function call diagnostics 2
157  LOGDIAG2CALL(_TINT(count));
158 
159  // test error logging
160  while( count-- > 0 )
161  {
162  LOGERROR("Salmonella scare %d...", count);
163  }
164 
165  // test system error logging
166  if( (fp = fopen(sFileName, "r")) == NULL )
167  {
168  LOGSYSERROR("%s", sFileName);
169  }
170  else
171  {
172  LOGDIAG4("%s: what a pleasant surprise", sFileName);
173  fclose(fp);
174  }
175 }
176 
177 /*!
178  * \brief Run log test(s).
179  *
180  * \returns 1 on success, \h_gt 0 on failure.
181  */
182 static int runlogtests()
183 {
184  short h = 10;
185  int i = 12;
186 
187  switch( OptsTest )
188  {
189  case 0:
190  break;
191  case 1:
192  logtest_num1(&i, "apples", 53, h, 123.5, 0xdead, false);
193  break;
194  case 2:
195  logtest_num2(3);
196  break;
197  case 3:
198  logtest_num1(&h, "pears", 12, h, -1.5E-2, 0xf1, true);
199  logtest_num2(3);
200  break;
201  default:
202  LOGERROR("bug: %d: unexpected test", OptsTest);
203  return 0;
204  }
205  return 1;
206 }
207 
208 
209 //.............................................................................
210 // Associative Validation
211 //.............................................................................
212 
213 #include "rnr/assoc.h"
214 
215 /*!
216  * \brief Major and minor solar body ids (partial, of course).
217  */
219 {
220  unknown,
221 
222  Sun,
223  Mercury,
224  Venus,
225  Earth, Moon,
226  Mars, Phobos, Deimos,
227  Ceres,
228  Jupiter, Io, Europa, Ganymede, Callisto,
229  Saturn, Titan,
230  Uranus, Titania,
231  Neptune, Triton,
232  Pluto, Charon,
233  Eris,
234 
235  NumBodies
236 };
237 
238 /*!
239  * \brief Solar body name-id pairs (partial).
240  */
242 {
243  {"unknown", unknown}, // default
244  {"Sun", Sun},
245  {"Mercury", Mercury},
246  {"Venus", Venus},
247  {"Earth", Earth},
248  {"Moon", Moon},
249  {"Mars", Mars},
250  {"Phobos", Phobos},
251  {"Deimos", Deimos},
252  {"Jupiter", Jupiter},
253  {"Io", Io},
254  {"Europa", Europa},
255  {"Ganymede", Ganymede},
256  {"Callisto", Callisto},
257  {"Saturn", Saturn},
258  {"Titan", Titan},
259  {"Uranus", Uranus},
260  {"Titania", Titania},
261  {"Neptune", Neptune},
262  {"Triton", Triton},
263  {"Ceres", Ceres},
264  {"Pluto", Pluto},
265  {"Charon", Charon}
266 };
267 
268 /*!
269  * \brief Test value to name association.
270  *
271  * \param oid Value.
272  */
274 {
275  cout << oid << " --> "
276  << NvpVal2Name(SolarBodyNames, arraysize(SolarBodyNames), (int)oid)
277  << endl;
278 }
279 
280 /*!
281  * \brief Test name to value association.
282  *
283  * \param name Name.
284  */
285 void test_assoc(const char *name)
286 {
287  cout << name << " --> "
288  << NvpName2Val(SolarBodyNames, arraysize(SolarBodyNames), name)
289  << endl;
290 }
291 
292 
293 //.............................................................................
294 // Char Validation
295 //.............................................................................
296 
297 #include "rnr/char.h"
298 
299 /*!
300  * \brief Test character routine(s).
301  */
302 void test_char()
303 {
304  byte_t buf[] = "\x04\xf3 apple\t\n\va day.";
305 
306  PrettyPrintBuf(stdout, buf, sizeof(buf));
307  cout << endl;
308 }
309 
310 
311 //.............................................................................
312 // Config (INI) Validation
313 //.............................................................................
314 
315 #include "rnr/config.h"
316 
317 /*!
318  * \brief Test INI configuration routines.
319  */
320 void test_config(string inifile)
321 {
322  Config_T *ini = NULL;
323  string path[] = {".", "./examples", "/prj/pkg/librnr/examples"};
324  string filepath;
325  int i;
326 
327  for(i=0; (i<arraysize(path)) && (ini == NULL); ++i)
328  {
329  filepath = path[i] + "/" + inifile;
330  ini = ConfigDbRead(filepath.c_str());
331  }
332 
333  if( ini != NULL )
334  {
335  ConfigDbPrint(ini, stdout);
336  }
337 }
338 
339 
340 //.............................................................................
341 // Doubly-Linked List Validation
342 //.............................................................................
343 
344 #include "rnr/dliststr.h"
345 
346 /*!
347  * \brief Test doubly-linked list routines.
348  */
350 {
351  DListStr_T *dlist;
352  DListStrIter_T iter;
353  char *s;
354 
355  dlist = DListStrNewDft();
356 
357  DListStrAppend(dlist, (char *)"elephant");
358  DListStrAppend(dlist, (char *)"rhinocerus");
359  DListStrPrepend(dlist, (char *)"hippopotomous");
360 
361  cout << "count = " << DListStrCount(dlist) << endl;
362 
363  for(s=DListStrIterDataFirst(dlist, &iter);
364  s!=NULL;
365  s=DListStrIterDataNext(&iter))
366  {
367  cout << s << endl;
368  }
369 }
370 
371 
372 //.............................................................................
373 // Hash Validation
374 //.............................................................................
375 
376 #include "rnr/hash.h"
377 #include "rnr/new.h"
378 
379 /*!
380  * \brief Colorado's 14,000+ foot mountains.
381  *
382  * N.B. there are 53 of them, I'm stopping at the highest 16.
383  */
384 static string Colorado14ers[][2] =
385 {
386  {"mt_elbert", "14,433"},
387  {"mt_massive", "14,421"},
388  {"mt_harvard", "14,420"},
389  {"blanca_peak", "14,345"},
390  {"la_plata_peak", "14,336"},
391  {"uncompahgre_peak", "14,309"},
392  {"crestone_peak", "14,294"},
393  {"mt_lincoln", "14,286"},
394  {"grays_peak", "14,270"},
395  {"mt_antero", "14,269"},
396  {"torreys_peak", "14,267"},
397  {"castle_peak", "14,265"},
398  {"quandary_peak", "14,265"},
399  {"mt_evans", "14,264"},
400  {"longs_peak", "14,255"},
401  {"mt_wilson", "14,246"}
402 };
403 
404 /*!
405  * \brief Delete node data - both key and value are dynamically allocated.
406  *
407  * \param key Data key.
408  * \param val Data value.
409  */
410 void del_node_data(void *key, void *val)
411 {
412  delete((char *)key);
413  delete((char *)val);
414 }
415 
416 /*!
417  * \brief Test hash and new routines.
418  */
419 void test_hash()
420 {
421  hash_t *h = NULL;
422  hscan_t hs;
423  hnode_t *hn;
424 
425  h = hash_table_create(
426  true, // dynamic table sizing
427  (hashcount_t)4, // minimum size
428  HASHCOUNT_T_MAX, // maximum size
429  NULL, // use default comparator function
430  NULL, // use default hashing function
431  del_node_data); // hash node data deletion func
432 
433  hash_set_self_verify(true); // off by default
434 
435  char *key, *val;
436 
437  for(size_t i=0; i<arraysize(Colorado14ers); ++i)
438  {
439  key = new_strdup(Colorado14ers[i][0].c_str());
440  val = new_strdup(Colorado14ers[i][1].c_str());
441 
442  hash_insert(h, key, val);
443  }
444 
445  hash_scan_begin(&hs, h);
446  while( (hn = hash_scan_next(&hs)) != NULL )
447  {
448  cout << (char *)hnode_getkey(hn) << " -> " << (char *)hnode_get(hn) << endl;
449  }
450 }
451 
452 
453 //.............................................................................
454 // Main Functions
455 //.............................................................................
456 
457 /*!
458  * \brief Main initialization.
459  *
460  * \param argc Command-line argument count.
461  * \param argv Command-line argument list.
462  *
463  * \return 1 on success, exits on failure.
464  */
465 static int init(int argc, char *argv[])
466 {
467  FILE *fp;
468  int i;
469 
470  // name of this process
471  Argv0 = basename(argv[0]);
472 
473  // parse input options
474  argv = OptsGet(Argv0, &PkgInfo, &LogExamplePgmInfo, LogExampleOptsInfo, true,
475  &argc, argv);
476 
477  // test log helper macro
478  CHKEXPR_INT(OptsTest, ((OptsTest >= 0) || (OptsTest <= 3)), 0);
479 
480  // test complicated logging
481  if( LOGABLE(LOG_LEVEL_DIAG1) )
482  {
483  LOGDIAG1("Post options processed non-option arguments:");
484  fp = LOG_GET_LOGFP();
485  for(i=0; i<argc; ++i)
486  {
487  fprintf(fp, " argv[%d]=\"%s\"\n", i, argv[i]);
488  }
489  }
490 
491  return 1;
492 }
493 
494 /*!
495  * \brief Example main.
496  *
497  * \param argc Command-line argument count.
498  * \param argv Command-line argument list.
499  *
500  * \par Exit Status:
501  * Program exits with 0 success, \h_gt 0 on failure.
502  */
503 int main(int argc, char *argv[])
504 {
505  cout << "Testing librnr Linkage" << endl
506  << "----------------------" << endl;
507 
508  cout << "* Validate options and logging." << endl;
509  if( !init(argc, argv) )
510  {
511  return 3;
512  }
513  runlogtests();
514 
515  cout << "* Validate associative mapping." << endl;
516  test_assoc(Titania);
517  test_assoc("Moon");
518  cout << endl;
519 
520  cout << "* Validate char." << endl;
521  test_char();
522  cout << endl;
523 
524  cout << "* Validate config (ini)." << endl;
525  test_config("example.ini");
526  cout << endl;
527 
528  cout << "* Validate string dlist." << endl;
529  test_dlist();
530  cout << endl;
531 
532  cout << "* Validate hash and new." << endl;
533  test_hash();
534  cout << endl;
535 
536  return 0;
537 }
static int logtest_num2(int count)
Log test number 2.
Simple associative map data and operator declarations.
#define _THEX(var)
int (hex)
Definition: log.h:581
#define CHKEXPR_INT(val, expr,...)
check integer
Definition: log.h:688
static char * Argv0
the command
Definition: example_cpp.cxx:61
const char * NvpVal2Name(Nvp_T tbl[], size_t nTblEntries, int iVal)
Get the name associated with the value.
Definition: assoc.c:94
#define _TINT(var)
int (decimal)
Definition: log.h:582
#define hnode_getkey(N)
Get hash node hash key.
Definition: hash.h:409
FILE * LOG_GET_LOGFP()
Get current logging output stream file pointer.
Definition: log.c:301
#define HASHCOUNT_T_MAX
Maximum maximum hash table size.
Definition: hash.h:81
static int runlogtests()
Run log test(s).
hnode_t * hash_scan_next(hscan_t *scan)
Retrieve the next node from the hash table.
Definition: hash.c:998
char * new_strdup(const char *s)
Duplicate a string.
Definition: new.c:176
static OptsInfo_T LogExampleOptsInfo[]
Command line options information.
Definition: example_log.c:76
Doubly linked list of character strings "inherited" from dlistvoid.
Standard command-line options options and parsing.
Program Description Strings Info Structure.
Definition: opts.h:226
int main(int argc, char *argv[])
Example main.
Configuration parser declarations.
char * OptsFmtInt(char *buf, size_t buflen, void *pOptVal)
Integer option value string formatter.
Definition: opts.c:1215
#define NULL
null pointer
Definition: rnrconfig.h:199
General purpose hash data and function declarations.
#define _TSHORT(var)
short int (decimal)
Definition: log.h:584
Memory allocation and deallocation declarations.
void del_node_data(void *key, void *val)
Delete node data - both key and value are dynamically allocated.
Simple character manipulations.
#define LOGDIAG1(fmt,...)
Standard Diagnostic Level 1 logging.
Definition: log.h:407
void ConfigDbPrint(Config_T *pConfig, FILE *fp)
Print configuration database to the output file stream.
Definition: config.c:514
#define LOGSYSERROR(fmt,...)
Standard System Error logging.
Definition: log.h:509
Definition: assoc.h:151
void hash_set_self_verify(bool_t selfverify)
Enable (disable) automatic self-checks during hash table modification operatations.
Definition: hash.c:1331
static OptsPgmInfo_T LogExamplePgmInfo
Program information.
Definition: example_cpp.cxx:75
#define arraysize(array)
array size, i.e. number of array entries
Definition: rnrconfig.h:259
#define LOGDIAG2(fmt,...)
Standard Diagnostic Level 2 logging.
Definition: log.h:400
void test_config(string inifile)
Test INI configuration routines.
int PrettyPrintBuf(FILE *fp, byte_t buf[], size_t len)
Print out &#39;prettified&#39; readable version of the contents of the given (binary) buffer.
Definition: char.c:107
#define LOGERROR(fmt,...)
Standard Error logging.
Definition: log.h:488
#define LOGABLE(level)
Test if given level is logable at current threshold.
Definition: log.h:195
unsigned long hashcount_t
maximum hash table size type
Definition: hash.h:94
void test_dlist()
Test doubly-linked list routines.
int OptsCvtArgInt(const char *argv0, const char *sOptName, char *optarg, void *pOptVal)
Convert options integer argument to integer.
Definition: opts.c:1065
void test_assoc(BodyId_T oid)
Test value to name association.
Nvp_T SolarBodyNames[]
Solar body name-id pairs (partial).
static int OptsTest
test option value
Definition: example_cpp.cxx:62
#define LOGDIAG4(fmt,...)
Standard Diagnostic Level 4 logging.
Definition: log.h:386
static string Colorado14ers[][2]
Colorado&#39;s 14,000+ foot mountains.
static const PkgInfo_T PkgInfo
Definition: version.h:45
void hash_scan_begin(hscan_t *scan, hash_t *hash)
Reset the hash scanner (iterator).
Definition: hash.c:937
void test_hash()
Test hash and new routines.
int bool_t
"boolean" T/F
Definition: rnrconfig.h:187
RoadNarrows Robotics common configuration file.
char ** OptsGet(const char *argv0, const PkgInfo_T *pPkgInfo, OptsPgmInfo_T *pPgmInfo, OptsInfo_T *pOptsInfo, bool_t bHasLogging, int *pargc, char *argv[])
Gets, validates, and sets all command line options.
Definition: opts.c:861
#define _TBOOL(var)
boolean
Definition: log.h:588
u8_t byte_t
8-bit byte
Definition: rnrconfig.h:177
static int init(int argc, char *argv[])
Main initialization.
Hash scanner structure.
Definition: hash.h:302
Package version information.
#define _TSTR(var)
string variable
Definition: log.h:578
#define hnode_get(N)
Get hash node user data.
Definition: hash.h:403
hash_t * hash_table_create(bool_t isdynamic, hashcount_t minsize, hashcount_t maxsize, hash_comp_t compfun, hash_fun_t hashfun, hnode_data_free_t freedatafun)
Create a dynamic hash table.
Definition: hash.c:691
#define LOG_LEVEL_DIAG1
diagnostic level 1
Definition: log.h:181
void test_char()
Test character routine(s).
#define _TPTR(var)
pointer
Definition: log.h:587
static DListStr_T * DListStrNewDft()
Allocator and initializer new empty string dlist with default callbacks.
Definition: dliststr.h:91
#define _TFLOAT(var)
float
Definition: log.h:586
Hash table control structure.
Definition: hash.h:267
Hash chain node structure.
Definition: hash.h:149
Logger declarations.
bool_t hash_insert(hash_t *hash, void *key, void *data)
Insert user data with the given key into the hash table.
Definition: hash.c:1283
#define LOGDIAG2CALL(...)
Standard Diagnostic Level 2 function call tracing.
Definition: log.h:454
static void logtest_num1(void *p, const char *sFruit, int n, int half, double f, int hex, bool_t bAreRipe)
Log test number 1.
Short and Long Options Info.
Definition: opts.h:134
#define LOGDIAG1CALL(...)
Standard Diagnostic Level 1 function call tracing.
Definition: log.h:460
Config_T * ConfigDbRead(const char *sFileName)
Create a new configuration database from a configuration file.
Definition: config.c:326
BodyId_T
Major and minor solar body ids (partial, of course).
Definition: example_assoc.c:55
int NvpName2Val(Nvp_T tbl[], size_t nTblEntries, const char *sName)
Get the value associated with the name.
Definition: assoc.c:64