设计模式与XML(三)组合模式、桥接模式和适配器模式(C++)

本文深入探讨了C++中三种重要的设计模式——组合模式,用于将对象组织成树形结构;桥接模式,旨在分离抽象与实现,提高代码可扩展性;以及适配器模式,用于兼容不同接口的对象。通过实例解析,展示了如何在实际项目中应用这些模式。
摘要由CSDN通过智能技术生成

一、实验目的及要求

1、掌握结构型模式的概念。

2、掌握适配器模式、桥接模式、组合模式、装饰器模式、外观模式、享元模式、代理模式的构造方式及使用情景。

 

二、实验设备(环境)

1、   软件需求: Dev-Cpp5.4, Rational Rose / Microsoft Visio

2、   硬件需求: Pentium III 450以上的CPU处理器,1G以上的内存,2G的自由硬盘空间

 

三、实验内容

1、操作系统中的目录结构是一个树形结构,因此在对文件(File)和文件夹(Folder)进行操作时可以应用组合模式。对于文件夹的操作,将递归处理文件夹中的每一个子文件夹和文件。利用组合模式设计并实现某一指定文件夹下所有文件的属性(如文件名)的读取。

 

2、桥接模式将抽象部分与它的实现部分分离,将两个角色之间的继承关系改为关联关系。利用桥接模式设计并实现步骤1中文件的属性(如文件名)的多种输出方式:文本输出(TextExport)、数据库输出(DbExport)、XML输出(XmlExport)。

 

3、为了提高开发效率,现需要重用已有的XML文件操作接口(API),这些操作封装在一些由第三方提供的类中。使用适配器模式设计并实现步骤2中XML输出模块,实现在不修改现有类的基础上重用第三方XML文件操作接口。

 

 

四、实验步骤与结果

练习一

 

1.组合模式设计结构图:

2.实验结果截图:

3.代码分析:

 

 Component.cpp

#include "Component.h"
Component::Component()
{
}
Component::~Component()
{
}
void Component::Add(const Component& com)
{
}
Component* Component::GetChild(int index)
{
	return 0;
}
void Component::Remove(const Component& com)
{
}

 

 Component.h

#ifndef _COMPONENT_H_
#define _COMPONENT_H_
#include <string>
using namespace std;
class Component
{
public:
	Component();
	virtual ~Component();
public:
	virtual void Operation(string path) = 0;
	virtual void Add(const Component&);
	virtual void Remove(const Component&);
	virtual Component* GetChild(int);
protected:
private:
};
#endif //~_COMPONENT_H_

Composite.cpp

#include "Composite.h"
#include "Component.h"
#include "Leaf.h"
#include <io.h>
#include <cstring>
#include <string>
#include <vector>
#include <iostream>
Composite::Composite()
{
}
Composite::~Composite()
{
}
void Composite::Operation(string path)
{
	vector<string> files;
	long hFile = 0;
	struct _finddata_t fileinfo;  
	
	string p;  
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) {
		do {
			if ((fileinfo.attrib & _A_SUBDIR)) {  
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) {
					files.push_back(p.assign(path).append("\\").append(fileinfo.name));
					Operation(p.assign(path).append("\\").append(fileinfo.name));
				}
			}
			else {
				Leaf f;
				f.Operation(p.assign(path).append("\\").append(fileinfo.name));
			}
		} while (_findnext(hFile, &fileinfo) == 0);  
		_findclose(hFile);
	}
}
void Composite::Add(Component* com)
{
	comVec.push_back(com);
}
void Composite::Remove(Component* com)
{
	vector<Component*>::iterator comIter;
	for (comIter = comVec.begin(); comIter != comVec.end(); comIter++)
		if ((*comIter) == com) comVec.erase(comIter);
}
Component* Composite::GetChild(int index)
{
	return comVec[index];
}

 Composite.h

#ifndef _COMPOSITE_H_
#define _COMPOSITE_H_
#include "Component.h"
#include <vector>
using namespace std;
class Composite :public Component
{
public:
	Composite();
	~Composite();
public:
	void Operation(string path);
	void Add(Component* com);
	void Remove(Component* com);
	Component* GetChild(int index);
protected:
private:
	vector<Component*> comVec;
};
#endif //~_COMPOSITE_H_

 Leaf.cpp

