//
// WorldGPS.h
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#if !defined(AFX_WORLDGPS_H__763AAF9D_7289_45A1_9026_4E2BF703C0E8__INCLUDED_)
#define AFX_WORLDGPS_H__763AAF9D_7289_45A1_9026_4E2BF703C0E8__INCLUDED_
#pragma once
class CWorldCountry;
class CWorldCity;
class CXMLElement;
class CWorldGPS
{
// Construction
public:
CWorldGPS();
~CWorldGPS();
// Attributes
public:
CWorldCountry* m_pCountry;
DWORD m_nCountry;
// Operations
public:
BOOL Load(LPCTSTR pszFile = NULL);
void Clear();
protected:
void Serialize(CArchive& ar);
BOOL LoadFrom(CXMLElement* pRoot);
};
class CWorldCountry
{
// Construction
public:
CWorldCountry();
~CWorldCountry();
// Attributes
public:
CHAR m_szID[2];
CString m_sName;
public:
CWorldCity* m_pCity;
DWORD m_nCity;
// Operations
public:
void Serialize(CArchive& ar);
BOOL LoadFrom(CXMLElement* pRoot);
void Clear();
};
class CWorldCity
{
// Attributes
public:
CString m_sName;
CString m_sState;
float m_nLatitude;
float m_nLongitude;
// Operations
public:
void Serialize(CArchive& ar);
BOOL LoadFrom(CXMLElement* pRoot);
};
#endif // !defined(AFX_WORLDGPS_H__763AAF9D_7289_45A1_9026_4E2BF703C0E8__INCLUDED_)
//
// WorldGPS.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "WorldGPS.h"
#include "Buffer.h"
#include "XML.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//
/*
这里是根据文件来构建worldGPS对象,如果文件是xml格式的,则调用LoadForm
进行解析和加载,并写入到worldgps.dat文件中。
如果是dat格式的,则直接调用序列化完成加载。
注意worldGPS中有好多个国家对象,每个国家对象有好多个城市对象,
需要为他们建立各自的loadForm方法从xmlElement中构建各个属性;
*/
// CWorldGPS construction
CWorldGPS::CWorldGPS()
{
m_pCountry = NULL;
m_nCountry = 0;
}
CWorldGPS::~CWorldGPS()
{
Clear();
}
//
// CWorldGPS load
//从文件中读取数据建立WorldGPS对象
BOOL CWorldGPS::Load(LPCTSTR pszFile)
{
CFile pFile;
Clear();
//路径在设置类中的data//worldgps.dat文件中,
CString strFile = Settings.General.Path + _T("//Data//WorldGPS.dat");
//如果参数为NULL,则读取默认文件worldgps.dat
if ( ! pszFile )
{
pszFile = strFile;
}
//打开这个文件pszFile
if ( ! pFile.Open( pszFile, CFile::modeRead ) )
{
return FALSE;
}
//检查是否是xml文件
if ( _tcsstr( pszFile, _T(".xml") ) == NULL )
{
//不是XML文件,则调用Serialize方法完成序列化
CArchive ar( &pFile, CArchive::load );
Serialize( ar );
ar.Close();
pFile.Close();
return TRUE;
}
//是xml文件,则根据文件建立一个CXMLElement对象
//来读取和解析xml文件的各项内容
CBuffer pBuffer;
pBuffer.EnsureBuffer( (DWORD)pFile.GetLength() );
pBuffer.m_nLength = (DWORD)pFile.GetLength();
pFile.Read( pBuffer.m_pBuffer, pBuffer.m_nLength );
pFile.Close();
CXMLElement* pXML =
CXMLElement::FromBytes( pBuffer.m_pBuffer, pBuffer.m_nLength );
if ( NULL == pXML )
{
return FALSE;
}
//从XMLElement对象中构建world的各项内容
BOOL bSuccess = LoadFrom( pXML );
delete pXML;
if ( ! bSuccess )
{
return FALSE;
}
//将从XMLElement中读取到的数据写入到worldgps.dat文件中
if ( ! pFile.Open( strFile,
CFile::modeWrite|CFile::modeCreate ) )
{
return FALSE;
}
CArchive ar( &pFile, CArchive::store );
Serialize( ar );
ar.Close();
pFile.Close();
return TRUE;
}
//只需要保存国家的数目和国家的内容,注意读取的时候需要创建空间
void CWorldGPS::Serialize(CArchive& ar)
{
if ( ar.IsStoring() )
{
ar.WriteCount( m_nCountry );
}
else
{
m_nCountry = ar.ReadCount();
m_pCountry = new CWorldCountry[ m_nCountry ];
}
for ( DWORD nCountry = 0 ; nCountry < m_nCountry ; nCountry++ )
{
m_pCountry[ nCountry ].Serialize( ar );
}
}
//根据xml来设置worldGPS各个属性的值
BOOL CWorldGPS::LoadFrom(CXMLElement* pRoot)
{
//pRoot的名字必须为world
if ( ! pRoot->IsNamed( _T("world") ) )
{
return FALSE;
}
//首先获得国家的总数,然后创建对应数目的数组空间
//然后将xml节点的内容装载进这个数组
for ( POSITION pos = pRoot->GetElementIterator() ; pos ; )
{
CXMLElement* pElement = pRoot->GetNextElement( pos );
if ( pElement->IsNamed( _T("country") ) )
{
m_nCountry++;
}
}
m_pCountry = new CWorldCountry[ m_nCountry ];
m_nCountry = 0;
for ( POSITION pos = pRoot->GetElementIterator() ; pos ; )
{
CXMLElement* pElement = pRoot->GetNextElement( pos );
if ( pElement->IsNamed( _T("country") ) )
{
m_pCountry[ m_nCountry++ ].LoadFrom( pElement );
}
}
return m_nCountry > 0;
}
//
// CWorldGPS clear
//一个世界有很多国检,所以有一个国家数组m_pCountry
void CWorldGPS::Clear()
{
if ( m_pCountry )
{
delete [] m_pCountry;
}
m_pCountry = NULL;
m_nCountry = 0;
}
//
// CWorldCountry construction
CWorldCountry::CWorldCountry()
{
m_pCity = NULL;
m_nCity = 0;
}
CWorldCountry::~CWorldCountry()
{
Clear();
}
//
// CWorldCountry serialize
//注意先写入city的数目,然后写入数据
void CWorldCountry::Serialize(CArchive& ar)
{
if ( ar.IsStoring() )
{
ar << m_szID[0];
ar << m_szID[1];
ar << m_sName;
ar.WriteCount( m_nCity );
}
else
{
ar >> m_szID[0];
ar >> m_szID[1];
ar >> m_sName;
m_nCity = ar.ReadCount();
//读取的时候首先创建空间,然后在调用Serialize实现序列化
m_pCity = new CWorldCity[ m_nCity ];
}
for ( DWORD nCity = 0 ; nCity < m_nCity ; nCity++ )
{
m_pCity[ nCity ].Serialize( ar );
}
}
//根据参数pRoot来设置国家的各个属性的值,注意需要创建city数组
BOOL CWorldCountry::LoadFrom(CXMLElement* pRoot)
{
//种类必须为国家
if ( ! pRoot->IsNamed( _T("country") ) )
{
return FALSE;
}
m_sName = pRoot->GetAttributeValue( _T("name") );
//编码为两个char,会不会不够呢??
CString strID = pRoot->GetAttributeValue( _T("code") );
if ( strID.GetLength() != 2 )
{
return FALSE;
}
m_szID[0] = (CHAR)strID.GetAt( 0 );
m_szID[1] = (CHAR)strID.GetAt( 1 );
//首先算出城市的数目,保存到m_nCity中
for ( POSITION pos = pRoot->GetElementIterator() ; pos ; )
{
CXMLElement* pElement = pRoot->GetNextElement( pos );
if ( pElement->IsNamed( _T("city") ) )
{
m_nCity++;
}
}
//然后创建m_nCity个大小的数组m_pCity,然后根据xml节点来装载之
m_pCity = new CWorldCity[ m_nCity ];
m_nCity = 0;
for ( POSITION pos = pRoot->GetElementIterator() ; pos ; )
{
CXMLElement* pElement = pRoot->GetNextElement( pos );
if ( pElement->IsNamed( _T("city") ) )
{
m_pCity[ m_nCity++ ].LoadFrom( pElement );
}
}
return m_nCity > 0;
}
//
// CWorldCountry clear
//一个国家里面有很多城市,删除城市数组所占内存
void CWorldCountry::Clear()
{
if ( m_pCity )
{
delete [] m_pCity;
}
m_pCity = NULL;
m_nCity = 0;
}
//
// CWorldCity load
//注意保存经度和维度的时候将其转化为signed short来保存
void CWorldCity::Serialize(CArchive& ar)
{
WORD nValue;
if ( ar.IsStoring() )
{
ar << m_sName;
ar << m_sState;
nValue = (WORD)(signed short)( m_nLatitude / 90.0f * 32700.0f );
ar << nValue;
nValue = (WORD)(signed short)( m_nLongitude / 180.0f * 32700.0f );
ar << nValue;
}
else
{
ar >> m_sName;
ar >> m_sState;
ar >> nValue;
m_nLatitude = (float)(signed short)nValue / 32700.0f * 90.0f;
ar >> nValue;
m_nLongitude = (float)(signed short)nValue / 32700.0f * 180.0f;
}
}
//根据参数pRoot来设置城市的各种属性
BOOL CWorldCity::LoadFrom(CXMLElement* pRoot)
{
//pRoot的名字必须是city
if ( ! pRoot->IsNamed( _T("city") ) )
{
return FALSE;
}
//m_sName和m_sState都设置为pRoot的对应属性
m_sName = pRoot->GetAttributeValue( _T("name") );
m_sState = pRoot->GetAttributeValue( _T("state") );
//设置city的经度和维度,就是转换为浮点数,保存到对应变量里面
CString strValue = pRoot->GetAttributeValue( _T("latitude") );
if ( _stscanf( strValue, _T("%f"), &m_nLatitude ) != 1 )
{
return FALSE;
}
strValue = pRoot->GetAttributeValue( _T("longitude") );
if ( _stscanf( strValue, _T("%f"), &m_nLongitude ) != 1 )
{
return FALSE;
}
return TRUE;
}