mirror of
https://bitbucket.org/theswgsource/src-1.2.git
synced 2026-07-30 00:15:47 -04:00
Added ChatServer and soePlatform
This commit is contained in:
+360
@@ -0,0 +1,360 @@
|
||||
// ======================================================================
|
||||
//
|
||||
// UnicodeCharDataMap.cpp
|
||||
// copyright (c) 2001 Sony Online Entertainment
|
||||
//
|
||||
// This contains Unicode 3.0 compliant Character data formats
|
||||
// The data is loaded dynamically from the UnicodeData.txt definition file
|
||||
//
|
||||
// ======================================================================
|
||||
|
||||
#include "FirstUnicode.h"
|
||||
#include "UnicodeCharacterDataMap.h"
|
||||
#include "UnicodeBlocks.h"
|
||||
#include "UnicodeCharacterData.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <cassert>
|
||||
|
||||
// ======================================================================
|
||||
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
namespace NAMESPACE
|
||||
{
|
||||
#endif
|
||||
|
||||
namespace Plat_Unicode
|
||||
{
|
||||
|
||||
CharDataMap * CharDataMap::ms_singleton = 0;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
CharDataMap::CharDataMap () :
|
||||
m_blockIds (),
|
||||
m_contiguousData (0),
|
||||
m_map (),
|
||||
m_dataIsValid (false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
CharDataMap::~CharDataMap ()
|
||||
{
|
||||
m_map.clear ();
|
||||
m_blockIds.clear ();
|
||||
|
||||
if (m_contiguousData)
|
||||
{
|
||||
delete[] m_contiguousData;
|
||||
m_contiguousData = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
void CharDataMap::initSingleton ()
|
||||
{
|
||||
explicitDestroy ();
|
||||
|
||||
// TODO: default blocks?
|
||||
ms_singleton = new CharDataMap ();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
void CharDataMap::explicitDestroy ()
|
||||
{
|
||||
if (ms_singleton)
|
||||
delete ms_singleton;
|
||||
|
||||
ms_singleton = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
typedef std::map <std::string, CharData::Category> CategoryMap_t;
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* Load a CharData from a string buffer representing a file.
|
||||
* The bufpos is set to the beginning of a line after this method returns.
|
||||
*/
|
||||
|
||||
|
||||
inline bool populateDataFromBuffer (size_t desiredCode,
|
||||
CharData & charData,
|
||||
const std::string & buffer,
|
||||
size_t & bufpos,
|
||||
const CategoryMap_t & cmap)
|
||||
{
|
||||
|
||||
size_t endpos = 0;
|
||||
|
||||
bool found = false;
|
||||
|
||||
do
|
||||
{
|
||||
size_t tokenNum = 0;
|
||||
|
||||
while ( (endpos = buffer.find ( ';', bufpos)) != std::string::npos ) //lint !e737 // loss of sign in promotion - STL bug
|
||||
{
|
||||
// code value
|
||||
if (tokenNum == 0)
|
||||
{
|
||||
const size_t code = static_cast <size_t> (strtoul (buffer.substr (bufpos, endpos - bufpos).c_str (), 0, 16));
|
||||
|
||||
// we passed the desired line, so it must not exist
|
||||
if (code > desiredCode)
|
||||
return found;
|
||||
// not there yet
|
||||
else if (code < desiredCode)
|
||||
break;
|
||||
|
||||
charData.m_code = static_cast<unicode_char_t> (code);
|
||||
}
|
||||
|
||||
// General Category
|
||||
else if (tokenNum == 2)
|
||||
{
|
||||
// all category codes are currently 2 characters long
|
||||
if (endpos - bufpos > 2)
|
||||
break;
|
||||
|
||||
const CategoryMap_t::const_iterator find_iter = cmap.find (buffer.substr (bufpos, 2));
|
||||
|
||||
if (find_iter == cmap.end ())
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
charData.m_category = (*find_iter).second;
|
||||
}
|
||||
|
||||
// Uppercase mapping
|
||||
else if (charData.isLowerCase ())
|
||||
{
|
||||
if (tokenNum == 12)
|
||||
{
|
||||
if (endpos - bufpos > 1)
|
||||
charData.m_reverseCase = static_cast<unicode_char_t> (strtoul (buffer.substr (bufpos, endpos - bufpos).c_str (), 0, 16));
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Lowercase mapping
|
||||
else if (tokenNum == 13)
|
||||
{
|
||||
if (endpos - bufpos > 1)
|
||||
charData.m_reverseCase = static_cast<unicode_char_t> (strtoul (buffer.substr (bufpos, endpos - bufpos).c_str (), 0, 16));
|
||||
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
||||
bufpos = endpos + 1;
|
||||
++tokenNum;
|
||||
|
||||
}
|
||||
}
|
||||
while ( (bufpos = buffer.find ('\n', bufpos)) != std::string::npos && //lint !e737 // loss of sign in promotion - STL bug
|
||||
(bufpos = buffer.find_first_not_of ('\n', bufpos + 1)) != std::string::npos); //lint !e737 // loss of sign in promotion - STL bug
|
||||
|
||||
return found;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a map of CharData's from a UnicodeData.txt standard Unicode 3.0 file, which has been packed into a buffer
|
||||
*/
|
||||
|
||||
CharDataMap::ErrorCode CharDataMap::generateMapFromBuffer (const Blocks::Mapping & blockMapping, const std::string & str_buf)
|
||||
{
|
||||
m_dataIsValid = false;
|
||||
|
||||
m_map.clear ();
|
||||
|
||||
//-- create the category map for use by the inline population function
|
||||
CategoryMap_t cmap;
|
||||
|
||||
{
|
||||
size_t i = 0;
|
||||
for (; CharData::ms_categoryNames [i].m_category != CharData::Cn; ++i)
|
||||
{
|
||||
cmap [CharData::ms_categoryNames [i].m_str] = CharData::ms_categoryNames [i].m_category;
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::set<unicode_char_t> IdSet_t;
|
||||
|
||||
IdSet_t idSet;
|
||||
|
||||
{
|
||||
for (BlockIdSet_t::const_iterator iter = m_blockIds.begin (); iter != m_blockIds.end (); ++iter)
|
||||
{
|
||||
const Blocks::Data & blockData = blockMapping.findBlock (*iter);
|
||||
|
||||
if (blockData.m_id != Blocks::End_Block_Ids)
|
||||
{
|
||||
blockData.generateFilteredIdSet (idSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-- read all the desired chars from file.
|
||||
//-- the file must be sorted by code
|
||||
|
||||
size_t bufpos = 0;
|
||||
size_t validChars = 0;
|
||||
|
||||
{
|
||||
|
||||
for (IdSet_t::const_iterator iter = idSet.begin (); iter != idSet.end (); ++iter)
|
||||
{
|
||||
CharData * data = new CharData;
|
||||
|
||||
assert (data); //lint !e1924 // c-style cast. MSVC bug
|
||||
|
||||
data->m_reverseCase = 0;
|
||||
|
||||
if (populateDataFromBuffer (*iter, *data, str_buf, bufpos, cmap) == false)
|
||||
{
|
||||
delete data;
|
||||
continue;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
++validChars;
|
||||
m_map[data->m_code] = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--
|
||||
//-- pack all the char data into a contiguous block of memory
|
||||
//--
|
||||
|
||||
if (m_contiguousData)
|
||||
delete[] m_contiguousData;
|
||||
|
||||
m_contiguousData = new CharData [validChars];
|
||||
|
||||
assert (m_contiguousData); //lint !e1924 // c-style cast. MSVC bug
|
||||
|
||||
size_t dataIndex = 0;
|
||||
|
||||
for (Map_t::iterator iter = m_map.begin (); iter != m_map.end (); ++iter, ++dataIndex)
|
||||
{
|
||||
m_contiguousData [dataIndex] = *(*iter).second;
|
||||
delete (*iter).second;
|
||||
(*iter).second = &m_contiguousData [dataIndex];
|
||||
}
|
||||
|
||||
m_dataIsValid = true;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Create a map of CharData's from a UnicodeData.txt standard Unicode 3.0 file, using cstdio
|
||||
*/
|
||||
|
||||
CharDataMap::ErrorCode CharDataMap::generateMap (const Blocks::Mapping & blockMapping, const char * filename)
|
||||
{
|
||||
//-- load data from file as a big std::string
|
||||
//-- read all the desired chars from file.
|
||||
//-- the file must be sorted by code
|
||||
|
||||
FILE * fl = fopen (filename, "rb");
|
||||
|
||||
if (fl == 0)
|
||||
{
|
||||
return ERR_NO_FILE;
|
||||
}
|
||||
|
||||
fseek (fl, 0, SEEK_END);
|
||||
|
||||
size_t fileLen = static_cast<size_t>(ftell (fl));
|
||||
|
||||
fseek (fl, 0, SEEK_SET);
|
||||
|
||||
char * buffer = new char [fileLen + 1];
|
||||
buffer [fileLen] = 0;
|
||||
|
||||
assert (buffer); //lint !e1924 // c-style cast. MSVC bug
|
||||
|
||||
if (fread (buffer, fileLen, 1, fl) != 1)
|
||||
{
|
||||
delete[] buffer;
|
||||
fclose (fl);
|
||||
return ERR_READ_FAILED;
|
||||
}
|
||||
|
||||
if (fclose (fl))
|
||||
{
|
||||
delete[] buffer;
|
||||
return ERR_CLOSE_FAILED;
|
||||
}
|
||||
|
||||
std::string str_buf (buffer, fileLen);
|
||||
|
||||
delete[] buffer;
|
||||
|
||||
return generateMapFromBuffer (blockMapping, str_buf);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Add a block Id that this CharacterDataMap is concerned with. Does not change the data map.
|
||||
*/
|
||||
|
||||
void CharDataMap::addBlock (Blocks::Id id)
|
||||
{
|
||||
m_blockIds.insert (id);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Remove a block Id that this CharacterDataMap is concerned with. Does not change the data map.
|
||||
*/
|
||||
|
||||
void CharDataMap::removeBlock (Blocks::Id id)
|
||||
{
|
||||
m_blockIds.erase (id);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------
|
||||
|
||||
/*
|
||||
* Add a block Id that this CharacterDataMap is concerned with. Does not change the data map.
|
||||
*/
|
||||
|
||||
void CharDataMap::clearBlocks ()
|
||||
{
|
||||
m_blockIds.clear ();
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
|
||||
};
|
||||
#ifdef EXTERNAL_DISTRO
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user