#include "Leaf.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
Leaf::Leaf()
{
}
Leaf::~Leaf()
{
}
void Leaf::Operation(string path)
{
	cout << path << endl;
}

 Leaf.h

#pragma once
#ifndef _LEAF_H_
#define _LEAF_H_
#include "Component.h"
class Leaf :public Component
{
public:
	Leaf();
	~Leaf();
	void Operation(string path);
protected:
private:
};
#endif //~_LEAF_H_

 main.cpp

#include "Component.h"
#include "Composite.h"
#include "Leaf.h"
#include <iostream>
#include <io.h>
#include <cstring>
#include <string>
#include <fstream>
#include <vector>
using namespace std;


int main(int argc, char* argv[])
{
	Composite *com = new Composite();
	string path = "D:\\设计模式课程";
	com->Operation(path);

//	system("pause");// 
	return 0;
}

练习二

1.桥接模式设计结构图UML图:

2.实验结果:

 

 

3.代码分析

Composite.h

#ifndef _COMPOSITE_H_
#define _COMPOSITE_H_
#include "Component.h"
#include <vector>
using namespace std;
class Composite :public Component
{
public:
	Composite();
	~Composite();
public:
	void Operation(string path,vector<string> &str);
	void Add(Component* com);
	void Remove(Component* com);
	Component* GetChild(int index);
protected:
private:
	vector<Component*> comVec;
};
#endif //~_COMPOSITE_H_

Composite.cpp

#include "Composite.h"
#include "Component.h"
#include "Leaf.h"
#include <io.h>
#include <cstring>
#include <string>
#include <vector>
#include <iostream>
//#define NULL 0 //define NULL POINTOR
Composite::Composite()
{
	//vector<Component*>::iterator itend = comVec.begin();
}
Composite::~Composite()
{
}
void Composite::Operation(string path,vector<string> &str)
{
	str.push_back(path);
	vector<string> files;
	//文件句柄
	long hFile = 0;
	//文件信息
	struct _finddata_t fileinfo;  //很少用的文件信息读取结构
	string p;  //string类很有意思的一个赋值函数:assign(),有很多重载版本
	if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) {
		do {
			if ((fileinfo.attrib & _A_SUBDIR)) {  //比较文件类型是否是文件夹
				if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0) {
					files.push_back(p.assign(path).append("\\").append(fileinfo.name));
					Operation(p.assign(path).append("\\").append(fileinfo.name),str);
				}
			}
			else {
				Leaf f;
				f.Operation(p.assign(path).append("\\").append(fileinfo.name),str);
			}
		} while (_findnext(hFile, &fileinfo) == 0);  //寻找下一个,成功返回0,否则-1
		_findclose(hFile);
	}
}
void Composite::Add(Component* com)
{
	comVec.push_back(com);
}
void Composite::Remove(Component* com)
{
	vector<Component*>::iterator comIter;
	for (comIter = comVec.begin(); comIter != comVec.end(); comIter++)
		if ((*comIter) == com) comVec.erase(comIter);
}
Component* Composite::GetChild(int index)
{
	return comVec[index];
}

Component.h

#ifndef _COMPONENT_H_
#define _COMPONENT_H_
#include <string>
#include <vector>
using namespace std;
class Component
{
public:
	Component();
	virtual ~Component();
public:
	virtual void Operation(string path,vector<string> &str) = 0;
	virtual void Add(const Component&);
	virtual void Remove(const Component&);
	virtual Component* GetChild(int);
protected:
private:
};
#endif //~_COMPONENT_H_

Component.cpp

#include "Component.h"
Component::Component()
{
}
Component::~Component()
{
}
void Component::Add(const Component& com)
{
}
Component* Component::GetChild(int index)
{
	return 0;
}
void Component::Remove(const Component& com)
{
}

Leaf.h

#pragma once
#ifndef _LEAF_H_
#define _LEAF_H_
#include "Component.h"
class Leaf :public Component
{
public:
	Leaf();
	~Leaf();
	void Operation(string path,vector<string> &str);
protected:
private:
};
#endif //~_LEAF_H_

Leaf.cpp

#include "Leaf.h"
#include <iostream>
#include <string>
#include <vector>
using namespace std;
Leaf::Leaf()
{
}
Leaf::~Leaf()
{
}
void Leaf::Operation(string path,vector<string> &str)
{
	str.push_back(path);
}

EXport.cpp

