00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 #include "CallStack.h"
00026
00027 #include "DataDictionary.h"
00028 #include "Message.h"
00029 #include <fstream>
00030 #include <memory>
00031
00032 #ifdef HAVE_LIBXML
00033 #include "LIBXML_DOMDocument.h"
00034 #elif _MSC_VER
00035 #include "MSXML_DOMDocument.h"
00036 #else
00037 #include "LIBXML_DOMDocument.h"
00038 #endif
00039
00040 #ifdef _MSC_VER
00041 #define RESET_AUTO_PTR(OLD, NEW) OLD = NEW;
00042 #else
00043 #define RESET_AUTO_PTR(OLD, NEW) OLD.reset( NEW.release() );
00044 #endif
00045
00046 namespace FIX
00047 {
00048 DataDictionary::DataDictionary()
00049 : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
00050 m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ),
00051 m_orderedFieldsArray(0) {}
00052
00053 DataDictionary::DataDictionary( std::istream& stream )
00054 throw( ConfigError )
00055 : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
00056 m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ),
00057 m_orderedFieldsArray(0)
00058 {
00059 readFromStream( stream );
00060 }
00061
00062 DataDictionary::DataDictionary( const std::string& url )
00063 throw( ConfigError )
00064 : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
00065 m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ),
00066 m_orderedFieldsArray(0)
00067 {
00068 readFromURL( url );
00069 }
00070
00071 DataDictionary::DataDictionary( const DataDictionary& copy )
00072 {
00073 *this = copy;
00074 }
00075
00076 DataDictionary::~DataDictionary()
00077 {
00078 FieldToGroup::iterator i;
00079 for ( i = m_groups.begin(); i != m_groups.end(); ++i )
00080 delete i->second.second;
00081 if( m_orderedFieldsArray )
00082 delete [] m_orderedFieldsArray;
00083 }
00084
00085 DataDictionary& DataDictionary::operator=( const DataDictionary& rhs )
00086 { QF_STACK_PUSH(DataDictionary::operator=)
00087
00088 m_hasVersion = rhs.m_hasVersion;
00089 m_checkFieldsOutOfOrder = rhs.m_checkFieldsOutOfOrder;
00090 m_checkFieldsHaveValues = rhs.m_checkFieldsHaveValues;
00091 m_checkUserDefinedFields = rhs.m_checkUserDefinedFields;
00092 m_beginString = rhs.m_beginString;
00093 m_messageFields = rhs.m_messageFields;
00094 m_requiredFields = rhs.m_requiredFields;
00095 m_messages = rhs.m_messages;
00096 m_fields = rhs.m_fields;
00097 m_orderedFields = rhs.m_orderedFields;
00098 m_orderedFieldsArray = 0;
00099 m_headerFields = rhs.m_headerFields;
00100 m_trailerFields = rhs.m_trailerFields;
00101 m_fieldTypes = rhs.m_fieldTypes;
00102 m_fieldValues = rhs.m_fieldValues;
00103 m_fieldNames = rhs.m_fieldNames;
00104 m_names = rhs.m_names;
00105 m_valueNames = rhs.m_valueNames;
00106
00107 FieldToGroup::const_iterator i = rhs.m_groups.begin();
00108 for ( ; i != rhs.m_groups.end(); ++i )
00109 {
00110 addGroup( i->first.first, i->first.second,
00111 i->second.first, *i->second.second );
00112 }
00113 return *this;
00114
00115 QF_STACK_POP
00116 }
00117
00118 void DataDictionary::validate( const Message& message,
00119 const DataDictionary* const pSessionDD,
00120 const DataDictionary* const pAppDD )
00121 throw( FIX::Exception )
00122 { QF_STACK_PUSH( DataDictionary::validate )
00123
00124 const bool bodyOnly = pSessionDD == 0;
00125 const Header& header = message.getHeader();
00126 const BeginString& beginString = FIELD_GET_REF( header, BeginString );
00127 const MsgType& msgType = FIELD_GET_REF( header, MsgType );
00128 if ( pSessionDD != 0 && pSessionDD->m_hasVersion )
00129 {
00130 if( pSessionDD->getVersion() != beginString )
00131 {
00132 throw UnsupportedVersion();
00133 }
00134 }
00135
00136 int field = 0;
00137 if( (pSessionDD !=0 && pSessionDD->m_checkFieldsOutOfOrder)
00138 || (pAppDD != 0 && pAppDD->m_checkFieldsOutOfOrder) )
00139 {
00140 if ( !message.hasValidStructure(field) )
00141 throw TagOutOfOrder(field);
00142 }
00143
00144 if ( pAppDD != 0 && pAppDD->m_hasVersion )
00145 {
00146 pAppDD->checkMsgType( msgType );
00147 pAppDD->checkHasRequired( message.getHeader(), message, message.getTrailer(), msgType );
00148 }
00149
00150 if( !bodyOnly )
00151 {
00152 pSessionDD->iterate( message.getHeader(), msgType );
00153 pSessionDD->iterate( message.getTrailer(), msgType );
00154 }
00155
00156 pAppDD->iterate( message, msgType );
00157
00158 QF_STACK_POP
00159 }
00160
00161 void DataDictionary::iterate( const FieldMap& map, const MsgType& msgType ) const
00162 { QF_STACK_PUSH(DataDictionary::iterate)
00163
00164 int lastField = 0;
00165
00166 FieldMap::iterator i;
00167 for ( i = map.begin(); i != map.end(); ++i )
00168 {
00169 const FieldBase& field = i->second;
00170 if( i != map.begin() && (field.getField() == lastField) )
00171 throw RepeatedTag( lastField );
00172 checkHasValue( field );
00173
00174 if ( m_hasVersion )
00175 {
00176 checkValidFormat( field );
00177 checkValue( field );
00178 }
00179
00180 if ( m_beginString.getValue().length() && shouldCheckTag(field) )
00181 {
00182 checkValidTagNumber( field );
00183 if ( !Message::isHeaderField( field, this )
00184 && !Message::isTrailerField( field, this ) )
00185 {
00186 checkIsInMessage( field, msgType );
00187 checkGroupCount( field, map, msgType );
00188 }
00189 }
00190 lastField = field.getField();
00191 }
00192
00193 QF_STACK_POP
00194 }
00195
00196 void DataDictionary::readFromURL( const std::string& url )
00197 throw( ConfigError )
00198 { QF_STACK_PUSH(DataDictionary::readFromURL)
00199
00200 #ifdef HAVE_LIBXML
00201 DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00202 #elif _MSC_VER
00203 DOMDocumentPtr pDoc = DOMDocumentPtr(new MSXML_DOMDocument());
00204 #else
00205 DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00206 #endif
00207
00208 if(!pDoc->load(url))
00209 throw ConfigError(url + ": Could not parse data dictionary file");
00210
00211 try
00212 {
00213 readFromDocument( pDoc );
00214 }
00215 catch( ConfigError& e )
00216 {
00217 throw ConfigError( url + ": " + e.what() );
00218 }
00219
00220 QF_STACK_POP
00221 }
00222
00223 void DataDictionary::readFromStream( std::istream& stream )
00224 throw( ConfigError )
00225 { QF_STACK_PUSH(DataDictionary::readFromStream)
00226
00227 #ifdef HAVE_LIBXML
00228 DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00229 #elif _MSC_VER
00230 DOMDocumentPtr pDoc = DOMDocumentPtr(new MSXML_DOMDocument());
00231 #else
00232 DOMDocumentPtr pDoc = DOMDocumentPtr(new LIBXML_DOMDocument());
00233 #endif
00234
00235 if(!pDoc->load(stream))
00236 throw ConfigError("Could not parse data dictionary stream");
00237
00238 readFromDocument( pDoc );
00239
00240 QF_STACK_POP
00241 }
00242
00243 void DataDictionary::readFromDocument( DOMDocumentPtr pDoc )
00244 throw( ConfigError )
00245 { QF_STACK_PUSH(DataDictionary::readFromDocument)
00246
00247
00248 DOMNodePtr pFixNode = pDoc->getNode("/fix");
00249 if(!pFixNode.get())
00250 throw ConfigError("Could not parse data dictionary file"
00251 ", or no <fix> node found at root");
00252 DOMAttributesPtr attrs = pFixNode->getAttributes();
00253 std::string type = "FIX";
00254 if(attrs->get("type", type))
00255 {
00256 if(type != "FIX" && type != "FIXT")
00257 throw ConfigError("type attribute must be FIX or FIXT");
00258 }
00259 std::string major;
00260 if(!attrs->get("major", major))
00261 throw ConfigError("major attribute not found on <fix>");
00262 std::string minor;
00263 if(!attrs->get("minor", minor))
00264 throw ConfigError("minor attribute not found on <fix>");
00265 setVersion(type + "." + major + "." + minor);
00266
00267
00268 DOMNodePtr pFieldsNode = pDoc->getNode("/fix/fields");
00269 if(!pFieldsNode.get())
00270 throw ConfigError("<fields> section not found in data dictionary");
00271
00272 DOMNodePtr pFieldNode = pFieldsNode->getFirstChildNode();
00273 if(!pFieldNode.get()) throw ConfigError("No fields defined");
00274
00275 while(pFieldNode.get())
00276 {
00277 if(pFieldNode->getName() == "field")
00278 {
00279 DOMAttributesPtr attrs = pFieldNode->getAttributes();
00280 std::string name;
00281 if(!attrs->get("name", name))
00282 throw ConfigError("<field> does not have a name attribute");
00283 std::string number;
00284 if(!attrs->get("number", number))
00285 throw ConfigError("<field> " + name + " does not have a number attribute");
00286 int num = atol(number.c_str());
00287 std::string type;
00288 if(!attrs->get("type", type))
00289 throw ConfigError("<field> " + name + " does not have a type attribute");
00290 addField(num);
00291 addFieldType(num, XMLTypeToType(type));
00292 addFieldName(num, name);
00293
00294 DOMNodePtr pFieldValueNode = pFieldNode->getFirstChildNode();
00295 while(pFieldValueNode.get())
00296 {
00297 if(pFieldValueNode->getName() == "value")
00298 {
00299 DOMAttributesPtr attrs = pFieldValueNode->getAttributes();
00300 std::string enumeration;
00301 if(!attrs->get("enum", enumeration))
00302 throw ConfigError("<value> does not have enum attribute in field " + name);
00303 addFieldValue(num, enumeration);
00304 std::string description;
00305 if(attrs->get("description", description))
00306 addValueName(num, enumeration, description);
00307 }
00308 RESET_AUTO_PTR(pFieldValueNode, pFieldValueNode->getNextSiblingNode());
00309 }
00310 }
00311 RESET_AUTO_PTR(pFieldNode, pFieldNode->getNextSiblingNode());
00312 }
00313
00314
00315 if( type == "FIXT" || (type == "FIX" && major < "5") )
00316 {
00317 DOMNodePtr pHeaderNode = pDoc->getNode("/fix/header");
00318 if(!pHeaderNode.get())
00319 throw ConfigError("<header> section not found in data dictionary");
00320
00321 DOMNodePtr pHeaderFieldNode = pHeaderNode->getFirstChildNode();
00322 if(!pHeaderFieldNode.get()) throw ConfigError("No header fields defined");
00323
00324 while(pHeaderFieldNode.get())
00325 {
00326 if(pHeaderFieldNode->getName() == "field" || pHeaderFieldNode->getName() == "group" )
00327 {
00328 DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();
00329 std::string name;
00330 if(!attrs->get("name", name))
00331 throw ConfigError("<field> does not have a name attribute");
00332 std::string required = "false";
00333 attrs->get("required", required);
00334 addHeaderField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");
00335 }
00336 if(pHeaderFieldNode->getName() == "group")
00337 {
00338 DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();
00339 std::string required;
00340 attrs->get("required", required);
00341 bool isRequired = (required == "Y" || required == "y");
00342 addXMLGroup(pDoc.get(), pHeaderFieldNode.get(), "_header_", *this, isRequired);
00343 }
00344
00345 RESET_AUTO_PTR(pHeaderFieldNode, pHeaderFieldNode->getNextSiblingNode());
00346 }
00347 }
00348
00349
00350 if( type == "FIXT" || (type == "FIX" && major < "5") )
00351 {
00352 DOMNodePtr pTrailerNode = pDoc->getNode("/fix/trailer");
00353 if(!pTrailerNode.get())
00354 throw ConfigError("<trailer> section not found in data dictionary");
00355
00356 DOMNodePtr pTrailerFieldNode = pTrailerNode->getFirstChildNode();
00357 if(!pTrailerFieldNode.get()) throw ConfigError("No trailer fields defined");
00358
00359 while(pTrailerFieldNode.get())
00360 {
00361 if(pTrailerFieldNode->getName() == "field" || pTrailerFieldNode->getName() == "group" )
00362 {
00363 DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();
00364 std::string name;
00365 if(!attrs->get("name", name))
00366 throw ConfigError("<field> does not have a name attribute");
00367 std::string required = "false";
00368 attrs->get("required", required);
00369 addTrailerField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");
00370 }
00371 if(pTrailerFieldNode->getName() == "group")
00372 {
00373 DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();
00374 std::string required;
00375 attrs->get("required", required);
00376 bool isRequired = (required == "Y" || required == "y");
00377 addXMLGroup(pDoc.get(), pTrailerFieldNode.get(), "_trailer_", *this, isRequired);
00378 }
00379
00380 RESET_AUTO_PTR(pTrailerFieldNode, pTrailerFieldNode->getNextSiblingNode());
00381 }
00382 }
00383
00384
00385 DOMNodePtr pMessagesNode = pDoc->getNode("/fix/messages");
00386 if(!pMessagesNode.get())
00387 throw ConfigError("<messages> section not found in data dictionary");
00388
00389 DOMNodePtr pMessageNode = pMessagesNode->getFirstChildNode();
00390 if(!pMessageNode.get()) throw ConfigError("No messages defined");
00391
00392 while(pMessageNode.get())
00393 {
00394 if(pMessageNode->getName() == "message")
00395 {
00396 DOMAttributesPtr attrs = pMessageNode->getAttributes();
00397 std::string msgtype;
00398 if(!attrs->get("msgtype", msgtype))
00399 throw ConfigError("<field> does not have a name attribute");
00400 addMsgType(msgtype);
00401
00402 std::string name;
00403 if(attrs->get("name", name))
00404 addValueName( 35, msgtype, name );
00405
00406 DOMNodePtr pMessageFieldNode = pMessageNode->getFirstChildNode();
00407 if( !pMessageFieldNode.get() )
00408 throw ConfigError("<message> contains no fields");
00409 while( pMessageFieldNode.get() )
00410 {
00411 if(pMessageFieldNode->getName() == "field"
00412 || pMessageFieldNode->getName() == "group")
00413 {
00414 DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
00415 std::string name;
00416 if(!attrs->get("name", name))
00417 throw ConfigError("<field> does not have a name attribute");
00418 int num = lookupXMLFieldNumber(pDoc.get(), name);
00419 addMsgField(msgtype, num);
00420
00421 std::string required;
00422 if(attrs->get("required", required)
00423 && (required == "Y" || required == "y"))
00424 {
00425 addRequiredField(msgtype, num);
00426 }
00427 }
00428 else if(pMessageFieldNode->getName() == "component")
00429 {
00430 DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
00431 std::string required;
00432 attrs->get("required", required);
00433 bool isRequired = (required == "Y" || required == "y");
00434 addXMLComponentFields(pDoc.get(), pMessageFieldNode.get(),
00435 msgtype, *this, isRequired);
00436 }
00437 if(pMessageFieldNode->getName() == "group")
00438 {
00439 DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
00440 std::string required;
00441 attrs->get("required", required);
00442 bool isRequired = (required == "Y" || required == "y");
00443 addXMLGroup(pDoc.get(), pMessageFieldNode.get(), msgtype, *this, isRequired);
00444 }
00445 RESET_AUTO_PTR(pMessageFieldNode,
00446 pMessageFieldNode->getNextSiblingNode());
00447 }
00448 }
00449 RESET_AUTO_PTR(pMessageNode, pMessageNode->getNextSiblingNode());
00450 }
00451
00452 QF_STACK_POP
00453 }
00454
00455 int* DataDictionary::getOrderedFields() const
00456 { QF_STACK_PUSH(DataDictionary::getOrderedFields)
00457
00458 if( m_orderedFieldsArray ) return m_orderedFieldsArray;
00459 m_orderedFieldsArray = new int[m_orderedFields.size() + 1];
00460
00461 int* i = m_orderedFieldsArray;
00462 OrderedFields::const_iterator iter;
00463 for( iter = m_orderedFields.begin(); iter != m_orderedFields.end(); *(i++) = *(iter++) ) {}
00464 *i = 0;
00465 return m_orderedFieldsArray;
00466
00467 QF_STACK_POP
00468 }
00469
00470 int DataDictionary::lookupXMLFieldNumber( DOMDocument* pDoc, DOMNode* pNode ) const
00471 { QF_STACK_PUSH(DataDictionary::lookupXMLFieldNumber)
00472
00473 DOMAttributesPtr attrs = pNode->getAttributes();
00474 std::string name;
00475 if(!attrs->get("name", name))
00476 throw ConfigError("No name given to field");
00477 return lookupXMLFieldNumber( pDoc, name );
00478
00479 QF_STACK_POP
00480 }
00481
00482 int DataDictionary::lookupXMLFieldNumber
00483 ( DOMDocument* pDoc, const std::string& name ) const
00484 { QF_STACK_PUSH(DataDictionary::lookupXMLFieldNumber)
00485
00486 NameToField::const_iterator i = m_names.find(name);
00487 if( i == m_names.end() )
00488 throw ConfigError("Field " + name + " not defined in fields section");
00489 return i->second;
00490
00491 QF_STACK_POP
00492 }
00493
00494 int DataDictionary::addXMLComponentFields( DOMDocument* pDoc, DOMNode* pNode,
00495 const std::string& msgtype,
00496 DataDictionary& DD,
00497 bool componentRequired )
00498 { QF_STACK_PUSH(DataDictionary::addXMLComponentFields)
00499
00500 int firstField = 0;
00501
00502 DOMAttributesPtr attrs = pNode->getAttributes();
00503 std::string name;
00504 if(!attrs->get("name", name))
00505 throw ConfigError("No name given to component");
00506
00507 DOMNodePtr pComponentNode =
00508 pDoc->getNode("/fix/components/component[@name='" + name + "']");
00509 if(pComponentNode.get() == 0)
00510 throw ConfigError("Component not found");
00511
00512 DOMNodePtr pComponentFieldNode = pComponentNode->getFirstChildNode();
00513 while(pComponentFieldNode.get())
00514 {
00515 if(pComponentFieldNode->getName() == "field"
00516 || pComponentFieldNode->getName() == "group")
00517 {
00518 DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
00519 std::string name;
00520 if(!attrs->get("name", name))
00521 throw ConfigError("No name given to field");
00522 int field = lookupXMLFieldNumber(pDoc, name);
00523 if( firstField == 0 ) firstField = field;
00524
00525 std::string required;
00526 if(attrs->get("required", required)
00527 && (required == "Y" || required =="y")
00528 && componentRequired)
00529 {
00530 addRequiredField(msgtype, field);
00531 }
00532
00533 DD.addField(field);
00534 DD.addMsgField(msgtype, field);
00535 }
00536 if(pComponentFieldNode->getName() == "component")
00537 {
00538 DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
00539 std::string required;
00540 attrs->get("required", required);
00541 bool isRequired = (required == "Y" || required == "y");
00542 addXMLComponentFields(pDoc, pComponentFieldNode.get(),
00543 msgtype, *this, isRequired);
00544 }
00545 if(pComponentFieldNode->getName() == "group")
00546 {
00547 DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
00548 std::string required;
00549 attrs->get("required", required);
00550 bool isRequired = (required == "Y" || required == "y");
00551 addXMLGroup(pDoc, pComponentFieldNode.get(), msgtype, DD, isRequired);
00552 }
00553 RESET_AUTO_PTR(pComponentFieldNode,
00554 pComponentFieldNode->getNextSiblingNode());
00555 }
00556 return firstField;
00557
00558 QF_STACK_POP
00559 }
00560
00561 void DataDictionary::addXMLGroup( DOMDocument* pDoc, DOMNode* pNode,
00562 const std::string& msgtype,
00563 DataDictionary& DD, bool groupRequired )
00564 { QF_STACK_PUSH(DataDictionary::addXMLGroup)
00565
00566 DOMAttributesPtr attrs = pNode->getAttributes();
00567 std::string name;
00568 if(!attrs->get("name", name))
00569 throw ConfigError("No name given to group");
00570 int group = lookupXMLFieldNumber( pDoc, name );
00571 int delim = 0;
00572 int field = 0;
00573 DataDictionary groupDD;
00574 DOMNodePtr node = pNode->getFirstChildNode();
00575 while(node.get())
00576 {
00577 if( node->getName() == "field" )
00578 {
00579 field = lookupXMLFieldNumber( pDoc, node.get() );
00580 groupDD.addField( field );
00581
00582 DOMAttributesPtr attrs = node->getAttributes();
00583 std::string required;
00584 if( attrs->get("required", required)
00585 && ( required == "Y" || required =="y" )
00586 && groupRequired )
00587 {
00588 groupDD.addRequiredField(msgtype, field);
00589 }
00590 }
00591 else if( node->getName() == "component" )
00592 {
00593 field = addXMLComponentFields( pDoc, node.get(), msgtype, groupDD, false );
00594 }
00595 else if( node->getName() == "group" )
00596 {
00597 field = lookupXMLFieldNumber( pDoc, node.get() );
00598 groupDD.addField( field );
00599 DOMAttributesPtr attrs = node->getAttributes();
00600 std::string required;
00601 if( attrs->get("required", required )
00602 && ( required == "Y" || required =="y" )
00603 && groupRequired)
00604 {
00605 groupDD.addRequiredField(msgtype, field);
00606 }
00607 bool isRequired = false;
00608 if( attrs->get("required", required) )
00609 isRequired = (required == "Y" || required == "y");
00610 addXMLGroup( pDoc, node.get(), msgtype, groupDD, isRequired );
00611 }
00612 if( delim == 0 ) delim = field;
00613 RESET_AUTO_PTR(node, node->getNextSiblingNode());
00614 }
00615
00616 if( delim ) DD.addGroup( msgtype, group, delim, groupDD );
00617
00618 QF_STACK_POP
00619 }
00620
00621 TYPE::Type DataDictionary::XMLTypeToType( const std::string& type ) const
00622 { QF_STACK_PUSH(DataDictionary::XMLTypeToType)
00623
00624 if ( m_beginString < "FIX.4.2" && type == "CHAR" )
00625 return TYPE::String;
00626
00627 if ( type == "STRING" ) return TYPE::String;
00628 if ( type == "CHAR" ) return TYPE::Char;
00629 if ( type == "PRICE" ) return TYPE::Price;
00630 if ( type == "INT" ) return TYPE::Int;
00631 if ( type == "AMT" ) return TYPE::Amt;
00632 if ( type == "QTY" ) return TYPE::Qty;
00633 if ( type == "CURRENCY" ) return TYPE::Currency;
00634 if ( type == "MULTIPLEVALUESTRING" ) return TYPE::MultipleValueString;
00635 if ( type == "MULTIPLESTRINGVALUE" ) return TYPE::MultipleStringValue;
00636 if ( type == "MULTIPLECHARVALUE" ) return TYPE::MultipleCharValue;
00637 if ( type == "EXCHANGE" ) return TYPE::Exchange;
00638 if ( type == "UTCTIMESTAMP" ) return TYPE::UtcTimeStamp;
00639 if ( type == "BOOLEAN" ) return TYPE::Boolean;
00640 if ( type == "LOCALMKTDATE" ) return TYPE::LocalMktDate;
00641 if ( type == "DATA" ) return TYPE::Data;
00642 if ( type == "FLOAT" ) return TYPE::Float;
00643 if ( type == "PRICEOFFSET" ) return TYPE::PriceOffset;
00644 if ( type == "MONTHYEAR" ) return TYPE::MonthYear;
00645 if ( type == "DAYOFMONTH" ) return TYPE::DayOfMonth;
00646 if ( type == "UTCDATE" ) return TYPE::UtcDate;
00647 if ( type == "UTCDATEONLY" ) return TYPE::UtcDateOnly;
00648 if ( type == "UTCTIMEONLY" ) return TYPE::UtcTimeOnly;
00649 if ( type == "NUMINGROUP" ) return TYPE::NumInGroup;
00650 if ( type == "PERCENTAGE" ) return TYPE::Percentage;
00651 if ( type == "SEQNUM" ) return TYPE::SeqNum;
00652 if ( type == "LENGTH" ) return TYPE::Length;
00653 if ( type == "COUNTRY" ) return TYPE::Country;
00654 if ( type == "TIME" ) return TYPE::UtcTimeStamp;
00655 return TYPE::Unknown;
00656
00657 QF_STACK_POP
00658 }
00659 }