2 // This file is part of the aMule Project.
4 // Copyright (c) 2004-2008 aMule Team ( admin@amule.org / http://www.amule.org )
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #define DEBUG_EC_IMPLEMENTATION
28 #include <common/Format.h> // Needed for CFormat
31 #include "ECTag.h" // Needed for ECTag
32 #include "ECSocket.h" // Needed for CECSocket
33 #include "ECSpecialTags.h" // Needed for CValueMap
35 /**********************************************************
39 **********************************************************/
41 //! Defines the Null tag which may be returned by GetTagByNameSafe.
42 const CECTag
CECTag::s_theNullTag
;
44 //! Defines the data for the Null tag. Large enough (16 bytes) for GetMD4Data.
45 const uint32
CECTag::s_theNullTagData
[4] = { 0, 0, 0, 0 };
48 * Creates a new null-valued CECTag instance
51 * @see s_theNullTagData
52 * @see GetTagByNameSafe
56 m_tagData(s_theNullTagData
),
59 m_dataType(EC_TAGTYPE_UNKNOWN
),
67 * Creates a new CECTag instance from the given data
69 * @param name TAG name
70 * @param length length of data buffer
71 * @param data TAG data
72 * @param copy whether to create a copy of the TAG data at \e *data, or should use the provided pointer.
74 * \note When you set \e copy to \b false, the provided data buffer must exist
75 * in the whole lifetime of the packet.
77 CECTag::CECTag(ec_tagname_t name
, unsigned int length
, const void *data
, bool copy
) : m_tagName(name
), m_dynamic(copy
), m_haschildren( false )
81 if (copy
&& (data
!= NULL
)) {
82 m_tagData
= malloc(m_dataLen
);
83 if (m_tagData
!= NULL
) {
84 memcpy((void *)m_tagData
, data
, m_dataLen
);
92 m_dataType
= EC_TAGTYPE_CUSTOM
;
96 * Creates a new CECTag instance for custom data
98 * @param name TAG name
99 * @param length length of data buffer that will be alloc'ed
100 * @param dataptr pointer to internal TAG data buffer
104 CECTag::CECTag(ec_tagname_t name
, unsigned int length
, void **dataptr
) : m_tagName(name
), m_dynamic(true), m_haschildren( false )
108 m_tagData
= malloc(m_dataLen
);
113 *dataptr
= (void *)m_tagData
;
114 m_dataType
= EC_TAGTYPE_CUSTOM
;
118 * Creates a new CECTag instance, which contains an IPv4 address.
120 * This function takes care of the endianness of the port number.
122 * @param name TAG name
123 * @param data The EC_IPv4_t class containing the IPv4 address.
127 CECTag::CECTag(ec_tagname_t name
, const EC_IPv4_t
& data
) : m_tagName(name
), m_dynamic(true), m_haschildren( false )
130 m_dataLen
= sizeof(EC_IPv4_t
);
131 m_tagData
= malloc(sizeof(EC_IPv4_t
));
132 if (m_tagData
!= NULL
) {
133 RawPokeUInt32( ((EC_IPv4_t
*)m_tagData
)->m_ip
, RawPeekUInt32( data
.m_ip
) );
134 ((EC_IPv4_t
*)m_tagData
)->m_port
= ENDIAN_HTONS(data
.m_port
);
136 m_dataType
= EC_TAGTYPE_IPV4
;
143 * Creates a new CECTag instance, which contains a MD4 hash.
145 * This function takes care to store hash in network byte order.
147 * @param name TAG name
148 * @param data The CMD4Hash class containing the MD4 hash.
152 CECTag::CECTag(ec_tagname_t name
, const CMD4Hash
& data
) : m_tagName(name
), m_dynamic(true), m_haschildren( false )
156 m_tagData
= malloc(16);
157 if (m_tagData
!= NULL
) {
158 RawPokeUInt64( (char*)m_tagData
, RawPeekUInt64( data
.GetHash() ) );
159 RawPokeUInt64( (char*)m_tagData
+ 8, RawPeekUInt64( data
.GetHash() + 8 ) );
161 m_dataType
= EC_TAGTYPE_HASH16
;
168 * Creates a new CECTag instance, which contains a string
170 * @param name TAG name
171 * @param data wxString object, it's contents are converted to UTF-8.
173 * @see GetStringDataSTL()
175 CECTag::CECTag(ec_tagname_t name
, const std::string
& data
) : m_tagName(name
), m_dynamic(true), m_haschildren( false )
177 ConstructStringTag(name
,data
);
181 * Creates a new CECTag instance, which contains a string
183 * @param name TAG name
184 * @param data wxString object, it's contents are converted to UTF-8.
186 * @see GetStringData()
188 CECTag::CECTag(ec_tagname_t name
, const wxString
& data
) : m_tagName(name
), m_dynamic(true), m_haschildren( false )
190 ConstructStringTag(name
, (const char*)unicode2UTF8(data
));
192 CECTag::CECTag(ec_tagname_t name
, const wxChar
* data
) : m_tagName(name
), m_dynamic(true), m_haschildren( false )
194 ConstructStringTag(name
, (const char*)unicode2UTF8(data
));
200 CECTag::CECTag(const CECTag
& tag
)
206 * Creates a new CECTag instance, which contains an int value.
208 * This takes care of endianness problems with numbers.
210 * @param name TAG name.
211 * @param data number.
215 CECTag::CECTag(ec_tagname_t name
, bool data
) : m_tagName(name
), m_dynamic(true)
219 CECTag::CECTag(ec_tagname_t name
, uint8 data
) : m_tagName(name
), m_dynamic(true)
223 CECTag::CECTag(ec_tagname_t name
, uint16 data
) : m_tagName(name
), m_dynamic(true)
227 CECTag::CECTag(ec_tagname_t name
, uint32 data
) : m_tagName(name
), m_dynamic(true)
231 CECTag::CECTag(ec_tagname_t name
, uint64 data
) : m_tagName(name
), m_dynamic(true)
236 void CECTag::InitInt(uint64 data
)
239 m_dataType
= EC_TAGTYPE_UINT8
;
241 } else if (data
<= 0xFFFF) {
242 m_dataType
= EC_TAGTYPE_UINT16
;
244 } else if (data
<= 0xFFFFFFFF) {
245 m_dataType
= EC_TAGTYPE_UINT32
;
248 m_dataType
= EC_TAGTYPE_UINT64
;
252 m_tagData
= malloc(m_dataLen
);
254 if (m_tagData
!= NULL
) {
255 switch (m_dataType
) {
256 case EC_TAGTYPE_UINT8
:
257 PokeUInt8( (void*)m_tagData
, (uint8
) data
);
259 case EC_TAGTYPE_UINT16
:
260 PokeUInt16( (void*)m_tagData
, wxUINT16_SWAP_ALWAYS((uint16
) data
));
262 case EC_TAGTYPE_UINT32
:
263 PokeUInt32( (void*)m_tagData
, wxUINT32_SWAP_ALWAYS((uint32
) data
));
265 case EC_TAGTYPE_UINT64
:
266 PokeUInt64( (void*)m_tagData
, wxUINT64_SWAP_ALWAYS(data
) );
271 free((void*)m_tagData
);
282 * Creates a new CECTag instance, which contains a double precision floating point number
284 * @param name TAG name
285 * @param data double number
287 * @note The actual data is converted to string representation, because we have not found
288 * yet an effective and safe way to transmit floating point numbers.
290 * @see GetDoubleData()
292 CECTag::CECTag(ec_tagname_t name
, double data
) : m_tagName(name
), m_dynamic(true)
294 std::ostringstream double_str
;
296 m_dataLen
= (ec_taglen_t
)strlen(double_str
.str().c_str()) + 1;
297 m_tagData
= malloc(m_dataLen
);
298 if (m_tagData
!= NULL
) {
299 memcpy((void *)m_tagData
, double_str
.str().c_str(), m_dataLen
);
300 m_dataType
= EC_TAGTYPE_DOUBLE
;
308 * Destructor - frees allocated data and deletes child TAGs.
310 CECTag::~CECTag(void)
312 if (m_dynamic
) free((void *)m_tagData
);
316 * Copy assignment operator.
318 * std::vector uses this, but the compiler-supplied version wouldn't properly
319 * handle m_dynamic and m_tagData. This wouldn't be necessary if m_tagData
320 * was a smart pointer (Hi, Kry!).
322 CECTag
& CECTag::operator=(const CECTag
& tag
)
325 m_state
= tag
.m_state
;
326 m_tagName
= tag
.m_tagName
;
327 m_dynamic
= tag
.m_dynamic
;
328 m_haschildren
= tag
.m_haschildren
;
330 m_dataLen
= tag
.m_dataLen
;
331 m_dataType
= tag
.m_dataType
;
332 if (m_dataLen
!= 0) {
334 m_tagData
= malloc(m_dataLen
);
335 if (m_tagData
!= NULL
) {
336 memcpy((void *)m_tagData
, tag
.m_tagData
, m_dataLen
);
337 } else { // Nice try, but it will crash anyway when out of memory...
343 m_tagData
= tag
.m_tagData
;
348 if (!tag
.m_tagList
.empty()) {
349 m_tagList
.reserve(tag
.m_tagList
.size());
350 for (TagList::size_type i
=0; i
<tag
.m_tagList
.size(); i
++) {
351 m_tagList
.push_back(tag
.m_tagList
[i
]);
352 if (m_tagList
.back().m_error
!= 0) {
353 m_error
= m_tagList
.back().m_error
;
354 #ifndef KEEP_PARTIAL_PACKETS
355 m_tagList
.pop_back();
370 bool CECTag::operator==(const CECTag
& tag
) const
372 return m_dataType
== tag
.m_dataType
373 && m_dataLen
== tag
.m_dataLen
375 || !memcmp(m_tagData
, tag
.m_tagData
, m_dataLen
))
376 && m_tagList
== tag
.m_tagList
;
380 * Add a child tag to this one.
382 * Be very careful that this creates a copy of \e tag. Thus, the following code won't work as expected:
385 * CECPacket *p = new CECPacket(whatever);
386 * CECTag *t1 = new CECTag(whatever);
387 * CECTag *t2 = new CECTag(whatever);
389 * t1.AddTag(*t2); // t2 won't be part of p !!!
393 * To get the desired results, the above should be replaced with something like:
397 * CECPacket *p = new CECPacket(whatever);
398 * CECTag *t1 = new CECTag(whatever);
399 * CECTag *t2 = new CECTag(whatever);
401 * delete t2; // we can safely delete t2 here, because t1 holds a copy
403 * delete t1; // now p holds a copy of both t1 and t2
407 * Then why copying? The answer is to enable simplifying the code like this:
411 * CECPacket *p = new CECPacket(whatever);
412 * CECTag t1(whatever);
413 * t1.AddTag(CECTag(whatever)); // t2 is now created on-the-fly
414 * p.AddTag(t1); // now p holds a copy of both t1 and t2
418 * @param tag a CECTag class instance to add.
419 * @return \b true on succcess, \b false when an error occured
421 bool CECTag::AddTag(const CECTag
& tag
, CValueMap
* valuemap
)
424 return valuemap
->AddTag(tag
, this);
426 // cannot have more than 64k tags
427 wxASSERT(m_tagList
.size() < 0xffff);
429 m_tagList
.push_back(tag
);
430 if (m_tagList
.back().m_error
== 0) {
433 m_error
= m_tagList
.back().m_error
;
434 #ifndef KEEP_PARTIAL_PACKETS
435 m_tagList
.pop_back();
441 void CECTag::AddTag(ec_tagname_t name
, uint64_t data
, CValueMap
* valuemap
)
444 valuemap
->CreateTag(name
, data
, this);
446 AddTag(CECTag(name
, data
));
450 void CECTag::AddTag(ec_tagname_t name
, const wxString
& data
, CValueMap
* valuemap
)
453 valuemap
->CreateTag(name
, data
, this);
455 AddTag(CECTag(name
, data
));
459 bool CECTag::ReadFromSocket(CECSocket
& socket
)
461 if (m_state
== bsName
) {
462 ec_tagname_t tmp_tagName
;
463 if (!socket
.ReadNumber(&tmp_tagName
, sizeof(ec_tagname_t
))) {
467 m_tagName
= tmp_tagName
>> 1;
468 m_haschildren
= (tmp_tagName
& 0x01) ? true : false;
473 if (m_state
== bsType
) {
475 if (!socket
.ReadNumber(&type
, sizeof(ec_tagtype_t
))) {
476 m_dataType
= EC_TAGTYPE_UNKNOWN
;
481 m_state
= bsLengthChld
;
488 if (m_state
== bsLength
|| m_state
== bsLengthChld
) {
490 if (!socket
.ReadNumber(&tagLen
, sizeof(ec_taglen_t
))) {
494 if (m_state
== bsLength
) {
497 m_state
= bsChildCnt
;
502 if (m_state
== bsChildCnt
|| m_state
== bsChildren
) {
503 if (!ReadChildren(socket
)) {
508 if (m_state
== bsData1
) {
509 unsigned int tmp_len
= m_dataLen
;
511 m_dataLen
= tmp_len
- GetTagLen();
513 m_tagData
= malloc(m_dataLen
);
517 m_state
= bsFinished
;
521 if (m_state
== bsData2
) {
522 if (m_tagData
!= NULL
) {
523 if (!socket
.ReadBuffer((void *)m_tagData
, m_dataLen
)) {
526 m_state
= bsFinished
;
538 bool CECTag::WriteTag(CECSocket
& socket
) const
540 ec_tagname_t tmp_tagName
= (m_tagName
<< 1) | (m_tagList
.empty() ? 0 : 1);
541 ec_tagtype_t type
= m_dataType
;
542 ec_taglen_t tagLen
= GetTagLen();
543 wxASSERT(type
!= EC_TAGTYPE_UNKNOWN
);
545 if (!socket
.WriteNumber(&tmp_tagName
, sizeof(ec_tagname_t
))) return false;
546 if (!socket
.WriteNumber(&type
, sizeof(ec_tagtype_t
))) return false;
547 if (!socket
.WriteNumber(&tagLen
, sizeof(ec_taglen_t
))) return false;
549 if (!m_tagList
.empty()) {
550 if (!WriteChildren(socket
)) return false;
554 if (m_tagData
!= NULL
) { // This is here only to make sure everything, it should not be NULL at this point
555 if (!socket
.WriteBuffer(m_tagData
, m_dataLen
)) return false;
562 bool CECTag::ReadChildren(CECSocket
& socket
)
564 if (m_state
== bsChildCnt
) {
566 if (!socket
.ReadNumber(&tmp_tagCount
, sizeof(uint16
))) {
570 if (tmp_tagCount
> 0) {
571 m_tagList
.reserve(tmp_tagCount
);
572 for (int i
=0; i
<tmp_tagCount
; i
++) {
573 m_tagList
.push_back(CECTag(socket
));
575 m_haschildren
= true;
576 m_state
= bsChildren
;
583 if (m_state
== bsChildren
) {
584 for (unsigned int i
=0; i
<m_tagList
.size(); i
++) {
585 CECTag
& tag
= m_tagList
[i
];
587 if (!tag
.ReadFromSocket(socket
)) {
588 if (tag
.m_error
!= 0) {
589 m_error
= tag
.m_error
;
601 bool CECTag::WriteChildren(CECSocket
& socket
) const
603 wxASSERT(m_tagList
.size() < 0xFFFF);
604 uint16 tmp
= (uint16
)m_tagList
.size();
605 if (!socket
.WriteNumber(&tmp
, sizeof(tmp
))) return false;
606 if (!m_tagList
.empty()) {
607 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++) {
608 if (!m_tagList
[i
].WriteTag(socket
)) return false;
615 * Finds the (first) child tag with given name.
617 * @param name TAG name to look for.
618 * @return the tag found, or NULL.
620 const CECTag
* CECTag::GetTagByName(ec_tagname_t name
) const
622 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++)
623 if (m_tagList
[i
].m_tagName
== name
) return &m_tagList
[i
];
628 * Finds the (first) child tag with given name.
630 * @param name TAG name to look for.
631 * @return the tag found, or NULL.
633 CECTag
* CECTag::GetTagByName(ec_tagname_t name
)
635 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++)
636 if (m_tagList
[i
].m_tagName
== name
) return &m_tagList
[i
];
641 * Finds the (first) child tag with given name.
643 * @param name TAG name to look for.
644 * @return the tag found, or a special null-valued tag otherwise.
648 const CECTag
* CECTag::GetTagByNameSafe(ec_tagname_t name
) const
650 const CECTag
* result
= GetTagByName(name
);
652 result
= &s_theNullTag
;
657 * Query TAG length that is suitable for the TAGLEN field (i.e.\
658 * without it's own header size).
660 * @return Tag length, containing its childs' length.
662 uint32
CECTag::GetTagLen(void) const
664 uint32 length
= m_dataLen
;
665 for (TagList::size_type i
=0; i
<m_tagList
.size(); i
++) {
666 length
+= m_tagList
[i
].GetTagLen();
667 length
+= sizeof(ec_tagname_t
) + sizeof(ec_tagtype_t
) + sizeof(ec_taglen_t
) + ((m_tagList
[i
].GetTagCount() > 0) ? 2 : 0);
673 uint64_t CECTag::GetInt() const
675 if (m_tagData
== NULL
) {
676 // Empty tag - This is NOT an error.
677 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
681 switch (m_dataType
) {
682 case EC_TAGTYPE_UINT8
:
683 return PeekUInt8(m_tagData
);
684 case EC_TAGTYPE_UINT16
:
685 return ENDIAN_NTOHS( RawPeekUInt16( m_tagData
) );
686 case EC_TAGTYPE_UINT32
:
687 return ENDIAN_NTOHL( RawPeekUInt32( m_tagData
) );
688 case EC_TAGTYPE_UINT64
:
689 return ENDIAN_NTOHLL( RawPeekUInt64( m_tagData
) );
690 case EC_TAGTYPE_UNKNOWN
:
691 // Empty tag - This is NOT an error.
700 std::string
CECTag::GetStringDataSTL() const
702 if (m_dataType
!= EC_TAGTYPE_STRING
) {
703 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
704 return std::string();
705 } else if (m_tagData
== NULL
) {
707 return std::string();
710 return std::string((const char*)m_tagData
);
714 #ifdef USE_WX_EXTENSIONS
715 wxString
CECTag::GetStringData() const
717 return UTF82unicode(GetStringDataSTL().c_str());
722 CMD4Hash
CECTag::GetMD4Data() const
724 if (m_dataType
!= EC_TAGTYPE_HASH16
) {
725 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
729 EC_ASSERT(m_tagData
!= NULL
);
731 // Doesn't matter if m_tagData is NULL in CMD4Hash(),
732 // that'll just result in an empty hash.
733 return CMD4Hash((const unsigned char *)m_tagData
);
738 * Returns an EC_IPv4_t class.
740 * This function takes care of the enadianness of the port number.
742 * @return EC_IPv4_t class.
744 * @see CECTag(ec_tagname_t, const EC_IPv4_t&)
746 EC_IPv4_t
CECTag::GetIPv4Data() const
750 if (m_tagData
== NULL
) {
752 } else if (m_dataType
!= EC_TAGTYPE_IPV4
) {
755 RawPokeUInt32( p
.m_ip
, RawPeekUInt32( ((EC_IPv4_t
*)m_tagData
)->m_ip
) );
756 p
.m_port
= ENDIAN_NTOHS(((EC_IPv4_t
*)m_tagData
)->m_port
);
763 * Returns a double value.
765 * @note The returned value is what we get by converting the string form
766 * of the number to a double.
768 * @return The double value of the tag.
770 * @see CECTag(ec_tagname_t, double)
772 double CECTag::GetDoubleData(void) const
774 if (m_dataType
!= EC_TAGTYPE_DOUBLE
) {
775 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
777 } else if (m_tagData
== NULL
) {
782 std::istringstream
double_str((const char*)m_tagData
);
790 void CECTag::ConstructStringTag(ec_tagname_t
/*name*/, const std::string
& data
)
792 m_dataLen
= (ec_taglen_t
)strlen(data
.c_str()) + 1;
793 m_tagData
= malloc(m_dataLen
);
794 if (m_tagData
!= NULL
) {
795 memcpy((void *)m_tagData
, data
.c_str(), m_dataLen
);
797 m_dataType
= EC_TAGTYPE_STRING
;
803 void CECTag::SetStringData(const wxString
& s
)
806 free((void *)m_tagData
);
807 ConstructStringTag(0, (const char*)unicode2UTF8(s
));
812 void CECTag::DebugPrint(int level
, bool print_empty
) const
814 if (m_dataLen
|| print_empty
) {
816 for (int i
= level
; i
--;) space
+= wxT(" ");
817 wxString s1
= CFormat(wxT("%s%s %d = ")) % space
% GetDebugNameECTagNames(m_tagName
) % m_dataLen
;
820 case EC_TAG_DETAIL_LEVEL
:
821 s2
= GetDebugNameEC_DETAIL_LEVEL(GetInt()); break;
822 case EC_TAG_SEARCH_TYPE
:
823 s2
= GetDebugNameEC_SEARCH_TYPE(GetInt()); break;
824 case EC_TAG_STAT_VALUE_TYPE
:
825 s2
= GetDebugNameEC_STATTREE_NODE_VALUE_TYPE(GetInt()); break;
827 switch (m_dataType
) {
828 case EC_TAGTYPE_UINT8
:
829 case EC_TAGTYPE_UINT16
:
830 case EC_TAGTYPE_UINT32
:
831 case EC_TAGTYPE_UINT64
:
832 s2
= CFormat(wxT("%d")) % GetInt(); break;
833 case EC_TAGTYPE_STRING
:
834 s2
= GetStringData(); break;
835 case EC_TAGTYPE_DOUBLE
:
836 s2
= CFormat(wxT("%.1f")) % GetDoubleData(); break;
837 case EC_TAGTYPE_HASH16
:
838 s2
= GetMD4Data().Encode(); break;
840 s2
= GetDebugNameECTagTypes(m_dataType
);
843 DoECLogLine(s1
+ s2
);
845 for (TagList::const_iterator it
= m_tagList
.begin(); it
!= m_tagList
.end(); ++it
) {
846 it
->DebugPrint(level
+ 1, true);
852 * \fn CMD4Hash CECTag::GetMD4Data(void) const
854 * \brief Returns a CMD4Hash class.
856 * This function takes care of converting from MSB to LSB as necessary.
858 * \return CMD4Hash class.
860 * \sa CECTag(ec_tagname_t, const CMD4Hash&)
864 * \fn CECTag *CECTag::GetTagByIndex(size_t index) const
866 * \brief Finds the indexth child tag.
868 * \param index 0-based index, 0 <= \e index < GetTagCount()
870 * \return The child tag, or NULL if index out of range.
874 * \fn CECTag *CECTag::GetTagByIndexSafe(size_t index) const
876 * \brief Finds the indexth child tag.
878 * \param index 0-based index, 0 <= \e index < GetTagCount()
880 * \return The child tag, or a special null-valued tag if index out of range.
884 * \fn size_t CECTag::GetTagCount(void) const
886 * \brief Returns the number of child tags.
888 * \return The number of child tags.
892 * \fn const void *CECTag::GetTagData(void) const
894 * \brief Returns a pointer to the TAG DATA.
896 * \return A pointer to the TAG DATA. (As specified with the data field of the constructor.)
900 * \fn uint16 CECTag::GetTagDataLen(void) const
902 * \brief Returns the length of the data buffer.
904 * \return The length of the data buffer.
908 * \fn ec_tagname_t CECTag::GetTagName(void) const
910 * \brief Returns TAGNAME.
912 * \return The name of the tag.
916 * \fn wxString CECTag::GetStringData(void) const
918 * \brief Returns the string data of the tag.
920 * Returns a wxString created from TAGDATA. It is automatically
921 * converted from UTF-8 to the internal application encoding.
922 * Should be used with care (only on tags created with the
923 * CECTag(ec_tagname_t, const wxString&) constructor),
924 * becuse it does not perform any check to see if the tag really contains a
927 * \return The string data of the tag.
929 * \sa CECTag(ec_tagname_t, const wxString&)
933 * \fn uint8 CECTag::GetInt(void) const
935 * \brief Returns the uint8 data of the tag.
937 * This function takes care of the endianness problems with numbers.
939 * \return The uint8 data of the tag.
941 * \sa CECTag(ec_tagname_t, uint8)
945 * \fn uint16 CECTag::GetInt(void) const
947 * \brief Returns the uint16 data of the tag.
949 * This function takes care of the endianness problems with numbers.
951 * \return The uint16 data of the tag.
953 * \sa CECTag(ec_tagname_t, uint16)
957 * \fn uint32 CECTag::GetInt(void) const
959 * \brief Returns the uint32 data of the tag.
961 * This function takes care of the endianness problems with numbers.
963 * \return The uint32 data of the tag.
965 * \sa CECTag(ec_tagname_t, uint32)
969 * \fn uint64 CECTag::GetInt(void) const
971 * \brief Returns the uint64 data of the tag.
973 * This function takes care of the endianness problems with numbers.
975 * \return The uint64 data of the tag.
977 * \sa CECTag(ec_tagname_t, uint64)
979 // File_checked_for_headers