#include "Export.h"
#include "ExportImp.h"
#include <iostream>
using namespace std;
Export::Export()
{
}

Export::~Export()
{
}

TextExport::TextExport(TextExportImp * imp)
{
	_imp = imp;
}

TextExport::~TextExport()
{
}
void TextExport::Operation(vector<string> str)
{
	_imp->Operation(str);
}

DbExport::DbExport(DbExportImp * imp)
{
	_imp = imp;
}

DbExport::~DbExport()
{
}
void DbExport::Operation(vector<string> str)
{
	_imp->Operation(str);
}

XmlExport::XmlExport(XmlExportImp * imp)
{
	_imp = imp;
}

XmlExport::~XmlExport()
{
}

void XmlExport::Operation(vector<string> str)
{
	_imp->Operation(str);
}

EXport.h

#ifndef _EXPORT_H
#define _EXPORT_H
#include <string>
#include <vector>
#include "ExportImp.h"
using namespace std;

class ExportImp;
class Export
{
public:
	virtual ~Export();
	virtual void Operation(vector<string> str) = 0;
protected:
	Export();
private:
};
class TextExport :public Export
{
public:
	TextExport(TextExportImp* imp);
	~TextExport();
	void Operation(vector<string> str);
protected:
private:
	ExportImp * _imp;
};
class DbExport :public Export
{
public:
	DbExport(DbExportImp* imp);
	~DbExport();
	void Operation(vector<string> str);
protected:
private:
	DbExportImp * _imp;
};
class XmlExport :public Export
{
public:
	XmlExport(XmlExportImp* imp);
	~XmlExport();
	void Operation(vector<string> str);
protected:
private:
	XmlExportImp * _imp;
};
#endif //~_ABSTRACTION_H_

ExportImp.cpp

#include "ExportImp.h"
#include <io.h>
#include <fstream>
#include <iostream>
#include "tinyxml2.h"


using namespace std;
using namespace tinyxml2;
ExportImp::ExportImp()
{
} 
ExportImp::~ExportImp()
{
}

TextExportImp::TextExportImp()
{
}
TextExportImp::~TextExportImp()
{
}

void TextExportImp::Operation(vector<string> str)
{
	ofstream out("out.txt");
	for (int i = 0; i < str.size(); i++)
	{
		out << str[i] << endl;
	}
}


DbExportImp::DbExportImp()
{
}
DbExportImp::~DbExportImp()
{
}
void DbExportImp::Operation(vector<string> str)
{
	cout << "目录" << endl;
	for (int a = 0; a < str.size(); a++)
	{
		cout << str[a] << endl;
	}
}

XmlExportImp::XmlExportImp()
{
}

XmlExportImp::~XmlExportImp()
{
}

void XmlExportImp::Operation(vector<string> str)
{
	XMLDocument *doc = new XMLDocument();
	XMLDeclaration *pDel = doc->NewDeclaration("xml version=\"1.0\" encoding=\"UTF-8\"");
	XMLElement* root = doc->NewElement(str[0].c_str());
	doc->InsertEndChild(root);
	
	for (int a = 0; a < str.size(); a++)
	{
		XMLElement *  location = doc->NewElement("地址");
		root->InsertEndChild(location);
		XMLText *text = doc->NewText(str[a].c_str());
		location->InsertEndChild(text);
	}
	doc->SaveFile("XMLFile.xml");
}

ExportImp.h

#ifndef _EXPORTIMP_h_
#define _EXPORTIMP_h_
#include <vector>
#include <string>
using namespace std;
class ExportImp
{
public:
	virtual ~ExportImp();
	virtual void Operation(vector<string> str) = 0;
protected:
	ExportImp();
private:
};
class TextExportImp :public ExportImp
{
public:
	TextExportImp();
	~TextExportImp();
	virtual void Operation(vector<string> str);
protected:
private:
};

class DbExportImp :public ExportImp
{
public:
	DbExportImp();
	~DbExportImp();
	virtual void Operation(vector<string> str);
protected:
private:
};

class XmlExportImp :public ExportImp
{
public:
	XmlExportImp();
	~XmlExportImp();
	virtual void Operation(vector<string> str);
protected:
private:
};
#endif //~_ABSTRACTIONIMP_H_

resource.h

