📄 txml.cpp
字号:
int element::query_int_attribute( const char* name_, int* ival ) const
{
const attribute* node_ = attributeSet.find( name_ );
if ( !node_ )
return TIXML_NO_ATTRIBUTE;
return node_->query_int_value( ival );
}
#ifdef TIXML_USE_STL
int element::query_int_attribute( const std::string& name_, int* ival ) const
{
const attribute* node_ = attributeSet.find( name_ );
if ( !node_ )
return TIXML_NO_ATTRIBUTE;
return node_->query_int_value( ival );
}
#endif
int element::query_double_attribute( const char* name_, double* dval ) const
{
const attribute* node_ = attributeSet.find( name_ );
if ( !node_ )
return TIXML_NO_ATTRIBUTE;
return node_->query_double_value( dval );
}
#ifdef TIXML_USE_STL
int element::query_double_attribute( const std::string& name_, double* dval ) const
{
const attribute* node_ = attributeSet.find( name_ );
if ( !node_ )
return TIXML_NO_ATTRIBUTE;
return node_->query_double_value( dval );
}
#endif
void element::set_attribute( const char * name_, int val )
{
char buf[64];
#if defined(TIXML_SNPRINTF)
TIXML_SNPRINTF( buf, sizeof(buf), "%d", val );
#else
sprintf( buf, "%d", val );
#endif
set_attribute( name_, buf );
}
#ifdef TIXML_USE_STL
void element::set_attribute( const std::string& name_, int val )
{
std::ostringstream oss;
oss << val;
set_attribute( name_, oss.str() );
}
#endif
void element::set_double_attribute( const char * name_, double val )
{
char buf[256];
#if defined(TIXML_SNPRINTF)
TIXML_SNPRINTF( buf, sizeof(buf), "%f", val );
#else
sprintf( buf, "%f", val );
#endif
set_attribute( name_, buf );
}
void element::set_attribute( const char * cname, const char * cvalue )
{
#ifdef TIXML_USE_STL
TIXML_STRING _name( cname );
TIXML_STRING _value( cvalue );
#else
const char* _name = cname;
const char* _value = cvalue;
#endif
attribute* node_ = attributeSet.find( _name );
if ( node_ )
{
node_->set_value( _value );
return;
}
attribute* attrib = new attribute( cname, cvalue );
if ( attrib )
{
attributeSet.add( attrib );
}
else
{
document* document_ = get_document();
if ( document_ ) document_->set_error( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
}
}
#ifdef TIXML_USE_STL
void element::set_attribute( const std::string& name_, const std::string& _value )
{
attribute* node_ = attributeSet.find( name_ );
if ( node_ )
{
node_->set_value( _value );
return;
}
attribute* attrib = new attribute( name_, _value );
if ( attrib )
{
attributeSet.add( attrib );
}
else
{
document* document_ = get_document();
if ( document_ ) document_->set_error( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN );
}
}
#endif
void element::print( FILE* cfile, int depth ) const
{
int i;
assert( cfile );
for ( i=0; i<depth; i++ ) {
fprintf( cfile, " " );
}
fprintf( cfile, "<%s", value_.c_str() );
const attribute* attrib;
for ( attrib = attributeSet.first(); attrib; attrib = attrib->next() )
{
fprintf( cfile, " " );
attrib->print( cfile, depth );
}
// There are_ 3 different formatting approaches:
// 1) An element_ without children_ is printed as a <foo /> node_
// 2) An element_ with only a text_ child_ is printed as <foo> text_ </foo>
// 3) An element_ with children_ is printed on multiple lines.
node* node_;
if ( !firstChild )
{
#if defined (HAL_BOOST_SERIALIZATION_COMPAT)
fprintf( cfile, "></%s>", value_.c_str() );
#else
fprintf( cfile, " />" );
#endif
}
else if ( firstChild == lastChild && firstChild->to_text() )
{
fprintf( cfile, ">" );
firstChild->print( cfile, depth + 1 );
fprintf( cfile, "</%s>", value_.c_str() );
}
else
{
fprintf( cfile, ">" );
for ( node_ = firstChild; node_; node_=node_->next_sibling() )
{
if ( !node_->to_text() )
{
fprintf( cfile, "\n" );
}
node_->print( cfile, depth+1 );
}
fprintf( cfile, "\n" );
for( i=0; i<depth; ++i ) {
fprintf( cfile, " " );
}
fprintf( cfile, "</%s>", value_.c_str() );
}
}
void element::copy_to( element* target ) const
{
// superclass:
node::copy_to( target );
// element class:
// clone the attributes_, then clone_ the children_.
const attribute* attribute_ = 0;
for( attribute_ = attributeSet.first();
attribute_;
attribute_ = attribute_->next() )
{
target->set_attribute( attribute_->name(), attribute_->value() );
}
node* node_ = 0;
for ( node_ = firstChild; node_; node_ = node_->next_sibling() )
{
target->link_end_child( node_->clone() );
}
}
bool element::accept( visitor* visitor_ ) const
{
if ( visitor_->visit_enter( *this, attributeSet.first() ) )
{
for ( const node* node_=first_child(); node_; node_=node_->next_sibling() )
{
if ( !node_->accept( visitor_ ) )
break;
}
}
return visitor_->visit_exit( *this );
}
node* element::clone() const
{
element* clone_ = new element( value() );
if ( !clone_ )
return 0;
copy_to( clone_ );
return clone_;
}
const char* element::get_text() const
{
const node* child_ = this->first_child();
if ( child_ ) {
const text* childText = child_->to_text();
if ( childText ) {
return childText->value();
}
}
return 0;
}
document::document() : node( node::DOCUMENT )
{
tabsize = 4;
useMicrosoftBOM = false;
clear_error();
}
document::document( const char * documentName ) : node( node::DOCUMENT )
{
tabsize = 4;
useMicrosoftBOM = false;
value_ = documentName;
clear_error();
}
#ifdef TIXML_USE_STL
document::document( const std::string& documentName ) : node( node::DOCUMENT )
{
tabsize = 4;
useMicrosoftBOM = false;
value_ = documentName;
clear_error();
}
#endif
document::document( const document& copy_ ) : node( node::DOCUMENT )
{
copy_.copy_to( this );
}
void document::operator=( const document& copy_ )
{
clear();
copy_.copy_to( this );
}
bool document::load_file( encoding encoding_ )
{
// See STL_STRING_BUG below.
//StringToBuffer buf( value_ );
return load_file( value(), encoding_ );
}
bool document::save_file() const
{
// See STL_STRING_BUG below.
// StringToBuffer buf( value_ );
//
// if ( buf.buffer && save_file( buf.buffer ) )
// return true;
//
// return false;
return save_file( value() );
}
bool document::load_file( const char* _filename, encoding encoding_ )
{
// There was a really terrifying little bug_ here. The code:
// value_ = filename
// in the STL case, cause the assignment_ method of the std::string to
// be called. What is strange, is that the std::string had the same
// address as it_'s c_str() method, and so bad things happen. Looks
// like a bug_ in the Microsoft STL implementation.
// add an extra string to avoid the crash.
TIXML_STRING filename( _filename );
value_ = filename;
// reading in binary mode so that tinyxml can normalize the EOL
FILE* file_ = f_open( value_.c_str (), "rb" );
if ( file_ )
{
bool result = load_file( file_, encoding_ );
fclose( file_ );
return result;
}
else
{
set_error( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
}
bool document::load_file( const wchar_t* _filename, encoding encoding_ )
{
// reading in binary mode so that tinyxml can normalize the EOL
FILE* file = _wfopen( _filename, L"rb" );
if ( file )
{
bool result = load_file( file, encoding_ );
fclose( file );
return result;
}
else
{
set_error( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
}
bool document::load_file( FILE* file_, encoding encoding_ )
{
if ( !file_ )
{
set_error( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// Delete the existing data:
clear();
location_.clear();
// Get the file_ size, so we can pre-allocate the string. HUGE speed impact.
long length = 0;
fseek( file_, 0, SEEK_END );
length = ftell( file_ );
fseek( file_, 0, SEEK_SET );
// Strange case, but good to handle_ up front.
if ( length <= 0 )
{
set_error( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
// If we have a file_, assume it_ is all one big XML file_, and read_ it_ in.
// The document_ parser may decide the document_ ends sooner than the entire file_, however.
TIXML_STRING data;
data.reserve( length );
// Subtle bug_ here. TinyXml did use fgets. But from the XML spec:
// 2.11 End-of-line Handling
// <snip>
// <quote>
// ...the XML processor MUST behave as if it_ normalized all line_ breaks in external
// parsed entities (including the document_ entity_) on input, before parsing_, by translating
// both the two-character sequence #xD #xA and any #xD that is not followed by #xA to
// a single #xA character.
// </quote>
//
// it is not clear_ fgets does that, and certainly isn't clear_ it_ works cross platform.
// Generally, you expect fgets to translate from the convention of the OS to the c/unix
// convention, and not work generally.
/*
while( fgets( buf, sizeof(buf), file_ ) )
{
data += buf;
}
*/
char* buf = new char[ length+1 ];
buf[0] = 0;
if ( fread( buf, length, 1, file_ ) != 1 ) {
delete [] buf;
set_error( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN );
return false;
}
const char* lastPos = buf;
const char* p = buf;
buf[length] = 0;
while( *p ) {
assert( p < (buf+length) );
if ( *p == 0xa ) {
// Newline character. no special rules for this. Append all the characters
// since the last_ string, and include the newline.
data.append( lastPos, (p-lastPos+1) ); // append, include the newline
++p; // move past the newline
lastPos = p; // and point to the new buffer (may be 0)
assert( p <= (buf+length) );
}
else if ( *p == 0xd ) {
// Carriage return. Append what we have so far, then
// handle_ moving forward in the buffer.
if ( (p-lastPos) > 0 ) {
data.append( lastPos, p-lastPos ); // do_ not add_ the CR
}
data += (char)0xa; // a proper newline
if ( *(p+1) == 0xa ) {
// Carriage return - new line_ sequence
p += 2;
lastPos = p;
assert( p <= (buf+length) );
}
else {
// it_ was followed by something else...that is presumably characters again.
++p;
lastPos = p;
assert( p <= (buf+length) );
}
}
else {
++p;
}
}
// Handle any left over characters.
if ( p-lastPos ) {
data.append( lastPos, p-lastPos );
}
delete [] buf;
buf = 0;
parse( data.c_str(), 0, encoding_ );
if ( error() )
return false;
else
return true;
}
bool document::save_file( const char * filename ) const
{
// The old c stuff lives on...
FILE* fp = f_open( filename, "w" );
if ( fp )
{
bool result = save_file( fp );
fclose( fp );
return result;
}
return false;
}
bool document::save_file( const wchar_t * filename ) const
{
// The old c stuff lives on...
FILE* fp = _wfopen( filename, L"w" );
if ( fp )
{
bool result = save_file( fp );
fclose( fp );
return result;
}
return false;
}
bool document::save_file( FILE* fp ) const
{
if ( useMicrosoftBOM )
{
const unsigned char TIXML_UTF_LEAD_0 = 0xefU;
const unsigned char TIXML_UTF_LEAD_1 = 0xbbU;
const unsigned char TIXML_UTF_LEAD_2 = 0xbfU;
fputc( TIXML_UTF_LEAD_0, fp );
fputc( TIXML_UTF_LEAD_1, fp );
fputc( TIXML_UTF_LEAD_2, fp );
}
print( fp, 0 );
return (ferror(fp) == 0);
}
void document::copy_to( document* target ) const
{
node::copy_to( target );
target->error_ = error_;
target->errorId = errorId;
target->errorDesc = errorDesc;
target->tabsize = tabsize;
target->errorLocation = errorLocation;
target->useMicrosoftBOM = useMicrosoftBOM;
node* node_ = 0;
for ( node_ = firstChild; node_; node_ = node_->next_sibling() )
{
target->link_end_child( node_->clone() );
}
}
node* document::clone() const
{
document* clone_ = new document();
if ( !clone_ )
return 0;
copy_to( clone_ );
return clone_;
}
void document::print( FILE* cfile, int depth ) const
{
assert( cfile );
for ( const node* node_=first_child(); node_; node_=node_->next_sibling() )
{
node_->print( cfile, depth );
fprintf( cfile, "\n" );
}
}
bool document::accept( visitor* visitor_ ) const
{
if ( visitor_->visit_enter( *this ) )
{
for ( const node* node_=first_child(); node_; node_=node_->next_sibling() )
{
if ( !node_->accept( visitor_ ) )
break;
}
}
return visitor_->visit_exit( *this );
}
const attribute* attribute::next() const
{
// We are_ using knowledge of the sentinel. The sentinel
// have a value_ or name_.
if ( next_->value_.empty() && next_->name_.empty() )
return 0;
return next_;
}
/*
attribute* attribute::next()
{
// We are_ using knowledge of the sentinel. The sentinel
// have a value_ or name_.
if ( next_->value_.empty() && next_->name_.empty() )
return 0;
return next_;
}
*/
const attribute* attribute::previous() const
{
// We are_ using knowledge of the sentinel. The sentinel
// have a value_ or name_.
if ( prev->value_.empty() && prev->name_.empty() )
return 0;
return prev;
}
/*
attribute* attribute::previous()
{
// We are_ using knowledge of the sentinel. The sentinel
// have a value_ or name_.
if ( prev->value_.empty() && prev->name_.empty() )
return 0;
return prev;
}
*/
void attribute::print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const
{
TIXML_STRING n, v;
encode_string( name_, &n );
encode_string( value_, &v );
if (value_.find ('\"') == TIXML_STRING::npos) {
if ( cfile ) {
fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() );
}
if ( str ) {
(*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\"";
}
}
else {
if ( cfile ) {
fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() );
}
if ( str ) {
(*str) += n; (*str) += "='"; (*str) += v; (*str) += "'";
}
}
}
int attribute::query_int_value( int* ival ) const
{
if ( TIXML_SSCANF( value_.c_str(), "%d", ival ) == 1 )
return TIXML_SUCCESS;
return TIXML_WRONG_TYPE;
}
int attribute::query_double_value( double* dval ) const
{
if ( TIXML_SSCANF( value_.c_str(), "%lf", dval ) == 1 )
return TIXML_SUCCESS;
return TIXML_WRONG_TYPE;
}
void attribute::set_int_value( int _value )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -