LCOV - code coverage report
Current view: top level - INDI/libcommon - IndiXmlParser.cpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 4.8 % 930 45
Test Date: 2026-01-03 21:03:39 Functions: 21.1 % 38 8

            Line data    Source code
       1              : /// IndiXmlParser.cpp
       2              : ///
       3              : /// @author Paul Grenz
       4              : ///
       5              : ////////////////////////////////////////////////////////////////////////////////
       6              : 
       7              : #include <stdexcept>
       8              : #include <string>
       9              : #include <cstring>
      10              : #include <cstdlib>
      11              : #include <iostream>
      12              : #include <iomanip>
      13              : #include <sstream>
      14              : #include "../liblilxml/base64.h"
      15              : #include "IndiMessage.hpp"
      16              : #include "IndiProperty.hpp"
      17              : #include "IndiXmlParser.hpp"
      18              : 
      19              : using std::runtime_error;
      20              : using std::string;
      21              : using std::stringbuf;
      22              : using std::stringstream;
      23              : using std::boolalpha;
      24              : using std::vector;
      25              : using std::istream;
      26              : using std::ostream;
      27              : using pcf::IndiElement;
      28              : using pcf::IndiMessage;
      29              : using pcf::IndiProperty;
      30              : using pcf::IndiXmlParser;
      31              : 
      32              : ////////////////////////////////////////////////////////////////////////////////
      33              : /// Constructor.
      34              : 
      35           12 : IndiXmlParser::IndiXmlParser( const string &szProtocolVersion )
      36              : {
      37           12 :   init( szProtocolVersion );
      38           12 : }
      39              : 
      40              : ////////////////////////////////////////////////////////////////////////////////
      41              : /// Constructor from an existing IndiMessage.
      42              : 
      43           10 : IndiXmlParser::IndiXmlParser( const IndiMessage &imSend,
      44           10 :                               const string &szProtocolVersion )
      45              : {
      46           10 :   init( szProtocolVersion );
      47              : 
      48           10 :   const IndiProperty &ipSend = imSend.getProperty();
      49              : 
      50              :   // Each Indi message has different attributes depending on the type of message.
      51           10 :   switch ( imSend.getType() )
      52              :   {
      53            0 :     case IndiMessage::Define:
      54            0 :       switch ( ipSend.getType() )
      55              :       {
      56            0 :         case IndiProperty::BLOB: createDefBLOBVector( ipSend ); break;
      57            0 :         case IndiProperty::Light: createDefLightVector( ipSend ); break;
      58            0 :         case IndiProperty::Number: createDefNumberVector( ipSend ); break;
      59            0 :         case IndiProperty::Switch: createDefSwitchVector( ipSend ); break;
      60            0 :         case IndiProperty::Text: createDefTextVector( ipSend ); break;
      61            0 :         default:
      62              :         case IndiProperty::Unknown:
      63            0 :           throw runtime_error( "Unknown INDI property DEF type is not allowed." );
      64              :           break;
      65              :       }
      66            0 :       break;
      67              : 
      68            0 :     case IndiMessage::Delete:
      69            0 :       createDelProperty( ipSend );
      70            0 :       break;
      71              : 
      72            0 :     case IndiMessage::EnableBLOB:
      73            0 :       createEnableBLOB( ipSend );
      74            0 :       break;
      75              : 
      76           10 :     case IndiMessage::GetProperties:
      77           10 :       createGetProperties( ipSend );
      78           10 :       break;
      79              : 
      80            0 :     case IndiMessage::Message:
      81            0 :       createMessage( ipSend );
      82            0 :       break;
      83              : 
      84            0 :     case IndiMessage::NewProperty:
      85            0 :       switch ( ipSend.getType() )
      86              :       {
      87            0 :         case IndiProperty::BLOB: createNewBLOBVector( ipSend ); break;
      88            0 :         case IndiProperty::Number: createNewNumberVector( ipSend ); break;
      89            0 :         case IndiProperty::Switch: createNewSwitchVector( ipSend ); break;
      90            0 :         case IndiProperty::Text: createNewTextVector( ipSend ); break;
      91            0 :         default:
      92              :         case IndiProperty::Unknown:
      93            0 :           throw runtime_error( "Unknown INDI property NEW type is not allowed." );
      94              :           break;
      95              :       }
      96            0 :       break;
      97              : 
      98            0 :     case IndiMessage::SetProperty:
      99            0 :       switch ( ipSend.getType() )
     100              :       {
     101            0 :         case IndiProperty::BLOB: createSetBLOBVector( ipSend ); break;
     102            0 :         case IndiProperty::Light: createSetLightVector( ipSend ); break;
     103            0 :         case IndiProperty::Number: createSetNumberVector( ipSend ); break;
     104            0 :         case IndiProperty::Switch: createSetSwitchVector( ipSend ); break;
     105            0 :         case IndiProperty::Text: createSetTextVector( ipSend ); break;
     106            0 :         default:
     107              :         case IndiProperty::Unknown:
     108            0 :           throw runtime_error( "Unknown INDI property SET type is not allowed." );
     109              :           break;
     110              :       }
     111            0 :       break;
     112              : 
     113            0 :     case IndiMessage::Unknown:
     114            0 :       throw runtime_error( "Unknown INDI property type is not allowed." );
     115              :       break;
     116              :   }
     117           10 : }
     118              : 
     119              : ////////////////////////////////////////////////////////////////////////////////
     120              : /// createSafeXmlString
     121              : /// This takes any string and replaces the '&', '<', '>', '\', and '"'
     122              : /// with its equivalent XML entity: &amp; &lt; &gt; &apos; and &quot;
     123              : 
     124            0 : string IndiXmlParser::createSafeXmlString( const string &szText )
     125              : {
     126            0 :   return ::entityXML( (char*)( szText.c_str() ) );
     127              : }
     128              : 
     129              : ////////////////////////////////////////////////////////////////////////////////
     130              : // DefTextVector REQUIRED: device name state perm
     131              : // DefTextVector IMPLIED:  label group timeout timestamp message
     132              : // DefText REQUIRED: name
     133              : // DefText IMPLIED: label
     134              : 
     135            0 : void IndiXmlParser::createDefTextVector( const IndiProperty &ip )
     136              : {
     137              :   // What kind of message is this?
     138            0 :   string szTag = "defTextVector";
     139            0 :   string szElementTag = "defText";
     140            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     141              : 
     142              :   // Clear out the xml stream.
     143            0 :   m_ssXml.str("");
     144            0 :   m_ssXml << "<" << szTag;
     145              : 
     146              :   // "required" means that the attribute must be added and contain a valid
     147              :   // entry. If it is not part of the generated XML, it is an error.
     148            0 :   if ( ip.hasValidDevice() == false )
     149            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     150            0 :   if ( ip.hasValidName() == false )
     151            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     152            0 :   if ( ip.hasValidState() == false )
     153            0 :     throw runtime_error( szDescrip + " must have attribute 'state' defined." );
     154            0 :   if ( ip.hasValidPerm() == false )
     155            0 :     throw runtime_error( szDescrip + " must have attribute 'perm' defined." );
     156              : 
     157            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     158            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     159            0 :   m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     160            0 :   m_ssXml << " perm=\"" << ip.getPropertyPermString( ip.getPerm() ) << "\"";
     161              : 
     162              :   // "implied" means that if they are not defined, don't add them. Adding an
     163              :   // empty "implied" attribute to the generated XML is an error.
     164            0 :   if ( ip.hasValidLabel() == true )
     165            0 :     m_ssXml << " label=\"" << ip.getLabel() << "\"";
     166            0 :   if ( ip.hasValidGroup() == true )
     167            0 :     m_ssXml << " group=\"" << ip.getGroup() << "\"";
     168            0 :   if ( ip.hasValidTimeout() == true )
     169            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     170            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     171            0 :   if ( ip.hasValidMessage() == true )
     172            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     173              : 
     174            0 :   m_ssXml << ">\r\n";
     175              : 
     176            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     177              :   {
     178            0 :     m_ssXml << "\t<" << szElementTag;
     179              : 
     180              :     // "required" means that the attribute must be added and contain a valid
     181              :     // entry. If it is not part of the generated XML, it is an error.
     182            0 :     if ( ip[ii].hasValidName() == false )
     183            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     184              : 
     185            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     186              : 
     187              :     // "implied" means that if they are not defined, don't add them. Adding an
     188              :     // empty "implied" attribute to the generated XML is an error.
     189            0 :     if ( ip[ii].hasValidLabel() == true )
     190            0 :       m_ssXml << " label=\"" << ip[ii].getLabel() << "\"";
     191              : 
     192            0 :     m_ssXml << ">\r\n";
     193              : 
     194              :     // Now add the data for the element...
     195            0 :     m_ssXml << createSafeXmlString( ip[ii].getValue() ) << "\r\n";
     196            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     197              :   }
     198            0 :   m_ssXml << "</" << szTag << ">\r\n";
     199            0 : }
     200              : 
     201              : ////////////////////////////////////////////////////////////////////////////////
     202              : // SetTextVector REQUIRED: device name
     203              : // SetTextVector IMPLIED:  state timeout timestamp message
     204              : // oneText REQUIRED: name
     205              : 
     206            0 : void IndiXmlParser::createSetTextVector( const IndiProperty &ip )
     207              : {
     208              :   // What kind of message is this?
     209            0 :   string szTag = "setTextVector";
     210            0 :   string szElementTag = "oneText";
     211            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     212              : 
     213              :   // Clear out the xml stream.
     214            0 :   m_ssXml.str("");
     215            0 :   m_ssXml << "<" << szTag;
     216              : 
     217              :   // "required" means that the attribute must be added and contain a valid
     218              :   // entry. If it is not part of the generated XML, it is an error.
     219            0 :   if ( ip.hasValidDevice() == false )
     220            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     221            0 :   if ( ip.hasValidName() == false )
     222            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     223              : 
     224            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     225            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     226              : 
     227              :   // "implied" means that if they are not defined, don't add them. Adding an
     228              :   // empty "implied" attribute to the generated XML is an error.
     229            0 :   if ( ip.hasValidState() == true )
     230            0 :     m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     231            0 :   if ( ip.hasValidTimeout() == true )
     232            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     233            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     234            0 :   if ( ip.hasValidMessage() == true )
     235            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     236              : 
     237            0 :   m_ssXml << ">\r\n";
     238              : 
     239            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     240              :   {
     241            0 :     m_ssXml << "\t<" << szElementTag;
     242              : 
     243              :     // "required" means that the attribute must be added and contain a valid
     244              :     // entry. If it is not part of the generated XML, it is an error.
     245            0 :     if ( ip[ii].hasValidName() == false )
     246            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     247              : 
     248            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     249              : 
     250            0 :     m_ssXml << ">\r\n";
     251              : 
     252              :     // Now add the data for the element...
     253            0 :     m_ssXml << createSafeXmlString( ip[ii].getValue() ) << "\r\n";
     254            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     255              :   }
     256            0 :   m_ssXml << "</" << szTag << ">\r\n";
     257            0 : }
     258              : 
     259              : ////////////////////////////////////////////////////////////////////////////////
     260              : // NewTextVector REQUIRED: device name
     261              : // NewTextVector IMPLIED:  timestamp
     262              : // oneText REQUIRED: name
     263              : 
     264            0 : void IndiXmlParser::createNewTextVector( const IndiProperty &ip )
     265              : {
     266              :   // What kind of message is this?
     267            0 :   string szTag = "newTextVector";
     268            0 :   string szElementTag = "oneText";
     269            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     270              : 
     271              :   // Clear out the xml stream.
     272            0 :   m_ssXml.str("");
     273            0 :   m_ssXml << "<" << szTag;
     274              : 
     275              :   // "required" means that the attribute must be added and contain a valid
     276              :   // entry. If it is not part of the generated XML, it is an error.
     277            0 :   if ( ip.hasValidDevice() == false )
     278            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     279            0 :   if ( ip.hasValidName() == false )
     280            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     281              : 
     282            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     283            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     284              : 
     285              :   // "implied" means that if they are not defined, don't add them. Adding an
     286              :   // empty "implied" attribute to the generated XML is an error.
     287            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     288              : 
     289            0 :   m_ssXml << ">\r\n";
     290              : 
     291            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     292              :   {
     293            0 :     m_ssXml << "\t<" << szElementTag;
     294              : 
     295              :     // "required" means that the attribute must be added and contain a valid
     296              :     // entry. If it is not part of the generated XML, it is an error.
     297            0 :     if ( ip[ii].hasValidName() == false )
     298            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     299              : 
     300            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     301              : 
     302            0 :     m_ssXml << ">\r\n";
     303              : 
     304              :     // Now add the data for the element...
     305            0 :     m_ssXml << createSafeXmlString( ip[ii].getValue() ) << "\r\n";
     306            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     307              :   }
     308            0 :   m_ssXml << "</" << szTag << ">\r\n";
     309            0 : }
     310              : 
     311              : ////////////////////////////////////////////////////////////////////////////////
     312              : // DefNumberVector REQUIRED: device name state perm
     313              : // DefNumberVector IMPLIED:  label group timeout timestamp message
     314              : // DefNumber REQUIRED: name format min max step
     315              : // DefNumber IMPLIED: label
     316              : 
     317            0 : void IndiXmlParser::createDefNumberVector( const IndiProperty &ip )
     318              : {
     319              :   // What kind of message is this?
     320            0 :   string szTag = "defNumberVector";
     321            0 :   string szElementTag = "defNumber";
     322            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     323              : 
     324              :   // Clear out the xml stream.
     325            0 :   m_ssXml.str("");
     326            0 :   m_ssXml << "<" << szTag;
     327              : 
     328              :   // "required" means that the attribute must be added and contain a valid
     329              :   // entry. If it is not part of the generated XML, it is an error.
     330            0 :   if ( ip.hasValidDevice() == false )
     331            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     332            0 :   if ( ip.hasValidName() == false )
     333            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     334            0 :   if ( ip.hasValidState() == false )
     335            0 :     throw runtime_error( szDescrip + " must have attribute 'state' defined." );
     336            0 :   if ( ip.hasValidPerm() == false )
     337            0 :     throw runtime_error( szDescrip + " must have attribute 'perm' defined." );
     338              : 
     339            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     340            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     341            0 :   m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     342            0 :   m_ssXml << " perm=\"" << ip.getPropertyPermString( ip.getPerm() ) << "\"";
     343              : 
     344              :   // "implied" means that if they are not defined, don't add them. Adding an
     345              :   // empty "implied" attribute to the generated XML is an error.
     346            0 :   if ( ip.hasValidLabel() == true )
     347            0 :     m_ssXml << " label=\"" << ip.getLabel() << "\"";
     348            0 :   if ( ip.hasValidGroup() == true )
     349            0 :     m_ssXml << " group=\"" << ip.getGroup() << "\"";
     350            0 :   if ( ip.hasValidTimeout() == true )
     351            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     352            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     353            0 :   if ( ip.hasValidMessage() == true )
     354            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     355              : 
     356            0 :   m_ssXml << ">\r\n";
     357              : 
     358            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     359              :   {
     360            0 :     m_ssXml << "\t<" << szElementTag;
     361              : 
     362              :     // "required" means that the attribute must be added and contain a valid
     363              :     // entry. If it is not part of the generated XML, it is an error.
     364            0 :     if ( ip[ii].hasValidName() == false )
     365            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     366            0 :     if ( ip[ii].hasValidFormat() == false )
     367            0 :       throw runtime_error( szElementTag + " must have attribute 'format' defined." );
     368            0 :     if ( ip[ii].hasValidMin() == false )
     369            0 :       throw runtime_error( szElementTag + " must have attribute 'min' defined." );
     370            0 :     if ( ip[ii].hasValidMax() == false )
     371            0 :       throw runtime_error( szElementTag + " must have attribute 'max' defined." );
     372            0 :     if ( ip[ii].hasValidStep() == false )
     373            0 :       throw runtime_error( szElementTag + " must have attribute 'step' defined." );
     374              : 
     375            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     376            0 :     m_ssXml << " format=\"" << ip[ii].getFormat() << "\"";
     377            0 :     m_ssXml << " min=\"" << ip[ii].getMin() << "\"";
     378            0 :     m_ssXml << " max=\"" << ip[ii].getMax() << "\"";
     379            0 :     m_ssXml << " step=\"" << ip[ii].getStep() << "\"";
     380              : 
     381              :     // "implied" means that if they are not defined, don't add them. Adding an
     382              :     // empty "implied" attribute to the generated XML is an error.
     383            0 :     if ( ip[ii].hasValidLabel() == true )
     384            0 :       m_ssXml << " label=\"" << ip[ii].getLabel() << "\"";
     385              : 
     386            0 :     m_ssXml << ">\r\n";
     387              : 
     388              :     // Now add the data for the element...
     389            0 :     m_ssXml << createSafeXmlString( ip[ii].getValue() ) << "\r\n";
     390            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     391              :   }
     392            0 :   m_ssXml << "</" << szTag << ">\r\n";
     393            0 : }
     394              : 
     395              : ////////////////////////////////////////////////////////////////////////////////
     396              : // SetNumberVector REQUIRED: device name
     397              : // SetNumberVector IMPLIED:  state timeout timestamp message
     398              : // oneNumber REQUIRED: name
     399              : 
     400            0 : void IndiXmlParser::createSetNumberVector( const IndiProperty &ip )
     401              : {
     402              :   // What kind of message is this?
     403            0 :   string szTag = "setNumberVector";
     404            0 :   string szElementTag = "oneNumber";
     405            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     406              : 
     407              :   // Clear out the xml stream.
     408            0 :   m_ssXml.str("");
     409            0 :   m_ssXml << "<" << szTag;
     410              : 
     411              :   // "required" means that the attribute must be added and contain a valid
     412              :   // entry. If it is not part of the generated XML, it is an error.
     413            0 :   if ( ip.hasValidDevice() == false )
     414            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     415            0 :   if ( ip.hasValidName() == false )
     416            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     417              : 
     418            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     419            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     420              : 
     421              :   // "implied" means that if they are not defined, don't add them. Adding an
     422              :   // empty "implied" attribute to the generated XML is an error.
     423            0 :   if ( ip.hasValidState() == true )
     424            0 :     m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     425            0 :   if ( ip.hasValidTimeout() == true )
     426            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     427            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     428            0 :   if ( ip.hasValidMessage() == true )
     429            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     430              : 
     431            0 :   m_ssXml << ">\r\n";
     432              : 
     433            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     434              :   {
     435            0 :     m_ssXml << "\t<" << szElementTag;
     436              : 
     437              :     // "required" means that the attribute must be added and contain a valid
     438              :     // entry. If it is not part of the generated XML, it is an error.
     439            0 :     if ( ip[ii].hasValidName() == false )
     440            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     441              : 
     442            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     443              : 
     444            0 :     m_ssXml << ">\r\n";
     445              : 
     446              :     // Now add the data for the element...
     447            0 :     m_ssXml << createSafeXmlString( ip[ii].getValue() ) << "\r\n";
     448            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     449              :   }
     450            0 :   m_ssXml << "</" << szTag << ">\r\n";
     451            0 : }
     452              : 
     453              : ////////////////////////////////////////////////////////////////////////////////
     454              : // NewNumberVector REQUIRED: device name
     455              : // NewNumberVector IMPLIED:  timestamp
     456              : // oneNumber REQUIRED: name
     457              : 
     458            0 : void IndiXmlParser::createNewNumberVector( const IndiProperty &ip )
     459              : {
     460              :   // What kind of message is this?
     461            0 :   string szTag = "newNumberVector";
     462            0 :   string szElementTag = "oneNumber";
     463            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     464              : 
     465              :   // Clear out the xml stream.
     466            0 :   m_ssXml.str("");
     467            0 :   m_ssXml << "<" << szTag;
     468              : 
     469              :   // "required" means that the attribute must be added and contain a valid
     470              :   // entry. If it is not part of the generated XML, it is an error.
     471            0 :   if ( ip.hasValidDevice() == false )
     472            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     473            0 :   if ( ip.hasValidName() == false )
     474            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     475              : 
     476            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     477            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     478              : 
     479              :   // "implied" means that if they are not defined, don't add them. Adding an
     480              :   // empty "implied" attribute to the generated XML is an error.
     481            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     482              : 
     483            0 :   m_ssXml << ">\r\n";
     484              : 
     485            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     486              :   {
     487            0 :     m_ssXml << "\t<" << szElementTag;
     488              : 
     489              :     // "required" means that the attribute must be added and contain a valid
     490              :     // entry. If it is not part of the generated XML, it is an error.
     491            0 :     if ( ip[ii].hasValidName() == false )
     492            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     493              : 
     494            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     495              : 
     496            0 :     m_ssXml << ">\r\n";
     497              : 
     498              :     // Now add the data for the element...
     499            0 :     m_ssXml << createSafeXmlString( ip[ii].getValue() ) << "\r\n";
     500            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     501              :   }
     502            0 :   m_ssXml << "</" << szTag << ">\r\n";
     503            0 : }
     504              : 
     505              : ////////////////////////////////////////////////////////////////////////////////
     506              : // DefSwitchVector REQUIRED: device name state perm rule
     507              : // DefSwitchVector IMPLIED:  label group timeout timestamp message
     508              : // DefSwitch REQUIRED: name
     509              : // DefSwitch IMPLIED: label
     510              : 
     511            0 : void IndiXmlParser::createDefSwitchVector( const IndiProperty &ip )
     512              : {
     513              :   // What kind of message is this?
     514            0 :   string szTag = "defSwitchVector";
     515            0 :   string szElementTag = "defSwitch";
     516            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     517              : 
     518              :   // Clear out the xml stream.
     519            0 :   m_ssXml.str("");
     520            0 :   m_ssXml << "<" << szTag;
     521              : 
     522              :   // "required" means that the attribute must be added and contain a valid
     523              :   // entry. If it is not part of the generated XML, it is an error.
     524            0 :   if ( ip.hasValidDevice() == false )
     525            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     526            0 :   if ( ip.hasValidName() == false )
     527            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     528            0 :   if ( ip.hasValidState() == false )
     529            0 :     throw runtime_error( szDescrip + " must have attribute 'state' defined." );
     530            0 :   if ( ip.hasValidPerm() == false )
     531            0 :     throw runtime_error( szDescrip + " must have attribute 'perm' defined." );
     532            0 :   if ( ip.hasValidRule() == false )
     533            0 :     throw runtime_error( szDescrip + " must have attribute 'rule' defined." );
     534              : 
     535            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     536            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     537            0 :   m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     538            0 :   m_ssXml << " perm=\"" << ip.getPropertyPermString( ip.getPerm() ) << "\"";
     539            0 :   m_ssXml << " rule=\"" << ip.getSwitchRuleString( ip.getRule() ) << "\"";
     540              : 
     541              :   // "implied" means that if they are not defined, don't add them. Adding an
     542              :   // empty "implied" attribute to the generated XML is an error.
     543            0 :   if ( ip.hasValidLabel() == true )
     544            0 :     m_ssXml << " label=\"" << ip.getLabel() << "\"";
     545            0 :   if ( ip.hasValidGroup() == true )
     546            0 :     m_ssXml << " group=\"" << ip.getGroup() << "\"";
     547            0 :   if ( ip.hasValidTimeout() == true )
     548            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     549            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     550            0 :   if ( ip.hasValidMessage() == true )
     551            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     552              : 
     553            0 :   m_ssXml << ">\r\n";
     554              : 
     555            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     556              :   {
     557            0 :     m_ssXml << "\t<" << szElementTag;
     558              : 
     559              :     // "required" means that the attribute must be added and contain a valid
     560              :     // entry. If it is not part of the generated XML, it is an error.
     561            0 :     if ( ip[ii].hasValidName() == false )
     562            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     563              : 
     564            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     565              : 
     566              :     // "implied" means that if they are not defined, don't add them. Adding an
     567              :     // empty "implied" attribute to the generated XML is an error.
     568            0 :     if ( ip[ii].hasValidLabel() == true )
     569            0 :       m_ssXml << " label=\"" << ip[ii].getLabel() << "\"";
     570              : 
     571            0 :     m_ssXml << ">\r\n";
     572              : 
     573              :     // Now add the data for the element...
     574            0 :     m_ssXml << IndiElement::getSwitchStateString( ip[ii].getSwitchState() ) << "\r\n";
     575            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     576              :   }
     577            0 :   m_ssXml << "</" << szTag << ">\r\n";
     578            0 : }
     579              : 
     580              : ////////////////////////////////////////////////////////////////////////////////
     581              : // SetSwitchVector REQUIRED: device name
     582              : // SetSwitchVector IMPLIED:  state timeout timestamp message
     583              : // oneSwitch REQUIRED: name
     584              : 
     585            0 : void IndiXmlParser::createSetSwitchVector( const IndiProperty &ip )
     586              : {
     587              :   // What kind of message is this?
     588            0 :   string szTag = "setSwitchVector";
     589            0 :   string szElementTag = "oneSwitch";
     590            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     591              : 
     592              :   // Clear out the xml stream.
     593            0 :   m_ssXml.str("");
     594            0 :   m_ssXml << "<" << szTag;
     595              : 
     596              :   // "required" means that the attribute must be added and contain a valid
     597              :   // entry. If it is not part of the generated XML, it is an error.
     598            0 :   if ( ip.hasValidDevice() == false )
     599            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     600            0 :   if ( ip.hasValidName() == false )
     601            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     602              : 
     603            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     604            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     605              : 
     606              :   // "implied" means that if they are not defined, don't add them. Adding an
     607              :   // empty "implied" attribute to the generated XML is an error.
     608            0 :   if ( ip.hasValidState() == true )
     609            0 :     m_ssXml << " state=\"" << IndiProperty::getPropertyStateString( ip.getState() ) << "\"";
     610            0 :   if ( ip.hasValidTimeout() == true )
     611            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     612            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     613            0 :   if ( ip.hasValidMessage() == true )
     614            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     615              : 
     616            0 :   m_ssXml << ">\r\n";
     617              : 
     618            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     619              :   {
     620            0 :     m_ssXml << "\t<" << szElementTag;
     621              : 
     622              :     // "required" means that the attribute must be added and contain a valid
     623              :     // entry. If it is not part of the generated XML, it is an error.
     624            0 :     if ( ip[ii].hasValidName() == false )
     625            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     626              : 
     627            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     628              : 
     629            0 :     m_ssXml << ">\r\n";
     630              : 
     631              :     // Now add the data for the element...
     632            0 :     m_ssXml << IndiElement::getSwitchStateString( ip[ii].getSwitchState() ) << "\r\n";
     633            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     634              :   }
     635            0 :   m_ssXml << "</" << szTag << ">\r\n";
     636            0 : }
     637              : 
     638              : ////////////////////////////////////////////////////////////////////////////////
     639              : // NewSwitchVector REQUIRED: device name
     640              : // NewSwitchVector IMPLIED:  timestamp
     641              : // oneSwitch REQUIRED: name
     642              : 
     643            0 : void IndiXmlParser::createNewSwitchVector( const IndiProperty &ip )
     644              : {
     645              :   // What kind of message is this?
     646            0 :   string szTag = "newSwitchVector";
     647            0 :   string szElementTag = "oneSwitch";
     648            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     649              : 
     650              :   // Clear out the xml stream.
     651            0 :   m_ssXml.str("");
     652            0 :   m_ssXml << "<" << szTag;
     653              : 
     654              :   // "required" means that the attribute must be added and contain a valid
     655              :   // entry. If it is not part of the generated XML, it is an error.
     656            0 :   if ( ip.hasValidDevice() == false )
     657            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     658            0 :   if ( ip.hasValidName() == false )
     659            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     660              : 
     661            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     662            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     663              : 
     664              :   // "implied" means that if they are not defined, don't add them. Adding an
     665              :   // empty "implied" attribute to the generated XML is an error.
     666            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     667              : 
     668            0 :   m_ssXml << ">\r\n";
     669              : 
     670            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     671              :   {
     672            0 :     m_ssXml << "\t<" << szElementTag;
     673              : 
     674              :     // "required" means that the attribute must be added and contain a valid
     675              :     // entry. If it is not part of the generated XML, it is an error.
     676            0 :     if ( ip[ii].hasValidName() == false )
     677            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     678              : 
     679            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     680              : 
     681            0 :     m_ssXml << ">\r\n";
     682              : 
     683              :     // Now add the data for the element...
     684            0 :     m_ssXml << IndiElement::getSwitchStateString( ip[ii].getSwitchState() ) << "\r\n";
     685            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     686              :   }
     687            0 :   m_ssXml << "</" << szTag << ">\r\n";
     688            0 : }
     689              : 
     690              : ////////////////////////////////////////////////////////////////////////////////
     691              : // DefLightVector REQUIRED: device name state
     692              : // DefLightVector IMPLIED:  label group timestamp message
     693              : // DefLight REQUIRED: name
     694              : // DefLight IMPLIED: label
     695              : 
     696            0 : void IndiXmlParser::createDefLightVector( const IndiProperty &ip )
     697              : {
     698              :   // What kind of message is this?
     699            0 :   string szTag = "defLightVector";
     700            0 :   string szElementTag = "defLight";
     701            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     702              : 
     703              :   // Clear out the xml stream.
     704            0 :   m_ssXml.str("");
     705            0 :   m_ssXml << "<" << szTag;
     706              : 
     707              :   // "required" means that the attribute must be added and contain a valid
     708              :   // entry. If it is not part of the generated XML, it is an error.
     709            0 :   if ( ip.hasValidDevice() == false )
     710            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     711            0 :   if ( ip.hasValidName() == false )
     712            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     713            0 :   if ( ip.hasValidState() == false )
     714            0 :     throw runtime_error( szDescrip + " must have attribute 'state' defined." );
     715              : 
     716            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     717            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     718            0 :   m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     719              : 
     720              :   // "implied" means that if they are not defined, don't add them. Adding an
     721              :   // empty "implied" attribute to the generated XML is an error.
     722            0 :   if ( ip.hasValidLabel() == true )
     723            0 :     m_ssXml << " label=\"" << ip.getLabel() << "\"";
     724            0 :   if ( ip.hasValidGroup() == true )
     725            0 :     m_ssXml << " group=\"" << ip.getGroup() << "\"";
     726            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     727            0 :   if ( ip.hasValidMessage() == true )
     728            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     729              : 
     730            0 :   m_ssXml << ">\r\n";
     731              : 
     732            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     733              :   {
     734            0 :     m_ssXml << "\t<" << szElementTag;
     735              : 
     736              :     // "required" means that the attribute must be added and contain a valid
     737              :     // entry. If it is not part of the generated XML, it is an error.
     738            0 :     if ( ip[ii].hasValidName() == false )
     739            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     740              : 
     741            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     742              : 
     743              :     // "implied" means that if they are not defined, don't add them. Adding an
     744              :     // empty "implied" attribute to the generated XML is an error.
     745            0 :     if ( ip[ii].hasValidLabel() == true )
     746            0 :       m_ssXml << " label=\"" << ip[ii].getLabel() << "\"";
     747              : 
     748            0 :     m_ssXml << ">\r\n";
     749              : 
     750              :     // Now add the data for the element...
     751            0 :     m_ssXml << IndiElement::getLightStateString( ip[ii].getLightState() ) << "\r\n";
     752            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     753              :   }
     754            0 :   m_ssXml << "</" << szTag << ">\r\n";
     755            0 : }
     756              : 
     757              : ////////////////////////////////////////////////////////////////////////////////
     758              : // SetLightVector REQUIRED: device name
     759              : // SetLightVector IMPLIED:  state timestamp message
     760              : // oneLight REQUIRED: name
     761              : 
     762            0 : void IndiXmlParser::createSetLightVector( const IndiProperty &ip )
     763              : {
     764              :   // What kind of message is this?
     765            0 :   string szTag = "setLightVector";
     766            0 :   string szElementTag = "oneLight";
     767            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     768              : 
     769              :   // Clear out the xml stream.
     770            0 :   m_ssXml.str("");
     771            0 :   m_ssXml << "<" << szTag;
     772              : 
     773              :   // "required" means that the attribute must be added and contain a valid
     774              :   // entry. If it is not part of the generated XML, it is an error.
     775            0 :   if ( ip.hasValidDevice() == false )
     776            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     777            0 :   if ( ip.hasValidName() == false )
     778            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     779              : 
     780            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     781            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     782              : 
     783              :   // "implied" means that if they are not defined, don't add them. Adding an
     784              :   // empty "implied" attribute to the generated XML is an error.
     785            0 :   if ( ip.hasValidState() == true )
     786            0 :     m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     787            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     788            0 :   if ( ip.hasValidMessage() == true )
     789            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     790              : 
     791            0 :   m_ssXml << ">\r\n";
     792              : 
     793            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     794              :   {
     795            0 :     m_ssXml << "\t<" << szElementTag;
     796              : 
     797              :     // "required" means that the attribute must be added and contain a valid
     798              :     // entry. If it is not part of the generated XML, it is an error.
     799            0 :     if ( ip[ii].hasValidName() == false )
     800            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     801              : 
     802            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     803              : 
     804            0 :     m_ssXml << ">\r\n";
     805              : 
     806              :     // Now add the data for the element...
     807            0 :     m_ssXml << IndiElement::getLightStateString( ip[ii].getLightState() ) << "\r\n";
     808            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     809              :   }
     810            0 :   m_ssXml << "</" << szTag << ">\r\n";
     811            0 : }
     812              : 
     813              : ////////////////////////////////////////////////////////////////////////////////
     814              : // DefBLOBVector REQUIRED: device name state perm
     815              : // DefBLOBVector IMPLIED:  label group timeout timestamp message
     816              : // DefBLOB REQUIRED: name
     817              : // DefBLOB IMPLIED: label
     818              : 
     819            0 : void IndiXmlParser::createDefBLOBVector( const IndiProperty &ip )
     820              : {
     821              :   // What kind of message is this?
     822            0 :   string szTag = "defBLOBVector";
     823            0 :   string szElementTag = "defBLOB";
     824            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     825              : 
     826              :   // Clear out the xml stream.
     827            0 :   m_ssXml.str("");
     828            0 :   m_ssXml << "<" << szTag;
     829              : 
     830              :   // "required" means that the attribute must be added and contain a valid
     831              :   // entry. If it is not part of the generated XML, it is an error.
     832            0 :   if ( ip.hasValidDevice() == false )
     833            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     834            0 :   if ( ip.hasValidName() == false )
     835            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     836            0 :   if ( ip.hasValidState() == false )
     837            0 :     throw runtime_error( szDescrip + " must have attribute 'state' defined." );
     838            0 :   if ( ip.hasValidPerm() == false )
     839            0 :     throw runtime_error( szDescrip + " must have attribute 'perm' defined." );
     840              : 
     841            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     842            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     843            0 :   m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     844            0 :   m_ssXml << " perm=\"" << ip.getPropertyPermString( ip.getPerm() ) << "\"";
     845              : 
     846              :   // "implied" means that if they are not defined, don't add them. Adding an
     847              :   // empty "implied" attribute to the generated XML is an error.
     848            0 :   if ( ip.hasValidLabel() == true )
     849            0 :     m_ssXml << " label=\"" << ip.getLabel() << "\"";
     850            0 :   if ( ip.hasValidGroup() == true )
     851            0 :     m_ssXml << " group=\"" << ip.getGroup() << "\"";
     852            0 :   if ( ip.hasValidTimeout() == true )
     853            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     854            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     855            0 :   if ( ip.hasValidMessage() == true )
     856            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     857              : 
     858            0 :   m_ssXml << ">\r\n";
     859              : 
     860            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     861              :   {
     862            0 :     m_ssXml << "\t<" << szElementTag;
     863              : 
     864              :     // "required" means that the attribute must be added and contain a valid
     865              :     // entry. If it is not part of the generated XML, it is an error.
     866            0 :     if ( ip[ii].hasValidName() == false )
     867            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     868              : 
     869            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     870              : 
     871              :     // "implied" means that if they are not defined, don't add them. Adding an
     872              :     // empty "implied" attribute to the generated XML is an error.
     873            0 :     if ( ip[ii].hasValidLabel() == true )
     874            0 :       m_ssXml << " label=\"" << ip[ii].getLabel() << "\"";
     875              : 
     876            0 :     m_ssXml << ">\r\n";
     877              : 
     878              :     // Now add the data for the element...
     879              :     // todo: This may need to be removed, as the BLOB has no initial value.
     880              :     // No data here!
     881            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     882              :   }
     883            0 :   m_ssXml << "</" << szTag << ">\r\n";
     884            0 : }
     885              : 
     886              : ////////////////////////////////////////////////////////////////////////////////
     887              : // SetBLOBVector REQUIRED: device name
     888              : // SetBLOBVector IMPLIED:  state timeout timestamp message
     889              : // oneBLOB REQUIRED: name size format
     890              : 
     891            0 : void IndiXmlParser::createSetBLOBVector( const IndiProperty &ip )
     892              : {
     893              :   // What kind of message is this?
     894            0 :   string szTag = "setBLOBVector";
     895            0 :   string szElementTag = "oneBLOB";
     896            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     897              : 
     898              :   // Clear out the xml stream.
     899            0 :   m_ssXml.str("");
     900            0 :   m_ssXml << "<" << szTag;
     901              : 
     902              :   // "required" means that the attribute must be added and contain a valid
     903              :   // entry. If it is not part of the generated XML, it is an error.
     904            0 :   if ( ip.hasValidDevice() == false )
     905            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     906            0 :   if ( ip.hasValidName() == false )
     907            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     908              : 
     909            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     910            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     911              : 
     912              :   // "implied" means that if they are not defined, don't add them. Adding an
     913              :   // empty "implied" attribute to the generated XML is an error.
     914            0 :   if ( ip.hasValidState() == true )
     915            0 :     m_ssXml << " state=\"" << ip.getPropertyStateString( ip.getState() ) << "\"";
     916            0 :   if ( ip.hasValidTimeout() == true )
     917            0 :     m_ssXml << " timeout=\"" << ip.getTimeout() << "\"";
     918            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     919            0 :   if ( ip.hasValidMessage() == true )
     920            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
     921              : 
     922            0 :   m_ssXml << ">\r\n";
     923              : 
     924            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     925              :   {
     926            0 :     m_ssXml << "\t<" << szElementTag;
     927              : 
     928              :     // "required" means that the attribute must be added and contain a valid
     929              :     // entry. If it is not part of the generated XML, it is an error.
     930            0 :     if ( ip[ii].hasValidName() == false )
     931            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
     932            0 :     if ( ip[ii].hasValidSize() == false )
     933            0 :       throw runtime_error( szElementTag + " must have attribute 'size' defined." );
     934            0 :     if ( ip[ii].hasValidFormat() == false )
     935            0 :       throw runtime_error( szElementTag + " must have attribute 'format' defined." );
     936              : 
     937            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
     938            0 :     m_ssXml << " size=\"" << ip[ii].getSize() << "\"";
     939            0 :     m_ssXml << " format=\"" << ip[ii].getFormat() << "\"";
     940              : 
     941            0 :     m_ssXml << ">\r\n";
     942              : 
     943              :     // Allocate a big buffer to hold the base64 encoded data.
     944            0 :     vector<unsigned char> vecBase64Buf( 4 * ip[ii].getValue().size() / 3 + 4 );
     945              : 
     946              :     // Now base64 encode the data.
     947            0 :     unsigned char *pcBase64Buf = &vecBase64Buf[0];
     948            0 :     unsigned char *pcValueBuf = (unsigned char *)( ip[ii].getValue().c_str() );
     949            0 :     unsigned int  uiValueBufLen = ip[ii].getValue().size();
     950              :     // unsigned int uiBase64BufLen =
     951            0 :     ::to64frombits( pcBase64Buf, pcValueBuf, uiValueBufLen );
     952              : 
     953              :     // Now add the data for the element...
     954            0 :     m_ssXml << pcBase64Buf << "\r\n";
     955            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
     956            0 :   }
     957            0 :   m_ssXml << "</" << szTag << ">\r\n";
     958            0 : }
     959              : 
     960              : ////////////////////////////////////////////////////////////////////////////////
     961              : // NewBLOBVector REQUIRED: device name
     962              : // NewBLOBVector IMPLIED:  timestamp
     963              : // oneBLOB REQUIRED: name size format
     964              : 
     965            0 : void IndiXmlParser::createNewBLOBVector( const IndiProperty &ip )
     966              : {
     967              :   // What kind of message is this?
     968            0 :   string szTag = "newBLOBVector";
     969            0 :   string szElementTag = "oneBLOB";
     970            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
     971              : 
     972              :   // Clear out the xml stream.
     973            0 :   m_ssXml.str("");
     974            0 :   m_ssXml << "<" << szTag;
     975              : 
     976              :   // "required" means that the attribute must be added and contain a valid
     977              :   // entry. If it is not part of the generated XML, it is an error.
     978            0 :   if ( ip.hasValidDevice() == false )
     979            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
     980            0 :   if ( ip.hasValidName() == false )
     981            0 :     throw runtime_error( szDescrip + " must have attribute 'name' defined." );
     982              : 
     983            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
     984            0 :   m_ssXml << " name=\"" << ip.getName() << "\"";
     985              : 
     986              :   // "implied" means that if they are not defined, don't add them. Adding an
     987              :   // empty "implied" attribute to the generated XML is an error.
     988            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
     989              : 
     990            0 :   m_ssXml << ">\r\n";
     991              : 
     992            0 :   for ( unsigned int ii = 0; ii < ip.getNumElements(); ii++ )
     993              :   {
     994            0 :     m_ssXml << "\t<" << szElementTag;
     995              : 
     996              :     // "required" means that the attribute must be added and contain a valid
     997              :     // entry. If it is not part of the generated XML, it is an error.
     998            0 :     if ( ip[ii].hasValidName() == false )
     999            0 :       throw runtime_error( szElementTag + " must have attribute 'name' defined." );
    1000            0 :     if ( ip[ii].hasValidSize() == false )
    1001            0 :       throw runtime_error( szElementTag + " must have attribute 'size' defined." );
    1002            0 :     if ( ip[ii].hasValidFormat() == false )
    1003            0 :       throw runtime_error( szElementTag + " must have attribute 'format' defined." );
    1004              : 
    1005            0 :     m_ssXml << " name=\"" << ip[ii].getName() << "\"";
    1006            0 :     m_ssXml << " size=\"" << ip[ii].getSize() << "\"";
    1007            0 :     m_ssXml << " format=\"" << ip[ii].getFormat() << "\"";
    1008              : 
    1009            0 :     m_ssXml << ">\r\n";
    1010              : 
    1011              :     // Allocate a big buffer to hold the base64 encoded data.
    1012            0 :     vector<unsigned char> vecBase64Buf( 4 * ip[ii].getValue().size() / 3 + 4 );
    1013              : 
    1014              :     // Now base64 encode the data.
    1015            0 :     unsigned char *pcBase64Buf = &vecBase64Buf[0];
    1016            0 :     unsigned char *pcValueBuf = (unsigned char *)( ip[ii].getValue().c_str() );
    1017            0 :     unsigned int  uiValueBufLen = ip[ii].getValue().size();
    1018              :     //unsigned int uiBase64BufLen =
    1019            0 :     ::to64frombits( pcBase64Buf, pcValueBuf, uiValueBufLen );
    1020              : 
    1021              :     // Now add the data for the element...
    1022            0 :     m_ssXml << pcBase64Buf << "\r\n";
    1023            0 :     m_ssXml << "\t</" << szElementTag << ">\r\n";
    1024            0 :   }
    1025            0 :   m_ssXml << "</" << szTag << ">\r\n";
    1026            0 : }
    1027              : 
    1028              : ////////////////////////////////////////////////////////////////////////////////
    1029              : // Message REQUIRED:
    1030              : // Message IMPLIED:  device timestamp message
    1031              : 
    1032            0 : void IndiXmlParser::createMessage( const IndiProperty &ip )
    1033              : {
    1034              :   // What kind of message is this?
    1035            0 :   string szTag = "message";
    1036              : 
    1037              :   // Clear out the xml stream.
    1038            0 :   m_ssXml.str("");
    1039            0 :   m_ssXml << "<" << szTag;
    1040              : 
    1041              :   // "implied" means that if they are not defined, don't add them. Adding an
    1042              :   // empty "implied" attribute to the generated XML is an error.
    1043            0 :   if ( ip.hasValidDevice() == true )
    1044            0 :     m_ssXml << " device=\"" << ip.getDevice() << "\"";
    1045            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
    1046            0 :   if ( ip.hasValidMessage() == true )
    1047            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
    1048              : 
    1049            0 :   m_ssXml << ">\r\n";
    1050            0 :   m_ssXml << "</" << szTag << ">\r\n";
    1051            0 : }
    1052              : 
    1053              : ////////////////////////////////////////////////////////////////////////////////
    1054              : // DelProperty REQUIRED: device
    1055              : // DelProperty IMPLIED:  name timestamp message
    1056              : 
    1057            0 : void IndiXmlParser::createDelProperty( const IndiProperty &ip )
    1058              : {
    1059              :   // What kind of message is this?
    1060            0 :   string szTag = "delProperty";
    1061            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
    1062              : 
    1063              :   // Clear out the xml stream.
    1064            0 :   m_ssXml.str("");
    1065            0 :   m_ssXml << "<" << szTag;
    1066              : 
    1067              :   // "required" means that the attribute must be added and contain a valid
    1068              :   // entry. If it is not part of the generated XML, it is an error.
    1069            0 :   if ( ip.hasValidDevice() == false )
    1070            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
    1071              : 
    1072            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
    1073              : 
    1074              :   // "implied" means that if they are not defined, don't add them. Adding an
    1075              :   // empty "implied" attribute to the generated XML is an error.
    1076            0 :   if ( ip.hasValidName() == true )
    1077            0 :     m_ssXml << " name=\"" << ip.getName() << "\"";
    1078            0 :   m_ssXml << " timestamp=\"" << ip.getTimeStamp().getFormattedIso8601Str() << "\"";
    1079            0 :   if ( ip.hasValidMessage() == true )
    1080            0 :     m_ssXml << " message=\"" << ip.getMessage() << "\"";
    1081              : 
    1082            0 :   m_ssXml << ">\r\n";
    1083            0 :   m_ssXml << "</" << szTag << ">\r\n";
    1084            0 : }
    1085              : 
    1086              : ////////////////////////////////////////////////////////////////////////////////
    1087              : // GetProperties REQUIRED:
    1088              : // GetProperties IMPLIED:  device name
    1089              : 
    1090           10 : void IndiXmlParser::createGetProperties( const IndiProperty &ip )
    1091              : {
    1092              :   // What kind of message is this?
    1093           10 :   string szTag = "getProperties";
    1094              : 
    1095              :   // Clear out the xml stream.
    1096           20 :   m_ssXml.str("");
    1097           10 :   m_ssXml << "<" << szTag;
    1098              : 
    1099              :   // "implied" means that if they are not defined, don't add them. Adding an
    1100              :   // empty "implied" attribute to the generated XML is an error.
    1101           10 :   if ( ip.hasValidDevice() == true )
    1102           10 :     m_ssXml << " device=\"" << ip.getDevice() << "\"";
    1103           10 :   if ( ip.hasValidName() == true )
    1104           10 :     m_ssXml << " name=\"" << ip.getName() << "\"";
    1105              : 
    1106           10 :   m_ssXml << " version=\"" << m_szProtocolVersion << "\"";
    1107              : 
    1108           10 :   m_ssXml << ">\r\n";
    1109           10 :   m_ssXml << "</" << szTag << ">\r\n";
    1110           10 : }
    1111              : 
    1112              : ////////////////////////////////////////////////////////////////////////////////
    1113              : // EnableBLOB REQUIRED: device
    1114              : // EnableBLOB IMPLIED:  name
    1115              : 
    1116            0 : void IndiXmlParser::createEnableBLOB( const IndiProperty &ip )
    1117              : {
    1118              :   // What kind of message is this?
    1119            0 :   string szTag = "enableBLOB";
    1120            0 :   string szDescrip = szTag + " '" + ip.getName() + "'";
    1121              : 
    1122              :   // Clear out the xml stream.
    1123            0 :   m_ssXml.str("");
    1124            0 :   m_ssXml << "<" << szTag;
    1125              : 
    1126              :   // "required" means that the attribute must be added and contain a valid
    1127              :   // entry. If it is not part of the generated XML, it is an error.
    1128            0 :   if ( ip.hasValidDevice() == false )
    1129            0 :     throw runtime_error( szDescrip + " must have attribute 'device' defined." );
    1130              : 
    1131            0 :   m_ssXml << " device=\"" << ip.getDevice() << "\"";
    1132              : 
    1133              :   // "implied" means that if they are not defined, don't add them. Adding an
    1134              :   // empty "implied" attribute to the generated XML is an error.
    1135            0 :   if ( ip.hasValidName() == true )
    1136            0 :     m_ssXml << " name=\"" << ip.getName() << "\"";
    1137              : 
    1138            0 :   m_ssXml << ">\r\n";
    1139            0 :   m_ssXml << IndiProperty::getBLOBEnableString( ip.getBLOBEnable() ) << "\r\n";
    1140            0 :   m_ssXml << "</" << szTag << ">\r\n";
    1141            0 : }
    1142              : 
    1143              : ////////////////////////////////////////////////////////////////////////////////
    1144              : ///  Copy constructor.
    1145              : 
    1146            0 : IndiXmlParser::IndiXmlParser( const IndiXmlParser &ixp )
    1147              : {
    1148            0 :   m_plxMessage = ::cloneLilXML( ixp.m_plxMessage );
    1149            0 :   m_pxeRoot = ::cloneXMLEle( ixp.m_pxeRoot );
    1150            0 :   ::memcpy( m_pcMessage, ixp.m_pcMessage, MaxErrorMsgSize );
    1151            0 :   m_szPrevXml = ixp.m_szPrevXml;
    1152            0 : }
    1153              : 
    1154              : ////////////////////////////////////////////////////////////////////////////////
    1155              : /// Destructor.
    1156              : 
    1157           22 : IndiXmlParser::~IndiXmlParser()
    1158              : {
    1159           22 :   ::delLilXML( m_plxMessage );
    1160           22 :   ::delXMLEle( m_pxeRoot );
    1161           22 : }
    1162              : 
    1163              : ////////////////////////////////////////////////////////////////////////////////
    1164              : /// Assigns the internal data of this object from an existing one.
    1165              : 
    1166            0 : const IndiXmlParser &IndiXmlParser::operator=( const IndiXmlParser &ixpRhs )
    1167              : {
    1168            0 :   if ( &ixpRhs != this )
    1169              :   {
    1170            0 :     ::delLilXML( m_plxMessage );
    1171            0 :     ::delXMLEle( m_pxeRoot );
    1172            0 :     m_plxMessage = ::cloneLilXML( ixpRhs.m_plxMessage );
    1173            0 :     m_pxeRoot = ::cloneXMLEle( ixpRhs.m_pxeRoot );
    1174            0 :     ::memcpy( m_pcMessage, ixpRhs.m_pcMessage, MaxErrorMsgSize );
    1175            0 :     m_szPrevXml = ixpRhs.m_szPrevXml;
    1176              :   }
    1177            0 :   return *this;
    1178              : }
    1179              : 
    1180              : ////////////////////////////////////////////////////////////////////////////////
    1181              : /// Remove all attributes and reset this object.
    1182              : 
    1183            0 : void IndiXmlParser::clear()
    1184              : {
    1185            0 :   ::delLilXML( m_plxMessage );
    1186            0 :   ::delXMLEle( m_pxeRoot );
    1187            0 :   m_plxMessage = ::newLilXML();
    1188            0 :   m_pxeRoot = NULL;
    1189            0 :   ::memset( m_pcMessage, 0, MaxErrorMsgSize*sizeof(char) );
    1190            0 :   m_szPrevXml = "";
    1191            0 :   m_ssXml.str( "" );
    1192            0 : }
    1193              : 
    1194              : ////////////////////////////////////////////////////////////////////////////////
    1195              : /// Initialize all data - assume we have just been created.
    1196              : 
    1197           22 : void IndiXmlParser::init( const string &szProtocolVersion )
    1198              : {
    1199           22 :   m_szProtocolVersion = szProtocolVersion;
    1200           22 :   m_plxMessage = ::newLilXML();
    1201           22 :   m_pxeRoot = NULL;
    1202           22 :   ::memset( m_pcMessage, 0, MaxErrorMsgSize*sizeof(char) );
    1203           22 : }
    1204              : 
    1205              : ////////////////////////////////////////////////////////////////////////////////
    1206              : /// Returns the data formatted as an xml string.
    1207              : 
    1208           10 : string IndiXmlParser::createXmlString() const
    1209              : {
    1210           10 :   string szXml;
    1211              : 
    1212           10 :   if ( m_pxeRoot != NULL )
    1213              :   {
    1214            0 :     int nNumChars = 1 + ::sprlXMLEle( m_pxeRoot, 0 );
    1215              :     //szXml.reserve( nNumChars );
    1216            0 :     char *pcXml = ( char * )( ::malloc( nNumChars * sizeof( char ) ) );
    1217            0 :     ::memset( pcXml, 0, sizeof( char ) * nNumChars );
    1218            0 :     ::sprXMLEle( pcXml, m_pxeRoot, 0 );
    1219            0 :     szXml = string( pcXml );
    1220              :   }
    1221           10 :   else if ( m_ssXml.str().size() > 0 )
    1222              :   {
    1223           10 :     szXml = m_ssXml.str();
    1224              :   }
    1225              : 
    1226           10 :   return szXml;
    1227            0 : }
    1228              : 
    1229              : ////////////////////////////////////////////////////////////////////////////////
    1230              : 
    1231            0 : IndiXmlParser::State IndiXmlParser::getState() const
    1232              : {
    1233            0 :   return ( m_pxeRoot != NULL ) ? ( CompleteState ) : ( IncompleteState );
    1234              : }
    1235              : 
    1236              : ////////////////////////////////////////////////////////////////////////////////
    1237              : /// Sets all the data in this object from formatted xml. First clears all
    1238              : /// internal data, then parses the xml.
    1239              : 
    1240            0 : void IndiXmlParser::parseXml( const char *pcXml,
    1241              :                               const unsigned int &uiNumBytes,
    1242              :                               string &szErrorMsg )
    1243              : {
    1244            0 :   parseXml( string( pcXml, uiNumBytes ), szErrorMsg );
    1245            0 : }
    1246              : 
    1247              : ////////////////////////////////////////////////////////////////////////////////
    1248              : /// Sets all the data in this object from formatted xml. First clears all
    1249              : /// internal data, then parses the xml.
    1250              : 
    1251            0 : void IndiXmlParser::parseXml( const string &szXml,
    1252              :                               string &szErrorMsg )
    1253              : {
    1254              :   // Do we have any text left from a previous call?
    1255            0 :   string szCurrXml = m_szPrevXml + szXml;
    1256              : 
    1257              :   // Make sure the message is empty.
    1258            0 :   szErrorMsg.clear();
    1259            0 :   ::memset( m_pcMessage, 0, MaxErrorMsgSize * sizeof(char) );
    1260              : 
    1261              :   // Reset the internal data.
    1262            0 :   ::delXMLEle( m_pxeRoot );
    1263            0 :   m_pxeRoot = NULL;
    1264              : 
    1265            0 :   unsigned int uiProcessed = 0;
    1266            0 :   XMLEle *pxeNewRoot = NULL;
    1267              :   // The pxeNewRoot will be NULL until the document is complete.
    1268            0 :   for ( ; uiProcessed < szCurrXml.size() && pxeNewRoot == NULL; uiProcessed++ )
    1269              :   {
    1270            0 :     pxeNewRoot = ::readXMLEle( m_plxMessage,
    1271            0 :                                ( int )( szCurrXml[uiProcessed] ),
    1272            0 :                                ( char * )( m_pcMessage ) );
    1273              :     // At this point, if there was an error, pxeNewRoot will be null, and
    1274              :     // m_pcMessage will contain why.
    1275            0 :     if ( ::strlen( ( char * )( m_pcMessage ) ) > 0 )
    1276              :     {
    1277              :       // Save the message.
    1278            0 :       szErrorMsg = string( ( const char * )( m_pcMessage ) );
    1279              :       std::cerr << "Error processing XML: '"
    1280            0 :                 << szXml << "'" << std::endl
    1281            0 :                 << "Error message: '" << szErrorMsg << "'" << std::endl;
    1282              :       // Clear out the existing data and start over.
    1283            0 :       clear();
    1284            0 :       break;
    1285              :     }
    1286              :   }
    1287              : 
    1288              :   // When we get here, the message was empty, so there was no error.
    1289              :   // We may or may not be complete.
    1290            0 :   m_pxeRoot = pxeNewRoot;
    1291              : 
    1292              :   // Store the left-over text for the next call.
    1293            0 :   m_szPrevXml = szCurrXml.substr( uiProcessed, szCurrXml.size() );
    1294            0 : }
    1295              : 
    1296              : ////////////////////////////////////////////////////////////////////////////////
    1297              : /// Returns the attribute value with name szAttributeName.
    1298              : 
    1299            0 : string IndiXmlParser::getAttributeValue( const string &szAttributeName,
    1300              :     XMLEle *pxeRoot ) const
    1301              : {
    1302            0 :   if ( pxeRoot == NULL )
    1303            0 :     return "";
    1304              : 
    1305            0 :   XMLAtt *attrib = ::findXMLAtt( pxeRoot, szAttributeName.c_str() );
    1306              : 
    1307            0 :   if ( attrib == NULL )
    1308            0 :     return "";
    1309              : 
    1310            0 :   return string( ::valuXMLAtt( attrib ) );
    1311              : }
    1312              : 
    1313              : ////////////////////////////////////////////////////////////////////////////////
    1314              : /// Get the IndiMessage created from the xml data.
    1315              : 
    1316            0 : IndiMessage IndiXmlParser::createIndiMessage() const
    1317              : {
    1318              :   IndiMessage::Type tMsgType;
    1319            0 :   IndiProperty ipNew;
    1320            0 :   string szValue;
    1321              : 
    1322            0 :   if ( m_pxeRoot != NULL )
    1323              :   {
    1324              :     // What type of message is this?
    1325            0 :     string szType = string( ::tagXMLEle( m_pxeRoot ) );
    1326            0 :     IndiXmlParser::MessageType tType = convertStringToType( szType );
    1327              : 
    1328            0 :     switch ( tType )
    1329              :     {
    1330            0 :       case UnknownType:
    1331            0 :         tMsgType = IndiMessage::Unknown;
    1332            0 :         break;
    1333              :       // Define properties.
    1334            0 :       case DefBLOBVector:
    1335            0 :         ipNew = IndiProperty( IndiProperty::BLOB );
    1336            0 :         tMsgType = IndiMessage::Define;
    1337            0 :         break;
    1338            0 :       case DefLightVector:
    1339            0 :         ipNew = IndiProperty( IndiProperty::Light );
    1340            0 :         tMsgType = IndiMessage::Define;
    1341            0 :         break;
    1342            0 :       case DefNumberVector:
    1343            0 :         ipNew = IndiProperty( IndiProperty::Number );
    1344            0 :         tMsgType = IndiMessage::Define;
    1345            0 :         break;
    1346            0 :       case DefSwitchVector:
    1347            0 :         ipNew = IndiProperty( IndiProperty::Switch );
    1348            0 :         tMsgType = IndiMessage::Define;
    1349            0 :         break;
    1350            0 :       case DefTextVector:
    1351            0 :         ipNew = IndiProperty( IndiProperty::Text );
    1352            0 :         tMsgType = IndiMessage::Define;
    1353            0 :         break;
    1354              :       // Delete properties.
    1355            0 :       case DelProperty:
    1356            0 :         ipNew = IndiProperty( IndiProperty::Unknown );
    1357            0 :         tMsgType = IndiMessage::Delete;
    1358            0 :         break;
    1359              :       // Enable blobs for a client.
    1360            0 :       case EnableBLOB:
    1361            0 :         ipNew = IndiProperty( IndiProperty::Unknown );
    1362            0 :         tMsgType = IndiMessage::EnableBLOB;
    1363            0 :         break;
    1364              :       // Command to enable snooping messages from other devices.
    1365            0 :       case GetProperties:
    1366            0 :         ipNew = IndiProperty( IndiProperty::Unknown );
    1367            0 :         tMsgType = IndiMessage::GetProperties;
    1368            0 :         break;
    1369              :       // A message.
    1370            0 :       case Message:
    1371            0 :         ipNew = IndiProperty( IndiProperty::Unknown );
    1372            0 :         tMsgType = IndiMessage::Message;
    1373            0 :         break;
    1374              :       // Update properties.
    1375            0 :       case NewBLOBVector:
    1376            0 :         ipNew = IndiProperty( IndiProperty::BLOB );
    1377            0 :         tMsgType = IndiMessage::NewProperty;
    1378            0 :         break;
    1379            0 :       case NewNumberVector:
    1380            0 :         ipNew = IndiProperty( IndiProperty::Number );
    1381            0 :         tMsgType = IndiMessage::NewProperty;
    1382            0 :         break;
    1383            0 :       case NewSwitchVector:
    1384            0 :         ipNew = IndiProperty( IndiProperty::Switch );
    1385            0 :         tMsgType = IndiMessage::NewProperty;
    1386            0 :         break;
    1387            0 :       case NewTextVector:
    1388            0 :         ipNew = IndiProperty( IndiProperty::Text );
    1389            0 :         tMsgType = IndiMessage::NewProperty;
    1390            0 :         break;
    1391              :       // Set properties.
    1392            0 :       case SetBLOBVector:
    1393            0 :         ipNew = IndiProperty( IndiProperty::BLOB );
    1394            0 :         tMsgType = IndiMessage::SetProperty;
    1395            0 :         break;
    1396            0 :       case SetLightVector:
    1397            0 :         ipNew = IndiProperty( IndiProperty::Light );
    1398            0 :         tMsgType = IndiMessage::SetProperty;
    1399            0 :         break;
    1400            0 :       case SetNumberVector:
    1401            0 :         ipNew = IndiProperty( IndiProperty::Number );
    1402            0 :         tMsgType = IndiMessage::SetProperty;
    1403            0 :         break;
    1404            0 :       case SetSwitchVector:
    1405            0 :         ipNew = IndiProperty( IndiProperty::Switch );
    1406            0 :         tMsgType = IndiMessage::SetProperty;
    1407            0 :         break;
    1408            0 :       case SetTextVector:
    1409            0 :         ipNew = IndiProperty( IndiProperty::Text );
    1410            0 :         tMsgType = IndiMessage::SetProperty;
    1411            0 :         break;
    1412              :     };
    1413              : 
    1414              :     // Set the attributes.
    1415            0 :     if ( ( szValue = getAttributeValue( "device", m_pxeRoot ) ).size() > 0 )
    1416            0 :       ipNew.setDevice( szValue );
    1417            0 :     if ( ( szValue = getAttributeValue( "group", m_pxeRoot ) ).size() > 0 )
    1418            0 :       ipNew.setGroup( szValue );
    1419            0 :     if ( ( szValue = getAttributeValue( "label", m_pxeRoot ) ).size() > 0 )
    1420            0 :       ipNew.setLabel( szValue );
    1421            0 :     if ( ( szValue = getAttributeValue( "message", m_pxeRoot ) ).size() > 0 )
    1422            0 :       ipNew.setMessage( szValue );
    1423            0 :     if ( ( szValue = getAttributeValue( "name", m_pxeRoot ) ).size() > 0 )
    1424            0 :       ipNew.setName( szValue );
    1425            0 :     if ( ( szValue = getAttributeValue( "perm", m_pxeRoot ) ).size() > 0 )
    1426            0 :       ipNew.setPerm( IndiProperty::getPropertyPermType( szValue ) );
    1427            0 :     if ( ( szValue = getAttributeValue( "rule", m_pxeRoot ) ).size() > 0 )
    1428            0 :       ipNew.setRule( IndiProperty::getSwitchRuleType( szValue ) );
    1429            0 :     if ( ( szValue = getAttributeValue( "state", m_pxeRoot ) ).size() > 0 )
    1430            0 :       ipNew.setState( IndiProperty::getPropertyStateType( szValue ) );
    1431            0 :     if ( ( szValue = getAttributeValue( "timeout", m_pxeRoot ) ).size() > 0 )
    1432              :     {
    1433            0 :       stringstream ssTimeout;
    1434            0 :       ssTimeout << szValue;
    1435              :       double xTimeout;
    1436            0 :       ssTimeout >> xTimeout;
    1437            0 :       ipNew.setTimeout( xTimeout );
    1438            0 :     }
    1439            0 :     if ( ( szValue = getAttributeValue( "timestamp", m_pxeRoot ) ).size() > 0 )
    1440              :     {
    1441            0 :       TimeStamp tsMod;
    1442            0 :       tsMod.fromFormattedIso8601Str( szValue );
    1443            0 :       ipNew.setTimeStamp( tsMod );
    1444            0 :     }
    1445            0 :     if ( ( szValue = getAttributeValue( "version", m_pxeRoot ) ).size() > 0 )
    1446            0 :       ipNew.setVersion( szValue );
    1447              : 
    1448              :     // A special case is a BLOB enable message - it has no elements,
    1449              :     // but has data in it.
    1450            0 :     if ( tType == EnableBLOB )
    1451              :     {
    1452            0 :       ipNew = IndiProperty::getBLOBEnableType( ::pcdataXMLEle( m_pxeRoot ) );
    1453              :     }
    1454              :     else
    1455              :     {
    1456              :       // Now iterate over all the child elements and add them to the message.
    1457              :       // The first time we call 'nextXMLEle' nInit is 1 to start fresh,
    1458              :       // then it is 0 and will step through each one to the end.
    1459            0 :       int nInit = 1;
    1460            0 :       XMLEle *pxeChild = NULL;
    1461              : 
    1462              :       // We need to iterate over each child element.
    1463            0 :       while ( pxeChild != NULL || nInit == 1 )
    1464              :       {
    1465            0 :         pxeChild = ::nextXMLEle( m_pxeRoot, nInit );
    1466              : 
    1467              :         // No children = we reached the end of the child elements.
    1468            0 :         if ( pxeChild != NULL )
    1469              :         {
    1470              :           // We need a new element....
    1471            0 :           IndiElement ieNew;
    1472              : 
    1473            0 :           if ( ( szValue = string( ::findXMLAttValu( pxeChild, "format" ) ) ).size() > 0 )
    1474            0 :             ieNew.setFormat( szValue );
    1475            0 :           if ( ( szValue = string( ::findXMLAttValu( pxeChild, "label" ) ) ).size() > 0 )
    1476            0 :             ieNew.setLabel( szValue );
    1477            0 :           if ( ( szValue = string( ::findXMLAttValu( pxeChild, "max" ) ) ).size() > 0 )
    1478            0 :             ieNew.setMax( szValue );
    1479            0 :           if ( ( szValue = string( ::findXMLAttValu( pxeChild, "min" ) ) ).size() > 0 )
    1480            0 :             ieNew.setMin( szValue );
    1481            0 :           if ( ( szValue = string( ::findXMLAttValu( pxeChild, "name" ) ) ).size() > 0 )
    1482            0 :             ieNew.setName( szValue );
    1483            0 :           if ( ( szValue = string( ::findXMLAttValu( pxeChild, "size" ) ) ).size() > 0 )
    1484            0 :             ieNew.setSize( szValue );
    1485            0 :           if ( ( szValue = string( ::findXMLAttValu( pxeChild, "step" ) ) ).size() > 0 )
    1486            0 :             ieNew.setStep( szValue );
    1487              : 
    1488            0 :           szValue = string( ::pcdataXMLEle( pxeChild ) );
    1489              : 
    1490              :           // The different types have different data...
    1491            0 :           switch ( tType )
    1492              :           {
    1493            0 :             case DefLightVector:
    1494              :             case SetLightVector:
    1495            0 :               ieNew.setLightState( IndiElement::getLightStateType( szValue ) );
    1496            0 :               break;
    1497            0 :             case DefSwitchVector:
    1498              :             case NewSwitchVector:
    1499              :             case SetSwitchVector:
    1500            0 :               ieNew.setSwitchState( IndiElement::getSwitchStateType( szValue ) );
    1501            0 :               break;
    1502            0 :             default:
    1503            0 :               ieNew.setValue( szValue );
    1504              :           }
    1505              : 
    1506              :           // Now add this element to the message.
    1507            0 :           ipNew.add( ieNew );
    1508            0 :         }
    1509            0 :         nInit = 0;
    1510              :       }
    1511              :     }
    1512            0 :   }
    1513              : 
    1514            0 :   return IndiMessage( tMsgType, ipNew );
    1515            0 : }
    1516              : 
    1517              : ////////////////////////////////////////////////////////////////////////////////
    1518              : /// This handles streaming from input and other stream-like constructs.
    1519              : 
    1520            0 : istream &operator>>( istream &strmIn, IndiXmlParser &ixpRhs )
    1521              : {
    1522            0 :   if ( strmIn.good() )
    1523              :   {
    1524            0 :     stringbuf sbData;
    1525            0 :     strmIn.get( sbData );
    1526              :     // We need a string for the error message, if any.
    1527            0 :     string szErrorMsg;
    1528            0 :     ixpRhs.parseXml( sbData.str(), szErrorMsg );
    1529            0 :   }
    1530            0 :   return strmIn;
    1531              : }
    1532              : 
    1533              : ////////////////////////////////////////////////////////////////////////////////
    1534              : /// This handles streaming to output and other stream-like constructs.
    1535              : 
    1536            0 : ostream &operator<<( ostream &strmOut, const IndiXmlParser &ixpRhs )
    1537              : {
    1538            0 :   strmOut << ixpRhs.createXmlString();
    1539            0 :   return strmOut;
    1540              : }
    1541              : 
    1542              : ////////////////////////////////////////////////////////////////////////////////
    1543              : // If this xml contains a complete INDI message, this returns true,
    1544              : // and start and stop will be the indices of the start and stop of it.
    1545              : /*
    1546              : IndiMessage::Type IndiXmlParser::extractMessage( const std::string &szXml,
    1547              :                                                  int &nStart,
    1548              :                                                  int &nStop )
    1549              : {
    1550              :   string szOpenTag;
    1551              :   string szCloseTag;
    1552              :   size_t tBegin = string::npos;
    1553              :   size_t tEnd = string::npos;
    1554              : 
    1555              :   // Do we have an open and close for any INDI Message type?
    1556              :   szOpenTag = "defBLOBVector";
    1557              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1558              :   {
    1559              :     // Find the first close after the open, above.
    1560              :     szCloseTag = "/defBLOBVector";
    1561              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1562              :     {
    1563              :       nStart = (int)( tBegin );
    1564              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1565              :       return IndiMessage::DefBLOBVector;
    1566              :     }
    1567              :   }
    1568              :   szOpenTag = "defLightVector";
    1569              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1570              :   {
    1571              :     // Find the first close after the open, above.
    1572              :     szCloseTag = "/defLightVector";
    1573              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1574              :     {
    1575              :       nStart = (int)( tBegin );
    1576              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1577              :       return IndiMessage::DefLightVector;
    1578              :     }
    1579              :   }
    1580              :   szOpenTag = "defNumberVector";
    1581              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1582              :   {
    1583              :     // Find the first close after the open, above.
    1584              :     szCloseTag = "/defNumberVector";
    1585              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1586              :     {
    1587              :       nStart = (int)( tBegin );
    1588              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1589              :       return IndiMessage::DefNumberVector;
    1590              :     }
    1591              :   }
    1592              :   szOpenTag = "defSwitchVector";
    1593              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1594              :   {
    1595              :     // Find the first close after the open, above.
    1596              :     szCloseTag = "/defSwitchVector";
    1597              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1598              :     {
    1599              :       nStart = (int)( tBegin );
    1600              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1601              :       return IndiMessage::DefSwitchVector;
    1602              :     }
    1603              :   }
    1604              :   szOpenTag = "defTextVector";
    1605              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1606              :   {
    1607              :     // Find the first close after the open, above.
    1608              :     szCloseTag = "/defTextVector";
    1609              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1610              :     {
    1611              :       nStart = (int)( tBegin );
    1612              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1613              :       return IndiMessage::DefTextVector;
    1614              :     }
    1615              :   }
    1616              :   szOpenTag = "delProperty";
    1617              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1618              :   {
    1619              :     // Find the first close after the open, above.
    1620              :     szCloseTag = "/delProperty";
    1621              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1622              :     {
    1623              :       nStart = (int)( tBegin );
    1624              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1625              :       return IndiMessage::DelProperty;
    1626              :     }
    1627              :   }
    1628              :   szOpenTag = "enableBLOB";
    1629              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1630              :   {
    1631              :     // Find the first close after the open, above.
    1632              :     szCloseTag = "/enableBLOB";
    1633              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1634              :     {
    1635              :       nStart = (int)( tBegin );
    1636              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1637              :       return IndiMessage::EnableBLOB;
    1638              :     }
    1639              :   }
    1640              :   szOpenTag = "getProperties";
    1641              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1642              :   {
    1643              :     // Find the first close after the open, above.
    1644              :     szCloseTag = "/getProperties";
    1645              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1646              :     {
    1647              :       nStart = (int)( tBegin );
    1648              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1649              :       return IndiMessage::GetProperties;
    1650              :     }
    1651              :   }
    1652              :   szOpenTag = "message";
    1653              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1654              :   {
    1655              :     // Find the first close after the open, above.
    1656              :     szCloseTag = "/message";
    1657              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1658              :     {
    1659              :       nStart = (int)( tBegin );
    1660              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1661              :       return IndiMessage::Message;
    1662              :     }
    1663              :   }
    1664              :   szOpenTag = "newBLOBVector";
    1665              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1666              :   {
    1667              :     // Find the first close after the open, above.
    1668              :     szCloseTag = "/newBLOBVector";
    1669              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1670              :     {
    1671              :       nStart = (int)( tBegin );
    1672              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1673              :       return IndiMessage::NewBLOBVector;
    1674              :     }
    1675              :   }
    1676              :   szOpenTag = "newNumberVector";
    1677              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1678              :   {
    1679              :     // Find the first close after the open, above.
    1680              :     szCloseTag = "/newNumberVector";
    1681              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1682              :     {
    1683              :       nStart = (int)( tBegin );
    1684              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1685              :       return IndiMessage::NewNumberVector;
    1686              :     }
    1687              :   }
    1688              :   szOpenTag = "newSwitchVector";
    1689              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1690              :   {
    1691              :     // Find the first close after the open, above.
    1692              :     szCloseTag = "/newSwitchVector";
    1693              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1694              :     {
    1695              :       nStart = (int)( tBegin );
    1696              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1697              :       return IndiMessage::NewSwitchVector;
    1698              :     }
    1699              :   }
    1700              :   szOpenTag = "newTextVector";
    1701              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1702              :   {
    1703              :     // Find the first close after the open, above.
    1704              :     szCloseTag = "/newTextVector";
    1705              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1706              :     {
    1707              :       nStart = (int)( tBegin );
    1708              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1709              :       return IndiMessage::NewTextVector;
    1710              :     }
    1711              :   }
    1712              :   szOpenTag = "setBLOBVector";
    1713              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1714              :   {
    1715              :     // Find the first close after the open, above.
    1716              :     szCloseTag = "/setBLOBVector";
    1717              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1718              :     {
    1719              :       nStart = (int)( tBegin );
    1720              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1721              :       return IndiMessage::SetBLOBVector;
    1722              :     }
    1723              :   }
    1724              :   szOpenTag = "setLightVector";
    1725              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1726              :   {
    1727              :     // Find the first close after the open, above.
    1728              :     szCloseTag = "/setLightVector";
    1729              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1730              :     {
    1731              :       nStart = (int)( tBegin );
    1732              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1733              :       return IndiMessage::SetLightVector;
    1734              :     }
    1735              :   }
    1736              :   szOpenTag = "setNumberVector";
    1737              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1738              :   {
    1739              :     // Find the first close after the open, above.
    1740              :     szCloseTag = "/setNumberVector";
    1741              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1742              :     {
    1743              :       nStart = (int)( tBegin );
    1744              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1745              :       return IndiMessage::SetNumberVector;
    1746              :     }
    1747              :   }
    1748              :   szOpenTag = "setSwitchVector";
    1749              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1750              :   {
    1751              :     // Find the first close after the open, above.
    1752              :     szCloseTag = "/setSwitchVector";
    1753              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1754              :     {
    1755              :       nStart = (int)( tBegin );
    1756              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1757              :       return IndiMessage::SetSwitchVector;
    1758              :     }
    1759              :   }
    1760              :   szOpenTag = "setTextVector";
    1761              :   if ( tBegin = szXml.find( szOpenTag ) != string::npos )
    1762              :   {
    1763              :     // Find the first close after the open, above.
    1764              :     szCloseTag = "/setTextVector";
    1765              :     if ( tEnd = szXml.find( szCloseTag, szOpenTag.size() ) != string::npos )
    1766              :     {
    1767              :       nStart = (int)( tBegin );
    1768              :       nStop = (int)( tEnd ) + szCloseTag.size();
    1769              :       return IndiMessage::SetTextVector;
    1770              :     }
    1771              :   }
    1772              : 
    1773              :   // If we got here, we do not have a valid XML document (yet).
    1774              :   return IndiMessage::UnknownType;
    1775              : }
    1776              : */
    1777              : ////////////////////////////////////////////////////////////////////////////////
    1778              : /// Returns the string type given the enumerated type.
    1779              : 
    1780            0 : string IndiXmlParser::convertTypeToString( const IndiXmlParser::MessageType &tType )
    1781              : {
    1782            0 :   string szType = "";
    1783              : 
    1784            0 :   switch ( tType )
    1785              :   {
    1786            0 :     case UnknownType:
    1787            0 :       szType = "";
    1788            0 :       break;
    1789              : 
    1790              :     // Define properties.
    1791            0 :     case DefBLOBVector:
    1792            0 :       szType = "defBLOBVector";
    1793            0 :       break;
    1794            0 :     case DefLightVector:
    1795            0 :       szType = "defLightVector";
    1796            0 :       break;
    1797            0 :     case DefNumberVector:
    1798            0 :       szType = "defNumberVector";
    1799            0 :       break;
    1800            0 :     case DefSwitchVector:
    1801            0 :       szType = "defSwitchVector";
    1802            0 :       break;
    1803            0 :     case DefTextVector:
    1804            0 :       szType = "defTextVector";
    1805            0 :       break;
    1806              : 
    1807              :     // Delete properties.
    1808            0 :     case DelProperty:
    1809            0 :       szType = "delProperty";
    1810            0 :       break;
    1811              : 
    1812              :     // Enable blobs for a client.
    1813            0 :     case EnableBLOB:
    1814            0 :       szType = "enableBLOB";
    1815            0 :       break;
    1816              : 
    1817              :     // Command to enable snooping messages from other devices.
    1818            0 :     case GetProperties:
    1819            0 :       szType = "getProperties";
    1820            0 :       break;
    1821              : 
    1822              :     // A message.
    1823            0 :     case Message:
    1824            0 :       szType = "message";
    1825            0 :       break;
    1826              : 
    1827              :     // Update properties.
    1828            0 :     case NewBLOBVector:
    1829            0 :       szType = "newBLOBVector";
    1830            0 :       break;
    1831            0 :     case NewNumberVector:
    1832            0 :       szType = "newNumberVector";
    1833            0 :       break;
    1834            0 :     case NewSwitchVector:
    1835            0 :       szType = "newSwitchVector";
    1836            0 :       break;
    1837            0 :     case NewTextVector:
    1838            0 :       szType = "newTextVector";
    1839            0 :       break;
    1840              : 
    1841              :     // Set properties.
    1842            0 :     case SetBLOBVector:
    1843            0 :       szType = "setBLOBVector";
    1844            0 :       break;
    1845            0 :     case SetLightVector:
    1846            0 :       szType = "setLightVector";
    1847            0 :       break;
    1848            0 :     case SetNumberVector:
    1849            0 :       szType = "setNumberVector";
    1850            0 :       break;
    1851            0 :     case SetSwitchVector:
    1852            0 :       szType = "setSwitchVector";
    1853            0 :       break;
    1854            0 :     case SetTextVector:
    1855            0 :       szType = "setTextVector";
    1856            0 :       break;
    1857              :   }
    1858              : 
    1859            0 :   return szType;
    1860            0 : }
    1861              : 
    1862              : ////////////////////////////////////////////////////////////////////////////////
    1863              : /// Sets the protocol version of this software.
    1864              : 
    1865           12 : void IndiXmlParser::setProtocolVersion( const string &szProtocolVersion )
    1866              : {
    1867           12 :   m_szProtocolVersion = szProtocolVersion;
    1868           12 : }
    1869              : 
    1870              : ////////////////////////////////////////////////////////////////////////////////
    1871              : /// Returns the protocol version of this software.
    1872              : 
    1873           22 : string IndiXmlParser::getProtocolVersion() const
    1874              : {
    1875           22 :   return m_szProtocolVersion;
    1876              : }
    1877              : 
    1878              : ////////////////////////////////////////////////////////////////////////////////
    1879              : /// Returns the enumerated type given the tag.
    1880              : 
    1881            0 : IndiXmlParser::MessageType IndiXmlParser::convertStringToType( const string &szTag )
    1882              : {
    1883            0 :   MessageType tType = UnknownType;
    1884              : 
    1885              :   // Define properties.
    1886            0 :   if ( szTag == "defBLOBVector" )
    1887            0 :     tType = DefBLOBVector;
    1888            0 :   else if ( szTag == "defLightVector" )
    1889            0 :     tType = DefLightVector;
    1890            0 :   else if ( szTag == "defNumberVector" )
    1891            0 :     tType = DefNumberVector;
    1892            0 :   else if ( szTag == "defSwitchVector" )
    1893            0 :     tType = DefSwitchVector;
    1894            0 :   else if ( szTag == "defTextVector" )
    1895            0 :     tType = DefTextVector;
    1896              : 
    1897              :   // Delete properties.
    1898            0 :   else if ( szTag == "delProperty" )
    1899            0 :     tType = DelProperty;
    1900              : 
    1901              :   // Enable blobs for a client.
    1902            0 :   else if ( szTag == "enableBLOB" )
    1903            0 :     tType = EnableBLOB;
    1904              : 
    1905              :   // Command to enable snooping messages from other devices.
    1906            0 :   else if ( szTag == "getProperties" )
    1907            0 :     tType = GetProperties;
    1908              : 
    1909              :   // A message.
    1910            0 :   else if ( szTag == "message" )
    1911            0 :     tType = Message;
    1912              : 
    1913              :   // Update properties.
    1914            0 :   else if ( szTag == "newBLOBVector" )
    1915            0 :     tType = NewBLOBVector;
    1916            0 :   else if ( szTag == "newNumberVector" )
    1917            0 :     tType = NewNumberVector;
    1918            0 :   else if ( szTag == "newSwitchVector" )
    1919            0 :     tType = NewSwitchVector;
    1920            0 :   else if ( szTag == "newTextVector" )
    1921            0 :     tType = NewTextVector;
    1922              : 
    1923              :   // Set properties.
    1924            0 :   else if ( szTag == "setBLOBVector" )
    1925            0 :     tType = SetBLOBVector;
    1926            0 :   else if ( szTag == "setLightVector" )
    1927            0 :     tType = SetLightVector;
    1928            0 :   else if ( szTag == "setNumberVector" )
    1929            0 :     tType = SetNumberVector;
    1930            0 :   else if ( szTag == "setSwitchVector" )
    1931            0 :     tType = SetSwitchVector;
    1932            0 :   else if ( szTag == "setTextVector" )
    1933            0 :     tType = SetTextVector;
    1934              : 
    1935            0 :   return tType;
    1936              : }
    1937              : 
    1938              : ////////////////////////////////////////////////////////////////////////////////
        

Generated by: LCOV version 2.0-1