//{
      {NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 桥接模式.rc 使用
//
#define IDR_ACCELERATOR1                101

// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40002
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

tinyxml2.h

/*
Original code by Lee Thomason (www.grinninglizard.com)

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.

Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.

2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.

3. This notice may not be removed or altered from any source
distribution.
*/

#ifndef TINYXML2_INCLUDED
#define TINYXML2_INCLUDED

#if defined(ANDROID_NDK) || defined(__BORLANDC__) || defined(__QNXNTO__)
#   include <ctype.h>
#   include <limits.h>
#   include <stdio.h>
#   include <stdlib.h>
#   include <string.h>
#	if defined(__PS3__)
#		include <stddef.h>
#	endif
#else
#   include <cctype>
#   include <climits>
#   include <cstdio>
#   include <cstdlib>
#   include <cstring>
#endif
#include <stdint.h>

/*
   TODO: intern strings instead of allocation.
*/
/*
	gcc:
        g++ -Wall -DTINYXML2_DEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe

    Formatting, Artistic Style:
        AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h
*/

#if defined( _DEBUG ) || defined (__DEBUG__)
#   ifndef TINYXML2_DEBUG
#       define TINYXML2_DEBUG
#   endif
#endif

#ifdef _MSC_VER
#   pragma warning(push)
#   pragma warning(disable: 4251)
#endif

#ifdef _WIN32
#   ifdef TINYXML2_EXPORT
#       define TINYXML2_LIB __declspec(dllexport)
#   elif defined(TINYXML2_IMPORT)
#       define TINYXML2_LIB __declspec(dllimport)
#   else
#       define TINYXML2_LIB
#   endif
#elif __GNUC__ >= 4
#   define TINYXML2_LIB __attribute__((visibility("default")))
#else
#   define TINYXML2_LIB
#endif


#if defined(TINYXML2_DEBUG)
#   if defined(_MSC_VER)
#       // "(void)0," is for suppressing C4127 warning in "assert(false)", "assert(true)" and the like
#       define TIXMLASSERT( x )           if ( !((void)0,(x))) { __debugbreak(); }
#   elif defined (ANDROID_NDK)
#       include <android/log.h>
#       define TIXMLASSERT( x )           if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); }
#   else
#       include <assert.h>
#       define TIXMLASSERT                assert
#   endif
#else
#   define TIXMLASSERT( x )               {}
#endif


/* Versioning, past 1.0.14:
	http://semver.org/
*/
static const int TIXML2_MAJOR_VERSION = 6;
static const int TIXML2_MINOR_VERSION = 2;
static const int TIXML2_PATCH_VERSION = 0;

#define TINYXML2_MAJOR_VERSION 6
#define TINYXML2_MINOR_VERSION 2
#define TINYXML2_PATCH_VERSION 0

// A fixed element depth limit is problematic. There needs to be a 
// limit to avoid a stack overflow. However, that limit varies per 
// system, and the capacity of the stack. On the other hand, it's a trivial 
// attack that can result from ill, malicious, or even correctly formed XML, 
// so there needs to be a limit in place.
static const int TINYXML2_MAX_ELEMENT_DEPTH = 100;

namespace tinyxml2
{
class XMLDocument;
class XMLElement;
class XMLAttribute;
class XMLComment;
class XMLText;
class XMLDeclaration;
class XMLUnknown;
class XMLPrinter;

/*
	A class that wraps strings. Normally stores the start and end
	pointers into the XML file itself, and will apply normalization
	and entity translation if actually read. Can also store (and memory
	manage) a traditional char[]
*/
class StrPair
{
public:
    enum {
        NEEDS_ENTITY_PROCESSING			= 0x01,
        NEEDS_NEWLINE_NORMALIZATION		= 0x02,
        NEEDS_WHITESPACE_COLLAPSING     = 0x04,

        TEXT_ELEMENT		            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
        TEXT_ELEMENT_LEAVE_ENTITIES		= NEEDS_NEWLINE_NORMALIZATION,
        ATTRIBUTE_NAME		            = 0,
        ATTRIBUTE_VALUE		            = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION,
        ATTRIBUTE_VALUE_LEAVE_ENTITIES  = NEEDS_NEWLINE_NORMALIZATION,
        COMMENT							= NEEDS_NEWLINE_NORMALIZATION
    };

    StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {}
    ~StrPair();

    void Set( char* start, char* end, int flags ) {
        TIXMLASSERT( start );
        TIXMLASSERT( end );
        Reset();
        _start  = start;
        _end    = end;
        _flags  = flags | NEEDS_FLUSH;
    }

    const char* GetStr();

    bool Empty() const {
        return _start == _end;
    }

    void SetInternedStr( const char* str ) {
        Reset();
        _start = const_cast<char*>(str);
    }

    void SetStr( const char* str, int flags=0 );

    char* ParseText( char* in, const char* endTag, int strFlags, int* curLineNumPtr );
    char* ParseName( char* in );

    void TransferTo( StrPair* other );
	void Reset();

private:
    void CollapseWhitespace();

    enum {
        NEEDS_FLUSH = 0x100,
        NEEDS_DELETE = 0x200
    };

    int     _flags;
    char*   _start;
    char*   _end;

    StrPair( const StrPair& other );	// not supported
    void operator=( StrPair& other );	// not supported, use TransferTo()
};


/*
	A dynamic array of Plain Old Data. Doesn't support constructors, etc.
	Has a small initial memory pool, so that low or no usage will not
	cause a call to new/delete
*/
template <class T, int INITIAL_SIZE>
class DynArray
{
public:
    DynArray() :
        _mem( _pool ),
        _allocated( INITIAL_SIZE ),
        _size( 0 )
    {
    }

    ~DynArray() {
        if ( _mem != _pool ) {
            delete [] _mem;
        }
    }

    void Clear() {
        _size = 0;
    }

    void Push( T t ) {
        TIXMLASSERT( _size < INT_MAX );
        EnsureCapacity( _size+1 );
        _mem[_size] = t;
        ++_size;
    }

    T* PushArr( int count ) {
        TIXMLASSERT( count >= 0 );
        TIXMLASSERT( _size <= INT_MAX - count );
        EnsureCapacity( _size+count );
        T* ret = &_mem[_size];
        _size += count;
        return ret;
    }

    T Pop() {
        TIXMLASSERT( _size > 0 );
        --_size;
        return _mem[_size];
    }

    void PopArr( int count ) {
        TIXMLASSERT( _size >= count );
        _size -= count;
    }

    bool Empty() const					{
        return _size == 0;
    }

    T& operator[](int i)				{
        TIXMLASSERT( i>= 0 && i < _size );
        return _mem[i];
    }

    const T& operator[](int i) const	{
        TIXMLASSERT( i>= 0 && i < _size );
        return _mem[i];
    }

    const T& PeekTop() const            {
        TIXMLASSERT( _size > 0 );
        return _mem[ _size - 1];
    }

    int Size() const					{
        TIXMLASSERT( _size >= 0 );
        return _size;
    }

    int Capacity() const				{
        TIXMLASSERT( _allocated >= INITIAL_SIZE );
        return _allocated;
    }

	void SwapRemove(int i) {
		TIXMLASSERT(i >= 0 && i < _size);
		TIXMLASSERT(_size > 0);
		_mem[i] = _mem[_size - 1];
		--_size;
	}

    const T* Mem() const				{
        TIXMLASSERT( _mem );
        return _mem;
    }

    T* Mem()							{
        TIXMLASSERT( _mem );
        return _mem;
    }

private:
    DynArray( const DynArray& ); // not supported
    void operator=( const DynArray& ); // not supported

    void EnsureCapacity( int cap ) {
        TIXMLASSERT( cap > 0 );
        if ( cap > _allocated ) {
            TIXMLASSERT( cap <= INT_MAX / 2 );
            int newAllocated = cap * 2;
            T* newMem = new T[newAllocated];
            TIXMLASSERT( newAllocated >= _size );
            memcpy( newMem, _mem, sizeof(T)*_size );	// warning: not using constructors, only works for PODs
            if ( _mem != _pool ) {
                delete [] _mem;
            }
            _mem = newMem;
            _allocated = newAllocated;
        }
    }

    T*  _mem;
    T   _pool[INITIAL_SIZE];
    int _allocated;		// objects allocated
    int _size;			// number objects in use
};


/*
	Parent virtual class of a pool for fast allocation
	and deallocation of objects.
*/
class MemPool
{
public:
    MemPool() {}
    virtual ~MemPool() {}

    virtual int ItemSize() const = 0;
    virtual void* Alloc() = 0;
    virtual void Free( void* ) = 0;
    virtual void SetTracked() = 0;
    virtual void Clear() = 0;
};


/*
	Template child class to create pools of the correct type.
*/
template< int ITEM_SIZE >
class MemPoolT : public MemPool
{
public:
    MemPoolT() : _blockPtrs(), _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0)	{}
    ~MemPoolT() {
        Clear();
    }
    
    void Clear() {
        // Delete the blocks.
        while( !_blockPtrs.Empty()) {
            Block* lastBlock = _blockPtrs.Pop();
            delete lastBlock;
        }
        _root = 0;
        _currentAllocs = 0;
        _nAllocs = 0;
        _maxAllocs = 0;
        _nUntracked = 0;
    }

    virtual int ItemSize() const	{
        return ITEM_SIZE;
    }
    int CurrentAllocs() const		{
        return _currentAllocs;
    }

    virtual void* Alloc() {
        if ( !_root ) {
            // Need a new block.
            Block* block = new Block();
            _blockPtrs.Push( block );

            Item* blockItems = block->items;
            for( int i = 0; i < ITEMS_PER_BLOCK - 1; ++i ) {
                blockItems[i].next = &(blockItems[i + 1]);
            }
            blockItems[ITEMS_PER_BLOCK - 1].next = 0;
            _root = blockItems;
        }
        Item* const result = _root;
        TIXMLASSERT( result != 0 );
        _root = _root->next;

        ++_currentAllocs;
        if ( _currentAllocs > _maxAllocs ) {
            _maxAllocs = _currentAllocs;
        }
        ++_nAllocs;
        ++_nUntracked;
        return result;
    }
    
    virtual void Free( void* mem ) {
        if ( !mem ) {
            return;
        }
        --_currentAllocs;
        Item* item = static_cast<Item*>( mem );
#ifdef TINYXML2_DEBUG
        memset( item, 0xfe, sizeof( *item ) );
#endif
        item->next = _root;
        _root = item;
    }
    void Trace( const char* name ) {
        printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n",
                name, _maxAllocs, _maxAllocs * ITEM_SIZE / 1024, _currentAllocs,
                ITEM_SIZE, _nAllocs, _blockPtrs.Size() );
    }

    void SetTracked() {
        --_nUntracked;
    }

    int Untracked() const {
        return _nUntracked;
    }

	// This number is perf sensitive. 4k seems like a good tradeoff on my machine.
	// The test file is large, 170k.
	// Release:		VS2010 gcc(no opt)
	//		1k:		4000
	//		2k:		4000
	//		4k:		3900	21000
	//		16k:	5200
	//		32k:	4300
	//		64k:	4000	21000
    // Declared public because some compilers do not accept to use ITEMS_PER_BLOCK
    // in private part if ITEMS_PER_BLOCK is private
    enum { ITEMS_PER_BLOCK = (4 * 1024) / ITEM_SIZE };

private:
    MemPoolT( const MemPoolT& ); // not supported
    void operator=( const MemPoolT& ); // not supported

    union Item {
        Item*   next;
        char    itemData[ITEM_SIZE];
    };
    struct Block {
        Item items[ITEMS_PER_BLOCK];
    };
    DynArray< Block*, 10 > _blockPtrs;
    Item* _root;

    int _currentAllocs;
    int _nAllocs;
    int _maxAllocs;
    int _nUntracked;
};



