1 //**************************************************************************************************
2 //                                          Component.cpp                                          *
3 //                                         ---------------                                         *
4 // Started     : 2004-05-14                                                                        *
5 // Last Update : 2015-04-06                                                                        *
6 // Copyright   : (C) 2004 by MSWaters                                                              *
7 //**************************************************************************************************
8 
9 //**************************************************************************************************
10 //                                                                                                 *
11 //      This program is free software; you can redistribute it and/or modify it under the          *
12 //      terms of the GNU General Public License as published by the Free Software Foundation;      *
13 //      either version 3 of the License, or (at your option) any later version.                    *
14 //                                                                                                 *
15 //**************************************************************************************************
16 
17 #include "Component.hpp"
18 
19 //**************************************************************************************************
20 // Finish the definition of the ArrayComponent type. The following expands into
21 // some C++ code and so should only be compiled once (ie. don't put this into a
22 // header file rather put it in a source file or there will be linker errors).
23 
24 #include <wx/arrimpl.cpp>
25 WX_DEFINE_OBJARRAY( ArrayComponent );
26 
27 //**************************************************************************************************
28 // Constructor.
29 
Component(void)30 Component::Component( void ) : wxString( )
31 {
32   bClear( );
33 }
34 
35 //**************************************************************************************************
36 // Destructor.
37 
~Component()38 Component::~Component( )
39 {
40 }
41 
42 //**************************************************************************************************
43 // Get the component ports.
44 
GetPorts(void)45 void  Component::GetPorts( void )
46 {
47   // Not yet implemented ???
48 }
49 
50 //**************************************************************************************************
51 // Test the values against each other.
52 //
53 // Return Values :
54 //   true  - Success
55 //   false - Failure
56 
bValidate(void)57 bool  Component::bValidate( void )
58 {
59   m_osErrMsg.Empty( );
60 
61   if( IsEmpty( ) )                      bSetErrMsg( wxT("component is empty") );
62   else if( m_osName.IsEmpty( ) )        bSetErrMsg( wxT("component has no name") );
63   else if( m_osaNodes.GetCount( ) < 2 ) bSetErrMsg( wxT("component has less than two nodes") );
64   else if( m_osValue.IsEmpty( ) )       bSetErrMsg( wxT("component has no value") );
65 
66   return( bIsValid( ) );
67 }
68 
69 //**************************************************************************************************
70 // Attempt to set the objects error message string attribute.
71 //
72 // Argument List :
73 //   rosErrMsg - A reference to a string containing the new error message
74 //
75 // Return Values :
76 //   true  - Success
77 //   false - Failure
78 
bSetErrMsg(const wxString & rosErrMsg)79 bool  Component::bSetErrMsg( const wxString & rosErrMsg )
80 {
81   if( ! bIsValid( ) ) return( false );
82 
83   m_osErrMsg = rosErrMsg;
84 
85   return( true );
86 }
87 
88 //**************************************************************************************************
89 // Compare algorithm for sorting Component objects.
90 //
91 // Argument List :
92 //   ppo1 - The address of a pointer to the first  Component object to compare
93 //   ppo2 - The address of a pointer to the second Component object to compare
94 //
95 // Return Values :
96 //   >0 - If *(*ppo1) is greater than *(*ppo2)
97 //   =0 - If *(*ppo1) is equal to     *(*ppo2)
98 //   <0 - If *(*ppo1) is less    than *(*ppo2)
99 
iCompare(Component ** ppo1,Component ** ppo2)100 int  Component::iCompare( Component ** ppo1, Component ** ppo2 )
101 {
102   const wxString & ros1 = (const wxString &) **ppo1;
103   const wxString & ros2 = (const wxString &) **ppo2;
104 
105   return( ros1.Cmp( ros2 ) );
106 }
107 
108 //**************************************************************************************************
109 // Clear the object attributes.
110 //
111 // Return Values :
112 //   true  - Success
113 //   false - Failure
114 
bClear(void)115 bool  Component::bClear( void )
116 {
117   wxString::Empty( );
118 
119   m_osErrMsg = wxT("Invalid");
120 
121   m_osName  .Clear( );
122   m_osaNodes.Clear( );
123   m_osValue .Clear( );
124 
125   m_eType = eCPNT_NONE;
126   m_osaPorts.Clear( );
127 
128   return( true );
129 }
130 
131 //**************************************************************************************************
132 // Parse a component definition string extracted from a netlist.
133 //
134 // Return Values :
135 //   true  - Success
136 //   false - Failure
137 
bParse(void)138 bool  Component::bParse( void )
139 {
140   wxStringTokenizer  ostk1;
141   wxString           os1;
142   size_t             szt1;
143 
144   // Clear the object attributes
145   os1 = (wxString &) *this;
146   bClear( );
147   wxString::assign( os1 );
148   m_osErrMsg.Empty( );
149 
150   // Tokenize the command string
151   if( IsEmpty( ) )               return( bValidate( ) );
152   ostk1.SetString( os1 );
153 
154   // Extract the component name
155   bSetName( ostk1.GetNextToken( ) );
156 
157   // Extract the nodes the component is connected to
158   if( ! ostk1.HasMoreTokens( ) ) return( bValidate( ) );
159   bSetNodes( ostk1.GetString( ) );
160   for( szt1=0; szt1<m_osaNodes.GetCount( ); szt1++ )
161     ostk1.GetNextToken( );
162 
163   // Extract the component value
164   if( ! ostk1.HasMoreTokens( ) ) return( bValidate( ) );
165   bSetValue( ostk1.GetString( ) );
166 
167   return( bValidate( ) );
168 }
169 
170 //**************************************************************************************************
171 // Format the command string.
172 //
173 // Eg. : C1 6 2 100n
174 //
175 // Return Values :
176 //   true  - Success
177 //   false - Failure
178 
bFormat(void)179 bool  Component::bFormat( void )
180 {
181   wxString  osCmd;
182   size_t    sz1;
183 
184   // Format the value part of the component definition
185   bFormatValue( );
186 
187   // Set the name
188   osCmd = m_osName;
189 
190   // Append the nodes
191   for( sz1=0; sz1<m_osaNodes.GetCount( ); sz1++ )
192     osCmd << wxT(' ') << m_osaNodes.Item( sz1 );
193 
194   // Append the value
195   osCmd << wxT(' ') << m_osValue;
196 
197   wxString::assign( osCmd );
198 
199   return( bValidate( ) );
200 }
201 
202 //**************************************************************************************************
203 // Set the object attributes via a component definition string.
204 //
205 // Argument List :
206 //   rosCmd - A reference to a string containing a component definition
207 //
208 // Return Values :
209 //   true  - Success
210 //   false - Failure
211 
bSetString(const wxString & rosCmd)212 bool  Component::bSetString( const wxString & rosCmd )
213 {
214   // Clear the component attributes
215   bClear( );
216 
217   // Set the underlying string to the raw component definition
218   wxString::assign( rosTrim( rosCmd ) );
219 
220   // Parse the component definition
221   bParse( );
222 
223   return( bIsValid( ) );
224 }
225 
226 //**************************************************************************************************
227 // Set the component name.
228 //
229 // Argument List :
230 //   rosName - A reference to a string containing a compoent name
231 //
232 // Return Values :
233 //   true  - Success
234 //   false - Failure
235 
bSetName(const wxString & rosName)236 bool  Component::bSetName( const wxString & rosName )
237 {
238   wxStringTokenizer  ostk1;
239   wxString           os1;
240   wxChar             oc1;
241 
242   // Tokenize the name string
243   ostk1.SetString( rosName );
244   if( ostk1.CountTokens( ) <=0 )                                               return( false );
245 
246   // Extract the component name and check that it begins with an alpha character
247   os1 = ostk1.GetNextToken( );
248   oc1 = os1.GetChar( 0 );
249   if( !(oc1>=wxT('a') && oc1<=wxT('z')) && !(oc1>=wxT('A') && oc1<=wxT('Z')) ) return( false );
250   m_osName = os1;
251 
252   // Determine the component type and units type
253   m_eType = eGetType( m_osName );
254 
255   return( true );
256 }
257 
258 //**************************************************************************************************
259 // Set the component nodes.
260 //
261 // Argument List :
262 //   rosNodes - A reference to a string containing component nodes eg. "2,1".
263 //
264 // Return Values :
265 //   true  - Success
266 //   false - Failure
267 
bSetNodes(const wxString & rosNodes)268 bool  Component::bSetNodes( const wxString & rosNodes )
269 {
270   wxStringTokenizer  ostk1;
271   size_t             szNodeCnt;
272   size_t             sz1;
273 
274   // Tokenize the name string
275   ostk1.SetString( rosNodes, wxT(" \t\r\n,") );
276   if( ostk1.CountTokens( ) <=0 )         return( false );
277 
278   // Determine how many nodes to look for based on the component type
279   switch( m_eType )
280   {
281     case eCPNT_CAP    :
282     case eCPNT_RES    :
283     case eCPNT_IND    :
284     case eCPNT_CIND   :
285     case eCPNT_DIODE  :
286     case eCPNT_VCVS   :
287     case eCPNT_CCCS   :
288     case eCPNT_VCCS   :
289     case eCPNT_CCVS   :
290     case eCPNT_IVS    :
291     case eCPNT_ICS    :
292     case eCPNT_NLDS   :
293     case eCPNT_NLDCS  :
294     case eCPNT_NLDVS  :
295     case eCPNT_STJ    : szNodeCnt = 2;                        break;
296 
297     case eCPNT_JFET   :
298     case eCPNT_MOSFET :
299     case eCPNT_MESFET :
300     case eCPNT_BJT    :
301     case eCPNT_VCSW   :
302     case eCPNT_CCSW   :
303     case eCPNT_URC    : szNodeCnt = 3;                        break;
304 
305     case eCPNT_TLINE  :
306     case eCPNT_LTRA   :
307     case eCPNT_TXL    : szNodeCnt = 4;                        break;
308 
309     case eCPNT_LOGIC  : szNodeCnt = ostk1.CountTokens( ) - 2; break;
310 
311     case eCPNT_CPL    :
312     case eCPNT_SUBCKT : szNodeCnt = ostk1.CountTokens( ) - 1; break;
313 
314     // For the default guess that all but the last token are nodes
315     default           : szNodeCnt = ostk1.CountTokens( ) - 1; break;
316   }
317   if( szNodeCnt > ostk1.CountTokens( ) ) return( false );
318 
319   // Extract the nodes the component is connected to
320   m_osaNodes.Empty( );
321   if( szNodeCnt > 0 )
322   {
323     for( sz1=0; sz1<szNodeCnt; sz1++ )
324       m_osaNodes.Add( ostk1.GetNextToken( ) );
325   }
326   else
327   {
328     for( sz1=0; sz1<ostk1.CountTokens( ); sz1++ )
329     {
330       if( isalpha( ostk1.GetString( ).GetChar( 0 ) ) ) break;
331       m_osaNodes.Add( ostk1.GetNextToken( ) );
332     }
333   }
334 
335   // Determine the device ports
336   GetPorts( );
337 
338   return( true );
339 }
340 
341 //**************************************************************************************************
342 // Set the component value.
343 //
344 // Argument List :
345 //   rosName - A reference to a string containing a compoent value
346 //
347 // Return Values :
348 //   true  - Success
349 //   false - Failure
350 
bSetValue(const wxString & rosValue)351 bool  Component::bSetValue( const wxString & rosValue )
352 {
353   wxString  os1;
354 
355   // Check if the string is empty
356   os1 = rosTrim( rosValue );
357   if( os1.IsEmpty( ) ) return( false );
358 
359   // Extract the component value
360   m_osValue = os1;
361 
362   return( bParseValue( ) );
363 }
364 
365 //**************************************************************************************************
366 // Get the component definition string.
367 //
368 // Return Values :
369 //   A reference to the component definition string
370 
rosGetString(void)371 const wxString & Component::rosGetString( void )
372 {
373   bFormat( );
374 
375   return( (wxString &) *this );
376 }
377 
378 //**************************************************************************************************
379 // Get the component nodes as a string separated by a comma.
380 //
381 // Return Values :
382 //   A reference to the component nodes string
383 
rosGetNodes(void)384 const wxString & Component::rosGetNodes( void )
385 {
386   static  wxString  osNodes;
387   size_t  sz1;
388 
389   osNodes.Empty( );
390 
391   if( ! m_osaNodes.IsEmpty( ) )
392   {
393     for( sz1=0; sz1<m_osaNodes.GetCount( ); sz1++ )
394     {
395       if( ! osNodes.IsEmpty( ) ) osNodes << wxT(",");
396       osNodes << m_osaNodes.Item( sz1 );
397     }
398   }
399 
400   return( osNodes );
401 }
402 
403 //**************************************************************************************************
404 // Get the numeric value as a mantissa and exponent if possible.
405 //
406 // Return Values :
407 //   A reference to the component nodes string
408 
rosGetNumValue(void)409 const wxString & Component::rosGetNumValue( void )
410 {
411   static  wxString   osNumValue;
412   wxStringTokenizer  ostk1;
413   wxString           os1;
414 
415   // Clear the local static variable
416   osNumValue.Empty( );
417 
418   // Tokenize the value string
419   ostk1 = m_osValue;
420 
421   // Attempt to parse a field in the value string as a numeric quantity
422   while( ostk1.HasMoreTokens( ) )
423   {
424     os1 = ostk1.GetNextToken( );
425 
426     if(      CnvtType::bIsInteger( os1 ) )
427     {
428       osNumValue = os1;
429       break;
430     }
431     else if( CnvtType::bIsFloat( os1 ) )
432     {
433       osNumValue = os1;
434       break;
435     }
436   }
437 
438   return( osNumValue );
439 }
440 
441 //**************************************************************************************************
442 // Get the component type.
443 //
444 // Argument List :
445 //   rosName - A component name
446 //
447 // Return Values :
448 //   An enumerate type indicating the type of the component
449 
eGetType(const wxString & rosName)450 eTypeCpnt  Component::eGetType( const wxString & rosName )
451 {
452   // Determine the component type from the first character of the name
453   switch( toupper( rosName.GetChar( 0 ) ) )
454   {
455     case wxT('B') : return( eCPNT_NLDS   );
456     case wxT('C') : return( eCPNT_CAP    );
457     case wxT('D') : return( eCPNT_DIODE  );
458     case wxT('E') : return( eCPNT_VCVS   );
459     case wxT('F') : return( eCPNT_CCCS   );
460     case wxT('G') : return( eCPNT_VCCS   );
461     case wxT('H') : return( eCPNT_CCVS   );
462     case wxT('I') : return( eCPNT_ICS    );
463     case wxT('J') : return( eCPNT_JFET   );
464     case wxT('K') : return( eCPNT_CIND   );
465     case wxT('L') : return( eCPNT_IND    );
466     case wxT('M') : return( eCPNT_MOSFET );
467     case wxT('O') : return( eCPNT_LTRA   );
468     case wxT('P') : return( eCPNT_CPL    );
469     case wxT('Q') : return( eCPNT_BJT    );
470     case wxT('R') : return( eCPNT_RES    );
471     case wxT('S') : return( eCPNT_VCSW   );
472     case wxT('T') : return( eCPNT_TLINE  );
473     case wxT('U') : return( eCPNT_URC    );
474     case wxT('V') : return( eCPNT_IVS    );
475     case wxT('W') : return( eCPNT_CCSW   );
476     case wxT('X') : return( eCPNT_SUBCKT );
477     case wxT('Y') : return( eCPNT_TXL    );
478     case wxT('Z') : return( eCPNT_MESFET );
479 
480     default       : return( eCPNT_NONE   );
481   }
482 }
483 
484 //**************************************************************************************************
485 // Get the units type (where appropriate).
486 //
487 // Argument List :
488 //   rosName - A component name
489 //
490 // Return Values :
491 //   An enumerate type indicating the type of units associated with this component
492 
eGetUnitsType(const wxString & rosName)493 eTypeUnits  Component::eGetUnitsType( const wxString & rosName )
494 {
495   // Determine the units type from the first character of the name
496   switch( toupper( rosName.GetChar( 0 ) ) )
497   {
498     case wxT('B') : return( eUNITS_EXP  );
499     case wxT('C') : return( eUNITS_CAP  );
500     case wxT('D') : return( eUNITS_NONE );
501     case wxT('E') : return( eUNITS_EXP  );
502     case wxT('F') : return( eUNITS_EXP  );
503     case wxT('G') : return( eUNITS_EXP  );
504     case wxT('H') : return( eUNITS_EXP  );
505     case wxT('I') : return( eUNITS_CURR );
506     case wxT('J') : return( eUNITS_NONE );
507     case wxT('K') : return( eUNITS_IND  );
508     case wxT('L') : return( eUNITS_IND  );
509     case wxT('M') : return( eUNITS_NONE );
510     case wxT('Q') : return( eUNITS_NONE );
511     case wxT('R') : return( eUNITS_RES  );
512     case wxT('S') : return( eUNITS_NONE );
513     case wxT('T') : return( eUNITS_NONE );
514     case wxT('U') : return( eUNITS_NONE );
515     case wxT('V') : return( eUNITS_VOLT );
516     case wxT('W') : return( eUNITS_NONE );
517     case wxT('X') : return( eUNITS_NONE );
518     case wxT('Y') : return( eUNITS_RES  );
519 
520     default       : return( eUNITS_NONE );
521   }
522 }
523 
524 //**************************************************************************************************
525 // Trim a component definition string by replacing all field separaters with a single space
526 // character and removing any line terminators.
527 //
528 // Argument List :
529 //   rosDefn - A reference to a string containing a component definition
530 //
531 // Return Values :
532 //   A reference to a string containing a trimmed copy of the component defn
533 
rosTrim(const wxString & rosDefn)534 const wxString & Component::rosTrim( const wxString & rosDefn )
535 {
536   static  wxString   osDefn;
537   wxStringTokenizer  ostk1;
538 
539   // Tokenize the component definition
540   ostk1.SetString( rosDefn, wxT(" \t\r\n"), wxTOKEN_STRTOK );
541 
542   // Reconstruct the component definition
543   osDefn = ostk1.GetNextToken( );
544   while( ostk1.HasMoreTokens( ) )
545     osDefn << wxT(' ') << ostk1.GetNextToken( );
546 
547   return( osDefn );
548 }
549 
550 //**************************************************************************************************
551 // Copy the contents of a wxString object.
552 //
553 // Argument List :
554 //   rosCmd - A reference to a string containing a component definition
555 //
556 // Return Values :
557 //   A reference to this object
558 
operator =(const wxString & rosCmd)559 wxString & Component::operator = ( const wxString & rosCmd )
560 {
561   bSetString( rosCmd );
562 
563   return( *((wxString *) this) );
564 }
565 
566 //**************************************************************************************************
567 // Copy the contents of another Component object.
568 //
569 // Argument List :
570 //   roCpnt - A reference to a Component object
571 //
572 // Return Values :
573 //   A reference to this object
574 
operator =(const Component & roCpnt)575 Component & Component::operator = ( const Component & roCpnt )
576 {
577   (wxString &) *this = (wxString &) roCpnt;
578 
579   m_eType    = roCpnt.m_eType;
580 
581   m_osName   = roCpnt.m_osName;
582   m_osaNodes = roCpnt.m_osaNodes;
583   m_osValue  = roCpnt.m_osValue;
584 
585   m_osaPorts = roCpnt.m_osaPorts;
586 
587   m_osErrMsg = roCpnt.m_osErrMsg;
588 
589   return( *this );
590 }
591 
592 //**************************************************************************************************
593 // Print the object attributes.
594 //
595 // Argument List :
596 //   rosPrefix - A prefix to every line displayed (usually just spaces)
597 
Print(const wxString & rosPrefix)598 void  Component::Print( const wxString & rosPrefix )
599 {
600   size_t  sz1;
601 
602   std::cout << rosPrefix.mb_str( ) << "wxString::        : " << this            ->mb_str( ) << '\n';
603 
604   std::cout << rosPrefix.mb_str( ) << "m_osErrMsg        : " << m_osErrMsg       .mb_str( ) << '\n';
605 
606   std::cout << rosPrefix.mb_str( ) << "m_eType           : ";
607   switch( m_eType )
608   {
609     case eCPNT_CAP    : std::cout << "eCPNT_CAP"   ; break; // Capacitor
610     case eCPNT_RES    : std::cout << "eCPNT_RES"   ; break; // Resistor
611     case eCPNT_IND    : std::cout << "eCPNT_IND"   ; break; // Inductor
612     case eCPNT_CIND   : std::cout << "eCPNT_CIND"  ; break; // Coupled (Mutual) Inductors
613     case eCPNT_DIODE  : std::cout << "eCPNT_DIODE" ; break; // Diode
614     case eCPNT_BJT    : std::cout << "eCPNT_BJT"   ; break; // BJT (Bipolar Junction Transistor)
615     case eCPNT_JFET   : std::cout << "eCPNT_JFET"  ; break; // JFET (Junction Field-Effect Transistor)
616     case eCPNT_MOSFET : std::cout << "eCPNT_MOSFET"; break; // MOSFET (Metal-Oxide Semiconductor Field-Effect Transistor)
617     case eCPNT_MESFET : std::cout << "eCPNT_MESFET"; break; // MESFET (Metal–Semiconductor Field Effect Transistor)
618     case eCPNT_VCVS   : std::cout << "eCPNT_VCVS"  ; break; // Voltage Controlled Voltage Source
619     case eCPNT_CCCS   : std::cout << "eCPNT_CCCS"  ; break; // Current Controlled Current Source
620     case eCPNT_VCCS   : std::cout << "eCPNT_VCCS"  ; break; // Voltage Controlled Current Source
621     case eCPNT_CCVS   : std::cout << "eCPNT_CCVS"  ; break; // Current Controlled Voltage Source
622     case eCPNT_TLINE  : std::cout << "eCPNT_TLINE" ; break; // Lossless Transmission Line
623     case eCPNT_LTRA   : std::cout << "eCPNT_LTRA"  ; break; // Lossy Transmission Line (LTRA)
624     case eCPNT_CPL    : std::cout << "eCPNT_CPL"   ; break; // Coupled Multi-conductor Transmission Line (CPL)
625     case eCPNT_TXL    : std::cout << "eCPNT_TXL"   ; break; // Single Lossy Transmission Line (TXL)
626     case eCPNT_URC    : std::cout << "eCPNT_URC"   ; break; // Uniform Distributed RC Transmission Line (URC)
627     case eCPNT_ICS    : std::cout << "eCPNT_ICS"   ; break; // Independent Current Source
628     case eCPNT_IVS    : std::cout << "eCPNT_IVS"   ; break; // Independent Voltage Source
629     case eCPNT_NLDS   : std::cout << "eCPNT_NLDS"  ; break; // Non-Linear Dependent Source
630     case eCPNT_NLDCS  : std::cout << "eCPNT_NLDCS" ; break; // Non-Linear Dependent Current Source
631     case eCPNT_NLDVS  : std::cout << "eCPNT_NLDVS" ; break; // Non-Linear Dependent Voltage Source
632     case eCPNT_CCSW   : std::cout << "eCPNT_CCSW"  ; break; // Current Controlled Switch
633     case eCPNT_VCSW   : std::cout << "eCPNT_VCSW"  ; break; // Voltage Controlled Switch
634     case eCPNT_SUBCKT : std::cout << "eCPNT_SUBCKT"; break; // Sub-circuit
635     case eCPNT_LOGIC  : std::cout << "eCPNT_LOGIC" ; break; // Logic Device
636     case eCPNT_STJ    : std::cout << "eCPNT_STJ"   ; break; // Super-conducting Tunnel Junction
637 
638     default           : std::cout << "Invalid";
639   }
640   std::cout << '\n';
641 
642   std::cout << rosPrefix.mb_str( ) << "m_osName          : " << m_osName         .mb_str( ) << '\n';
643 
644   std::cout << rosPrefix.mb_str( ) << "m_osaNodes[ ]     : ";
645   for( sz1=0; sz1<m_osaNodes.GetCount( ); sz1++ )
646   {
647     if( sz1 > 0 ) std::cout << ", ";
648     std::cout << m_osaNodes.Item( sz1 ).mb_str( );
649   }
650   std::cout << '\n';
651 
652   std::cout << rosPrefix.mb_str( ) << "m_osaPorts[ ]     : ";
653   for( sz1=0; sz1<m_osaPorts.GetCount( ); sz1++ )
654   {
655     if( sz1 > 0 ) std::cout << " ";
656     std::cout << m_osaPorts.Item( sz1 ).mb_str( );
657   }
658   std::cout << '\n';
659 
660   std::cout << rosPrefix.mb_str( ) << "m_osValue         : " << m_osValue        .mb_str( ) << '\n';
661 
662   std::cout << rosPrefix.mb_str( ) << "rosGetNumValue( ) : " << rosGetNumValue( ).mb_str( ) << '\n';
663 
664   std::cout << rosPrefix.mb_str( ) << "eGetUnitsType( )  : ";
665   switch( eGetUnitsType( m_osName ) )
666   {
667     case eUNITS_CAP  : std::cout << "eUNITS_CAP";  break;
668     case eUNITS_IND  : std::cout << "eUNITS_IND";  break;
669     case eUNITS_RES  : std::cout << "eUNITS_RES";  break;
670     case eUNITS_VOLT : std::cout << "eUNITS_VOLT"; break;
671     case eUNITS_CURR : std::cout << "eUNITS_CURR"; break;
672     case eUNITS_TIME : std::cout << "eUNITS_TIME"; break;
673     case eUNITS_FREQ : std::cout << "eUNITS_FREQ"; break;
674     case eUNITS_PHAD : std::cout << "eUNITS_PHAD"; break;
675     case eUNITS_PHAR : std::cout << "eUNITS_PHAR"; break;
676     case eUNITS_TMPC : std::cout << "eUNITS_TMPC"; break;
677     case eUNITS_TMPF : std::cout << "eUNITS_TMPF"; break;
678     case eUNITS_EXP  : std::cout << "eUNITS_EXP";  break;
679     case eUNITS_NONE : std::cout << "eUNITS_NONE"; break;
680 
681     default          : std::cout << "Invalid";     break;
682   }
683   std::cout << '\n';
684 }
685 
686 //**************************************************************************************************
687 //                                          Test Utility                                           *
688 //**************************************************************************************************
689 
690 #ifdef TEST_COMPONENT
691 
692 using  namespace  std;
693 
694 // Function prototypes
695 
696 void  Usage( char * psAppName );
697 
698 //**************************************************************************************************
699 
main(int argc,char * argv[])700 int  main( int argc, char * argv[ ] )
701 {
702   wxString  osCpnt;
703   wxString  os1;
704 
705   // Validate the argument count passed to the application
706   if( argc > 2 )                    { Usage( argv[0] ); exit( EXIT_FAILURE ); }
707 
708   // Process the command line arguments
709   os1 = wxConvLibc.cMB2WC( argv[ 1 ] );
710   if( argc > 1 )
711   {
712     if( os1.at( 0 ) == wxT('-') )
713     {
714       if( os1.at( 1 ) == wxT('h') ) { Usage( argv[0] ); exit( EXIT_SUCCESS ); }
715       else                          { Usage( argv[0] ); exit( EXIT_FAILURE ); }
716     }
717   }
718 
719   // Display the utility banner
720   cout << "\n  Component Class Test Utility"
721        << "\n   Version 1.07 (19/08/2011)\n";
722 
723   // Create a GNU-CAP OP command object
724   Component  tCpnt;
725 
726   // Use the following command example to check the formatter and the parser :
727   osCpnt = wxT("Vin	 2	0	 AC	1V"); // This contains TABs and SPACEs
728   cout << "\nCpnt defn to test : "
729        << osCpnt.mb_str( ) << "\n\n";
730 
731   // ******************** Test the formatter ********************
732   cout << "Test the component formatter :";
733 
734   // Set things up for a formatter test
735   tCpnt.bClear( );
736   tCpnt.bSetName ( wxT("Vin")   );
737   tCpnt.bSetNodes( wxT("2,0")   );
738   tCpnt.bSetValue( wxT("AC 1V") );
739 
740   // Run the formatter
741   cout << "\n  Run formatter  : ";
742   if( tCpnt.bFormat( ) )
743        cout << "OK";
744   else cout << "FAULT (" << tCpnt.rosGetErrMsg( ).mb_str( ) << ')';
745 
746   // Test the formatter output
747   cout << "\n  Test format    : ";
748   if( (wxString) tCpnt == Component::rosTrim( osCpnt ) )
749     cout << "OK\n" << "  Component defn : "
750          << tCpnt.rosGetString( ).mb_str( ) << '\n';
751   else
752   { // There's been an error so print the component contents
753     cout << "FAULT\n";
754     cout << "  tCpnt Contents : \n";
755     tCpnt.Print( wxT("    ") );
756   }
757 
758   cout << "\n";
759 
760   // ********************* Test the parser *********************
761   cout << "Test the component parser :";
762 
763   // Set things up for a parser test
764   tCpnt.bClear( );
765   tCpnt = osCpnt;
766 
767   // Run the parser
768   cout << "\n  Run parser     : ";
769   if( tCpnt.bParse( ) )
770        cout << "OK";
771   else cout << "FAULT (" << tCpnt.rosGetErrMsg( ).mb_str( ) << ')';
772 
773   // Test the parser output
774   tCpnt.bFormat( );
775   cout << "\n  Test format    : ";
776   if( (wxString) tCpnt == Component::rosTrim( osCpnt ) )
777     cout << "OK\n" << "  Component defn : "
778          << tCpnt.rosGetString( ).mb_str( ) << '\n';
779   else
780   { // There's been an error so print the component contents
781     cout << "FAULT\n";
782     cout << "  tCpnt Contents : \n";
783     tCpnt.Print( wxT("    ") );
784   }
785 
786   cout << "\n";
787 
788   exit( EXIT_SUCCESS );
789 }
790 
791 //**************************************************************************************************
792 
Usage(char * psAppName)793 void  Usage( char * psAppName )
794 {
795   cout << "\nUsage   : " << psAppName << " [-OPTIONS]"
796        << "\nOptions :"
797        << "\n  -h : Print usage (this message)\n";
798 }
799 
800 #endif // TEST_COMPONENT
801 
802 //**************************************************************************************************
803