2 // This file is part of the aMule Project.
4 // Copyright (c) 2004-2011 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
34 #include "ECID.h" // Needed for CECID
36 /**********************************************************
40 **********************************************************/
42 //! Defines the Null tag which may be returned by GetTagByNameSafe.
43 const CECTag
CECTag::s_theNullTag
;
46 * Creates a new null-valued CECTag instance
49 * @see GetTagByNameSafe
53 m_dataType(EC_TAGTYPE_UNKNOWN
),
55 m_tagData(NULL
) // All access functions check m_dataType, so no need to allocate a dummy buffer.
60 * Creates a new CECTag instance from the given data
62 * @param name TAG name
63 * @param length length of data buffer
64 * @param data TAG data
67 CECTag::CECTag(ec_tagname_t name
, unsigned int length
, const void *data
) : m_tagName(name
)
72 memcpy(m_tagData
, data
, m_dataLen
);
74 wxASSERT(length
== 0);
78 m_dataType
= EC_TAGTYPE_CUSTOM
;
82 * Creates a new CECTag instance for custom data
84 * @param name TAG name
85 * @param length length of data buffer that will be alloc'ed
86 * @param dataptr pointer to a void pointer which will be assigned the internal TAG data buffer
88 * \note TAG data buffer has to be filled with valid data after the ctor
90 CECTag::CECTag(ec_tagname_t name
, unsigned int length
, void **dataptr
) : m_tagName(name
)
95 m_dataType
= EC_TAGTYPE_CUSTOM
;
99 * Creates a new CECTag instance, which contains an IPv4 address.
101 * This function takes care of the endianness of the port number.
103 * @param name TAG name
104 * @param data The EC_IPv4_t class containing the IPv4 address.
108 CECTag::CECTag(ec_tagname_t name
, const EC_IPv4_t
& data
) : m_tagName(name
)
111 m_dataLen
= sizeof(EC_IPv4_t
);
113 RawPokeUInt32( ((EC_IPv4_t
*)m_tagData
)->m_ip
, RawPeekUInt32( data
.m_ip
) );
114 ((EC_IPv4_t
*)m_tagData
)->m_port
= ENDIAN_HTONS(data
.m_port
);
115 m_dataType
= EC_TAGTYPE_IPV4
;
119 * Creates a new CECTag instance, which contains a MD4 hash.
121 * This function takes care to store hash in network byte order.
123 * @param name TAG name
124 * @param data The CMD4Hash class containing the MD4 hash.
128 CECTag::CECTag(ec_tagname_t name
, const CMD4Hash
& data
) : m_tagName(name
)
132 RawPokeUInt64( m_tagData
, RawPeekUInt64( data
.GetHash() ) );
133 RawPokeUInt64( m_tagData
+ 8, RawPeekUInt64( data
.GetHash() + 8 ) );
134 m_dataType
= EC_TAGTYPE_HASH16
;
138 * Creates a new CECTag instance, which contains a string
140 * @param name TAG name
141 * @param data wxString object, it's contents are converted to UTF-8.
143 * @see GetStringDataSTL()
145 CECTag::CECTag(ec_tagname_t name
, const std::string
& data
) : m_tagName(name
)
147 ConstructStringTag(name
, data
);
151 * Creates a new CECTag instance, which contains a string
153 * @param name TAG name
154 * @param data wxString object, it's contents are converted to UTF-8.
156 * @see GetStringData()
158 CECTag::CECTag(ec_tagname_t name
, const wxString
& data
)
160 ConstructStringTag(name
, (const char*)unicode2UTF8(data
));
162 CECTag::CECTag(ec_tagname_t name
, const wxChar
* data
)
164 ConstructStringTag(name
, (const char*)unicode2UTF8(data
));
170 CECTag::CECTag(const CECTag
& tag
)
177 * Creates a new CECTag instance, which contains an int value.
179 * This takes care of endianness problems with numbers.
181 * @param name TAG name.
182 * @param data number.
186 CECTag::CECTag(ec_tagname_t name
, bool data
) : m_tagName(name
)
190 CECTag::CECTag(ec_tagname_t name
, uint8 data
) : m_tagName(name
)
194 CECTag::CECTag(ec_tagname_t name
, uint16 data
) : m_tagName(name
)
198 CECTag::CECTag(ec_tagname_t name
, uint32 data
) : m_tagName(name
)
202 CECTag::CECTag(ec_tagname_t name
, uint64 data
) : m_tagName(name
)
207 void CECTag::InitInt(uint64 data
)
210 m_dataType
= EC_TAGTYPE_UINT8
;
212 } else if (data
<= 0xFFFF) {
213 m_dataType
= EC_TAGTYPE_UINT16
;
215 } else if (data
<= 0xFFFFFFFF) {
216 m_dataType
= EC_TAGTYPE_UINT32
;
219 m_dataType
= EC_TAGTYPE_UINT64
;
225 switch (m_dataType
) {
226 case EC_TAGTYPE_UINT8
:
227 PokeUInt8( m_tagData
, (uint8
) data
);
229 case EC_TAGTYPE_UINT16
:
230 PokeUInt16( m_tagData
, ENDIAN_HTONS((uint16
) data
));
232 case EC_TAGTYPE_UINT32
:
233 PokeUInt32( m_tagData
, ENDIAN_HTONL((uint32
) data
));
235 case EC_TAGTYPE_UINT64
:
236 PokeUInt64( m_tagData
, ENDIAN_HTONLL(data
) );
242 * Creates a new CECTag instance, which contains a double precision floating point number
244 * @param name TAG name
245 * @param data double number
247 * @note The actual data is converted to string representation, because we have not found
248 * yet an effective and safe way to transmit floating point numbers.
250 * @see GetDoubleData()
252 CECTag::CECTag(ec_tagname_t name
, double data
) : m_tagName(name
)
254 std::ostringstream double_str
;
256 std::string double_string
= double_str
.str();
257 const char * double_chr
= double_string
.c_str();
258 m_dataLen
= (ec_taglen_t
)strlen(double_chr
) + 1;
260 memcpy(m_tagData
, double_chr
, m_dataLen
);
261 m_dataType
= EC_TAGTYPE_DOUBLE
;
265 * Destructor - frees allocated data and deletes child TAGs.
267 CECTag::~CECTag(void)
273 * Copy assignment operator.
275 * std::vector uses this, but the compiler-supplied version wouldn't properly
276 * handle m_dynamic and m_tagData. This wouldn't be necessary if m_tagData
277 * was a smart pointer (Hi, Kry!).
279 CECTag
& CECTag::operator=(const CECTag
& tag
)
282 m_tagName
= tag
.m_tagName
;
283 m_dataLen
= tag
.m_dataLen
;
284 m_dataType
= tag
.m_dataType
;
286 if (m_dataLen
!= 0) {
288 memcpy(m_tagData
, tag
.m_tagData
, m_dataLen
);
293 for (const_iterator it
= tag
.begin(); it
!= tag
.end(); ++it
) {
294 m_tagList
.push_back(*it
);
304 bool CECTag::operator==(const CECTag
& tag
) const
306 return m_dataType
== tag
.m_dataType
307 && m_tagName
== tag
.m_tagName
308 && m_dataLen
== tag
.m_dataLen
310 || !memcmp(m_tagData
, tag
.m_tagData
, m_dataLen
))
311 && m_tagList
== tag
.m_tagList
;
315 * Add a child tag to this one. The tag argument is reset to an empty tag.
317 * Be very careful that this method swallows the content of \e tag, leaving \e tag empty.
318 * Thus, the following code won't work as expected:
321 * CECPacket *p = new CECPacket(whatever);
322 * CECTag *t1 = new CECTag(whatever);
323 * CECTag *t2 = new CECTag(whatever);
325 * t1->AddTag(*t2); // t2 won't be part of p !!!
329 * To get the desired results, the above should be replaced with something like:
333 * CECPacket *p = new CECPacket(whatever);
334 * CECTag *t1 = new CECTag(whatever);
335 * CECTag *t2 = new CECTag(whatever);
337 * delete t2; // we can safely delete the now empty t2 here, because t1 holds its content
339 * delete t1; // now p holds the content of both t1 and t2
343 * Then why copying? The answer is to enable simplifying the code like this:
347 * CECPacket *p = new CECPacket(whatever);
348 * CECTag t1(whatever);
349 * t1.AddTag(CECTag(whatever)); // t2 is now created on-the-fly
350 * p->AddTag(t1); // now p holds a copy of both t1 and t2
354 * @param tag a CECTag class instance to add.
355 * @return \b true if tag was really added,
356 * \b false when it was omitted through valuemap.
358 bool CECTag::AddTag(const CECTag
& tag
, CValueMap
* valuemap
)
361 return valuemap
->AddTag(tag
, this);
363 // cannot have more than 64k tags
364 wxASSERT(m_tagList
.size() < 0xffff);
366 // First add an empty tag.
367 m_tagList
.push_back(CECEmptyTag());
368 // Then exchange the data. The original tag will be destroyed right after this call anyway.
369 // UGLY - GCC allows a reference to an in place constructed object only to be passed as const.
370 // So pass it the way it wants it and then cheat and cast it back to non-const. :-/
371 CECTag
& wtag
= const_cast<CECTag
&>(tag
);
372 wtag
.swap(m_tagList
.back());
376 void CECTag::AddTag(ec_tagname_t name
, uint64_t data
, CValueMap
* valuemap
)
379 valuemap
->CreateTag(name
, data
, this);
381 AddTag(CECTag(name
, data
));
385 void CECTag::AddTag(ec_tagname_t name
, const wxString
& data
, CValueMap
* valuemap
)
388 valuemap
->CreateTag(name
, data
, this);
390 AddTag(CECTag(name
, data
));
394 void CECTag::AddTag(ec_tagname_t name
, const CMD4Hash
& data
, CValueMap
* valuemap
)
397 valuemap
->CreateTag(name
, data
, this);
399 AddTag(CECTag(name
, data
));
403 void CECTag::swap(CECTag
& t2
)
405 std::swap(m_tagName
, t2
.m_tagName
);
406 std::swap(m_dataType
, t2
.m_dataType
);
407 std::swap(m_dataLen
, t2
.m_dataLen
);
408 std::swap(m_tagData
, t2
.m_tagData
);
409 std::swap(m_tagList
, t2
.m_tagList
);
412 bool CECTag::ReadFromSocket(CECSocket
& socket
)
414 ec_tagname_t tmp_tagName
;
415 if (!socket
.ReadNumber(&tmp_tagName
, sizeof(ec_tagname_t
))) {
418 m_tagName
= tmp_tagName
>> 1;
419 bool hasChildren
= (tmp_tagName
& 0x01) != 0;
421 if (!socket
.ReadNumber(&m_dataType
, sizeof(ec_tagtype_t
))) {
425 if (!socket
.ReadNumber(&m_dataLen
, sizeof(ec_taglen_t
))) {
429 if (hasChildren
&& !ReadChildren(socket
)) {
433 unsigned int tmp_len
= m_dataLen
;
435 m_dataLen
= tmp_len
- GetTagLen();
438 if (!socket
.ReadBuffer(m_tagData
, m_dataLen
)) {
449 bool CECTag::WriteTag(CECSocket
& socket
) const
451 ec_tagname_t tmp_tagName
= (m_tagName
<< 1) | (m_tagList
.empty() ? 0 : 1);
452 ec_tagtype_t type
= m_dataType
;
453 ec_taglen_t tagLen
= GetTagLen();
454 wxASSERT(type
!= EC_TAGTYPE_UNKNOWN
);
456 if (!socket
.WriteNumber(&tmp_tagName
, sizeof(ec_tagname_t
))) return false;
457 if (!socket
.WriteNumber(&type
, sizeof(ec_tagtype_t
))) return false;
458 if (!socket
.WriteNumber(&tagLen
, sizeof(ec_taglen_t
))) return false;
460 if (!m_tagList
.empty()) {
461 if (!WriteChildren(socket
)) return false;
465 if (m_tagData
!= NULL
) { // This is here only to make sure everything, it should not be NULL at this point
466 if (!socket
.WriteBuffer(m_tagData
, m_dataLen
)) return false;
473 bool CECTag::ReadChildren(CECSocket
& socket
)
476 if (!socket
.ReadNumber(&tmp_tagCount
, sizeof(uint16
))) {
480 for (int i
= 0; i
< tmp_tagCount
; i
++) {
481 m_tagList
.push_back(CECTag());
482 CECTag
& tag
= m_tagList
.back();
483 if (!tag
.ReadFromSocket(socket
)) {
490 bool CECTag::WriteChildren(CECSocket
& socket
) const
492 wxASSERT(m_tagList
.size() < 0xFFFF);
493 uint16 tmp
= (uint16
)m_tagList
.size();
494 if (!socket
.WriteNumber(&tmp
, sizeof(tmp
))) return false;
495 for (const_iterator it
= begin(); it
!= end(); ++it
) {
496 if (!it
->WriteTag(socket
)) return false;
502 * Finds the (first) child tag with given name.
504 * @param name TAG name to look for.
505 * @return the tag found, or NULL.
507 const CECTag
* CECTag::GetTagByName(ec_tagname_t name
) const
509 for (const_iterator it
= begin(); it
!= end(); ++it
) {
510 if (it
->m_tagName
== name
) return & *it
;
516 * Finds the (first) child tag with given name.
518 * @param name TAG name to look for.
519 * @return the tag found, or NULL.
521 CECTag
* CECTag::GetTagByName(ec_tagname_t name
)
523 for (TagList::iterator it
= m_tagList
.begin(); it
!= m_tagList
.end(); ++it
) {
524 if (it
->m_tagName
== name
) return & *it
;
530 * Finds the (first) child tag with given name.
532 * @param name TAG name to look for.
533 * @return the tag found, or a special null-valued tag otherwise.
537 const CECTag
* CECTag::GetTagByNameSafe(ec_tagname_t name
) const
539 const CECTag
* result
= GetTagByName(name
);
541 result
= &s_theNullTag
;
546 * Query TAG length that is suitable for the TAGLEN field (i.e.\
547 * without it's own header size).
549 * @return Tag length, containing its childs' length.
551 uint32
CECTag::GetTagLen(void) const
553 uint32 length
= m_dataLen
;
554 for (const_iterator it
= begin(); it
!= end(); ++it
) {
555 length
+= it
->GetTagLen();
556 length
+= sizeof(ec_tagname_t
) + sizeof(ec_tagtype_t
) + sizeof(ec_taglen_t
) + (it
->HasChildTags() ? 2 : 0);
562 uint64_t CECTag::GetInt() const
564 if (m_tagData
== NULL
) {
565 // Empty tag - This is NOT an error.
566 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
570 switch (m_dataType
) {
571 case EC_TAGTYPE_UINT8
:
572 return PeekUInt8(m_tagData
);
573 case EC_TAGTYPE_UINT16
:
574 return ENDIAN_NTOHS( RawPeekUInt16( m_tagData
) );
575 case EC_TAGTYPE_UINT32
:
576 return ENDIAN_NTOHL( RawPeekUInt32( m_tagData
) );
577 case EC_TAGTYPE_UINT64
:
578 return ENDIAN_NTOHLL( RawPeekUInt64( m_tagData
) );
579 case EC_TAGTYPE_UNKNOWN
:
580 // Empty tag - This is NOT an error.
589 std::string
CECTag::GetStringDataSTL() const
591 if (m_dataType
!= EC_TAGTYPE_STRING
) {
592 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
593 return std::string();
594 } else if (m_tagData
== NULL
) {
596 return std::string();
599 return std::string(m_tagData
);
603 #ifdef USE_WX_EXTENSIONS
604 wxString
CECTag::GetStringData() const
606 return UTF82unicode(GetStringDataSTL().c_str());
611 CMD4Hash
CECTag::GetMD4Data() const
613 if (m_dataType
!= EC_TAGTYPE_HASH16
) {
614 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
618 EC_ASSERT(m_tagData
!= NULL
);
620 // Doesn't matter if m_tagData is NULL in CMD4Hash(),
621 // that'll just result in an empty hash.
622 return CMD4Hash((const unsigned char *)m_tagData
);
627 * Returns an EC_IPv4_t class.
629 * This function takes care of the endianness of the port number.
631 * @return EC_IPv4_t class.
633 * @see CECTag(ec_tagname_t, const EC_IPv4_t&)
635 EC_IPv4_t
CECTag::GetIPv4Data() const
639 if (m_dataType
!= EC_TAGTYPE_IPV4
) {
640 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
641 } else if (m_tagData
== NULL
) {
644 RawPokeUInt32( p
.m_ip
, RawPeekUInt32( ((EC_IPv4_t
*)m_tagData
)->m_ip
) );
645 p
.m_port
= ENDIAN_NTOHS(((EC_IPv4_t
*)m_tagData
)->m_port
);
652 * Returns a double value.
654 * @note The returned value is what we get by converting the string form
655 * of the number to a double.
657 * @return The double value of the tag.
659 * @see CECTag(ec_tagname_t, double)
661 double CECTag::GetDoubleData(void) const
663 if (m_dataType
!= EC_TAGTYPE_DOUBLE
) {
664 EC_ASSERT(m_dataType
== EC_TAGTYPE_UNKNOWN
);
666 } else if (m_tagData
== NULL
) {
671 std::istringstream
double_str(m_tagData
);
679 void CECTag::ConstructStringTag(ec_tagname_t name
, const std::string
& data
)
682 m_dataLen
= (ec_taglen_t
)strlen(data
.c_str()) + 1;
684 memcpy(m_tagData
, data
.c_str(), m_dataLen
);
685 m_dataType
= EC_TAGTYPE_STRING
;
688 void CECTag::SetStringData(const wxString
& s
)
692 ConstructStringTag(m_tagName
, (const char*)unicode2UTF8(s
));
697 bool CECTag::AssignIfExist(ec_tagname_t tagname
, bool *target
) const
700 const CECTag
*tag
= GetTagByName(tagname
);
702 ret
= tag
->GetInt() > 0;
710 bool CECTag::AssignIfExist(ec_tagname_t tagname
, bool &target
) const
712 const CECTag
*tag
= GetTagByName(tagname
);
714 target
= tag
->GetInt() > 0;
720 uint8_t CECTag::AssignIfExist(ec_tagname_t tagname
, uint8_t *target
) const
723 const CECTag
*tag
= GetTagByName(tagname
);
725 EC_ASSERT((tag
->GetType() == EC_TAGTYPE_UINT8
) || (m_dataType
== EC_TAGTYPE_UNKNOWN
));
734 bool CECTag::AssignIfExist(ec_tagname_t tagname
, uint8_t &target
) const
736 const CECTag
*tag
= GetTagByName(tagname
);
738 EC_ASSERT((tag
->GetType() == EC_TAGTYPE_UINT8
) || (m_dataType
== EC_TAGTYPE_UNKNOWN
));
739 target
= tag
->GetInt();
745 uint16_t CECTag::AssignIfExist(ec_tagname_t tagname
, uint16_t *target
) const
748 const CECTag
*tag
= GetTagByName(tagname
);
751 (tag
->GetType() == EC_TAGTYPE_UINT16
)
752 || (tag
->GetType() == EC_TAGTYPE_UINT8
)
753 || (m_dataType
== EC_TAGTYPE_UNKNOWN
)
763 bool CECTag::AssignIfExist(ec_tagname_t tagname
, uint16_t &target
) const
765 const CECTag
*tag
= GetTagByName(tagname
);
768 (tag
->GetType() == EC_TAGTYPE_UINT16
)
769 || (tag
->GetType() == EC_TAGTYPE_UINT8
)
770 || (m_dataType
== EC_TAGTYPE_UNKNOWN
)
772 target
= tag
->GetInt();
778 uint32_t CECTag::AssignIfExist(ec_tagname_t tagname
, uint32_t *target
) const
781 const CECTag
*tag
= GetTagByName(tagname
);
784 (tag
->GetType() == EC_TAGTYPE_UINT32
)
785 || (tag
->GetType() == EC_TAGTYPE_UINT16
)
786 || (tag
->GetType() == EC_TAGTYPE_UINT8
)
787 || (m_dataType
== EC_TAGTYPE_UNKNOWN
)
797 bool CECTag::AssignIfExist(ec_tagname_t tagname
, uint32_t &target
) const
799 const CECTag
*tag
= GetTagByName(tagname
);
802 (tag
->GetType() == EC_TAGTYPE_UINT32
)
803 || (tag
->GetType() == EC_TAGTYPE_UINT16
)
804 || (tag
->GetType() == EC_TAGTYPE_UINT8
)
805 || (m_dataType
== EC_TAGTYPE_UNKNOWN
)
807 target
= tag
->GetInt();
813 uint64_t CECTag::AssignIfExist(ec_tagname_t tagname
, uint64_t *target
) const
816 const CECTag
*tag
= GetTagByName(tagname
);
826 bool CECTag::AssignIfExist(ec_tagname_t tagname
, uint64_t &target
) const
828 const CECTag
*tag
= GetTagByName(tagname
);
830 target
= tag
->GetInt();
836 time_t CECTag::AssignIfExist(ec_tagname_t tagname
, time_t *target
) const
839 const CECTag
*tag
= GetTagByName(tagname
);
849 bool CECTag::AssignIfExist(ec_tagname_t tagname
, time_t &target
) const
851 const CECTag
*tag
= GetTagByName(tagname
);
853 target
= tag
->GetInt();
859 double CECTag::AssignIfExist(ec_tagname_t tagname
, double *target
) const
862 const CECTag
*tag
= GetTagByName(tagname
);
864 ret
= tag
->GetDoubleData();
872 bool CECTag::AssignIfExist(ec_tagname_t tagname
, double &target
) const
874 const CECTag
*tag
= GetTagByName(tagname
);
876 target
= tag
->GetDoubleData();
882 float CECTag::AssignIfExist(ec_tagname_t tagname
, float *target
) const
885 const CECTag
*tag
= GetTagByName(tagname
);
887 ret
= tag
->GetDoubleData();
895 bool CECTag::AssignIfExist(ec_tagname_t tagname
, float &target
) const
897 const CECTag
*tag
= GetTagByName(tagname
);
899 target
= tag
->GetDoubleData();
905 CMD4Hash
CECTag::AssignIfExist(ec_tagname_t tagname
, CMD4Hash
*target
) const
908 const CECTag
*tag
= GetTagByName(tagname
);
910 ret
= tag
->GetMD4Data();
918 bool CECTag::AssignIfExist(ec_tagname_t tagname
, CMD4Hash
&target
) const
920 const CECTag
*tag
= GetTagByName(tagname
);
922 target
= tag
->GetMD4Data();
928 std::string
CECTag::AssignIfExist(ec_tagname_t tagname
, std::string
*target
) const
931 const CECTag
*tag
= GetTagByName(tagname
);
933 ret
= tag
->GetStringDataSTL();
941 bool CECTag::AssignIfExist(ec_tagname_t tagname
, std::string
&target
) const
943 const CECTag
*tag
= GetTagByName(tagname
);
945 target
= tag
->GetStringDataSTL();
951 #ifdef USE_WX_EXTENSIONS
952 wxString
CECTag::AssignIfExist(ec_tagname_t tagname
, wxString
*target
) const
955 const CECTag
*tag
= GetTagByName(tagname
);
957 ret
= tag
->GetStringData();
965 bool CECTag::AssignIfExist(ec_tagname_t tagname
, wxString
&target
) const
967 const CECTag
*tag
= GetTagByName(tagname
);
969 target
= tag
->GetStringData();
978 void CECTag::DebugPrint(int level
, bool print_empty
) const
980 if (m_dataLen
|| print_empty
) {
982 for (int i
= level
; i
--;) space
+= wxT(" ");
983 wxString s1
= CFormat(wxT("%s%s %d = ")) % space
% GetDebugNameECTagNames(m_tagName
) % m_dataLen
;
986 case EC_TAG_DETAIL_LEVEL
:
987 s2
= GetDebugNameEC_DETAIL_LEVEL(GetInt()); break;
988 case EC_TAG_SEARCH_TYPE
:
989 s2
= GetDebugNameEC_SEARCH_TYPE(GetInt()); break;
990 case EC_TAG_STAT_VALUE_TYPE
:
991 s2
= GetDebugNameEC_STATTREE_NODE_VALUE_TYPE(GetInt()); break;
993 switch (m_dataType
) {
994 case EC_TAGTYPE_UINT8
:
995 case EC_TAGTYPE_UINT16
:
996 case EC_TAGTYPE_UINT32
:
997 case EC_TAGTYPE_UINT64
:
998 s2
= CFormat(wxT("%d")) % GetInt(); break;
999 case EC_TAGTYPE_STRING
:
1000 s2
= GetStringData(); break;
1001 case EC_TAGTYPE_DOUBLE
:
1002 s2
= CFormat(wxT("%.1f")) % GetDoubleData(); break;
1003 case EC_TAGTYPE_HASH16
:
1004 s2
= GetMD4Data().Encode(); break;
1005 case EC_TAGTYPE_CUSTOM
:
1006 if (m_dataLen
== 0) {
1009 // Make a hex dump (limited to maxOutput)
1010 const uint32 maxOutput
= 50;
1011 for (uint32 i
= 0; i
< m_dataLen
; i
++) {
1012 if (i
== maxOutput
) {
1016 s2
+= CFormat(wxT("%02X ")) % (unsigned char) m_tagData
[i
];
1021 s2
= GetDebugNameECTagTypes(m_dataType
);
1024 DoECLogLine(s1
+ s2
);
1026 for (TagList::const_iterator it
= m_tagList
.begin(); it
!= m_tagList
.end(); ++it
) {
1027 it
->DebugPrint(level
+ 1, true);
1033 * \fn CMD4Hash CECTag::GetMD4Data(void) const
1035 * \brief Returns a CMD4Hash class.
1037 * This function takes care of converting from MSB to LSB as necessary.
1039 * \return CMD4Hash class.
1041 * \sa CECTag(ec_tagname_t, const CMD4Hash&)
1045 * \fn CECTag *CECTag::GetTagByIndex(size_t index) const
1047 * \brief Finds the indexth child tag.
1049 * \param index 0-based index, 0 <= \e index < GetTagCount()
1051 * \return The child tag, or NULL if index out of range.
1055 * \fn CECTag *CECTag::GetTagByIndexSafe(size_t index) const
1057 * \brief Finds the indexth child tag.
1059 * \param index 0-based index, 0 <= \e index < GetTagCount()
1061 * \return The child tag, or a special null-valued tag if index out of range.
1065 * \fn size_t CECTag::GetTagCount(void) const
1067 * \brief Returns the number of child tags.
1069 * \return The number of child tags.
1073 * \fn const void *CECTag::GetTagData(void) const
1075 * \brief Returns a pointer to the TAG DATA.
1077 * \return A pointer to the TAG DATA. (As specified with the data field of the constructor.)
1081 * \fn uint16 CECTag::GetTagDataLen(void) const
1083 * \brief Returns the length of the data buffer.
1085 * \return The length of the data buffer.
1089 * \fn ec_tagname_t CECTag::GetTagName(void) const
1091 * \brief Returns TAGNAME.
1093 * \return The name of the tag.
1097 * \fn wxString CECTag::GetStringData(void) const
1099 * \brief Returns the string data of the tag.
1101 * Returns a wxString created from TAGDATA. It is automatically
1102 * converted from UTF-8 to the internal application encoding.
1103 * Should be used with care (only on tags created with the
1104 * CECTag(ec_tagname_t, const wxString&) constructor),
1105 * becuse it does not perform any check to see if the tag really contains a
1108 * \return The string data of the tag.
1110 * \sa CECTag(ec_tagname_t, const wxString&)
1114 * \fn uint8 CECTag::GetInt(void) const
1116 * \brief Returns the uint8 data of the tag.
1118 * This function takes care of the endianness problems with numbers.
1120 * \return The uint8 data of the tag.
1122 * \sa CECTag(ec_tagname_t, uint8)
1126 * \fn uint16 CECTag::GetInt(void) const
1128 * \brief Returns the uint16 data of the tag.
1130 * This function takes care of the endianness problems with numbers.
1132 * \return The uint16 data of the tag.
1134 * \sa CECTag(ec_tagname_t, uint16)
1138 * \fn uint32 CECTag::GetInt(void) const
1140 * \brief Returns the uint32 data of the tag.
1142 * This function takes care of the endianness problems with numbers.
1144 * \return The uint32 data of the tag.
1146 * \sa CECTag(ec_tagname_t, uint32)
1150 * \fn uint64 CECTag::GetInt(void) const
1152 * \brief Returns the uint64 data of the tag.
1154 * This function takes care of the endianness problems with numbers.
1156 * \return The uint64 data of the tag.
1158 * \sa CECTag(ec_tagname_t, uint64)
1161 uint32
CECID::s_IDCounter
= 0;
1163 // File_checked_for_headers