/**
	Implements the interface to the "Visitor pattern" (see the Accept() method.)
	If you call the Accept() method, it requires being passed a XMLVisitor
	class to handle callbacks. For nodes that contain other nodes (Document, Element)
	you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs
	are simply called with Visit().

	If you return 'true' from a Visit method, recursive parsing will continue. If you return
	false, <b>no children of this node or its siblings</b> will be visited.

	All flavors of Visit methods have a default implementation that returns 'true' (continue
	visiting). You need to only override methods that are interesting to you.

	Generally Accept() is called on the XMLDocument, although all nodes support visiting.

	You should never change the document from a callback.

	@sa XMLNode::Accept()
*/
class TINYXML2_LIB XMLVisitor
{
public:
    virtual ~XMLVisitor() {}

    /// Visit a document.
    virtual bool VisitEnter( const XMLDocument& /*doc*/ )			{
        return true;
    }
    /// Visit a document.
    virtual bool VisitExit( const XMLDocument& /*doc*/ )			{
        return true;
    }

    /// Visit an element.
    virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ )	{
        return true;
    }
    /// Visit an element.
    virtual bool VisitExit( const XMLElement& /*element*/ )			{
        return true;
    }

    /// Visit a declaration.
    virtual bool Visit( const XMLDeclaration& /*declaration*/ )		{
        return true;
    }
    /// Visit a text node.
    virtual bool Visit( const XMLText& /*text*/ )					{
        return true;
    }
    /// Visit a comment node.
    virtual bool Visit( const XMLComment& /*comment*/ )				{
        return true;
    }
    /// Visit an unknown node.
    virtual bool Visit( const XMLUnknown& /*unknown*/ )				{
        return true;
    }
};

// WARNING: must match XMLDocument::_errorNames[]
enum XMLError {
    XML_SUCCESS = 0,
    XML_NO_ATTRIBUTE,
    XML_WRONG_ATTRIBUTE_TYPE,
    XML_ERROR_FILE_NOT_FOUND,
    XML_ERROR_FILE_COULD_NOT_BE_OPENED,
    XML_ERROR_FILE_READ_ERROR,
    UNUSED_XML_ERROR_ELEMENT_MISMATCH,	// remove at next major version
    XML_ERROR_PARSING_ELEMENT,
    XML_ERROR_PARSING_ATTRIBUTE,
    UNUSED_XML_ERROR_IDENTIFYING_TAG,	// remove at next major version
    XML_ERROR_PARSING_TEXT,
    XML_ERROR_PARSING_CDATA,
    XML_ERROR_PARSING_COMMENT,
    XML_ERROR_PARSING_DECLARATION,
    XML_ERROR_PARSING_UNKNOWN,
    XML_ERROR_EMPTY_DOCUMENT,
    XML_ERROR_MISMATCHED_ELEMENT,
    XML_ERROR_PARSING,
    XML_CAN_NOT_CONVERT_TEXT,
    XML_NO_TEXT_NODE,
	XML_ELEMENT_DEPTH_EXCEEDED,

	XML_ERROR_COUNT
};


/*
	Utility functionality.
*/
class TINYXML2_LIB XMLUtil
{
public:
    static const char* SkipWhiteSpace( const char* p, int* curLineNumPtr )	{
        TIXMLASSERT( p );

        while( IsWhiteSpace(*p) ) {
            if (curLineNumPtr && *p == '\n') {
                ++(*curLineNumPtr);
            }
            ++p;
        }
        TIXMLASSERT( p );
        return p;
    }
    static char* SkipWhiteSpace( char* p, int* curLineNumPtr )				{
        return const_cast<char*>( SkipWhiteSpace( const_cast<const char*>(p), curLineNumPtr ) );
    }

    // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't
    // correct, but simple, and usually works.
    static bool IsWhiteSpace( char p )					{
        return !IsUTF8Continuation(p) && isspace( static_cast<unsigned char>(p) );
    }
    
    inline static bool IsNameStartChar( unsigned char ch ) {
        if ( ch >= 128 ) {
            // This is a heuristic guess in attempt to not implement Unicode-aware isalpha()
            return true;
        }
        if ( isalpha( ch ) ) {
            return true;
        }
        return ch == ':' || ch == '_';
    }
    
    inline static bool IsNameChar( unsigned char ch ) {
        return IsNameStartChar( ch )
               || isdigit( ch )
               || ch == '.'
               || ch == '-';
    }

    inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX )  {
        if ( p == q ) {
            return true;
        }
        TIXMLASSERT( p );
        TIXMLASSERT( q );
        TIXMLASSERT( nChar >= 0 );
        return strncmp( p, q, nChar ) == 0;
    }
    
    inline static bool IsUTF8Continuation( char p ) {
        return ( p & 0x80 ) != 0;
    }

    static const char* ReadBOM( const char* p, bool* hasBOM );
    // p is the starting location,
    // the UTF-8 value of the entity will be placed in value, and length filled in.
    static const char* GetCharacterRef( const char* p, char* value, int* length );
    static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length );

    // converts primitive types to strings
    static void ToStr( int v, char* buffer, int bufferSize );
    static void ToStr( unsigned v, char* buffer, int bufferSize );
    static void ToStr( bool v, char* buffer, int bufferSize );
    static void ToStr( float v, char* buffer, int bufferSize );
    static void ToStr( double v, ch
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值