📄 propertylist.cpp
字号:
/****************License************************************************
*
* Copyright 2000-2003. ScanSoft, Inc.
*
* Use of this software is subject to notices and obligations set forth
* in the SpeechWorks Public License - Software Version 1.2 which is
* included with this software.
*
* ScanSoft is a registered trademark of ScanSoft, Inc., and OpenSpeech,
* SpeechWorks and the SpeechWorks logo are registered trademarks or
* trademarks of SpeechWorks International, Inc. in the United States
* and other countries.
*
***********************************************************************/
#include <vxibuildopts.h>
#if P_VXI
#include "PropertyList.hpp"
#include "CommonExceptions.hpp" // for VXIException class
#include "vxi/VXIinet.h"
#include "VXML.h"
#include "SimpleLogger.hpp" // for SimpleLogger
#include "DocumentParser.hpp" // for string constants
#include "DocumentModel.hpp"
#include <sstream>
// ------*---------*---------*---------*---------*---------*---------*---------
// The use of spaces here creates identifiers which cannot be specified
// within the property or meta tags.
const VXIchar * const PropertyList::BaseURI = L" base";
const VXIchar * const PropertyList::Language = L" lang";
const VXIchar * const PropertyList::AbsoluteURI = L" absoluteURI";
static vxistring toString(const VXIString * s)
{
if (s == NULL) return L"";
const VXIchar * temp = VXIStringCStr(s);
if (temp == NULL) return L"";
return temp;
}
static vxistring toString(const VXIchar * s)
{
if (s == NULL) return L"";
return s;
}
// ------*---------*---------*---------*---------*---------*---------*---------
PropertyList::PropertyList(const SimpleLogger & l) : log(l)
{
properties.reserve(LAST_PROP);
while (properties.size() < LAST_PROP)
properties.push_back(STRINGMAP());
}
PropertyList::PropertyList(const PropertyList & p) : log(p.log)
{
properties = p.properties;
}
PropertyList& PropertyList::operator=(const PropertyList & x)
{
if (this != &x) {
properties = x.properties;
}
return *this;
}
const VXIchar* PropertyList::GetProperty(const VXIchar * key,
PropertyLevel L) const
{
int pos = L;
do {
if (pos == LAST_PROP) --pos;
STRINGMAP::const_iterator i = properties[pos].find(key);
if (i != properties[pos].end()) return (*i).second.c_str();
} while (--pos >= 0);
return NULL;
}
bool PropertyList::SetProperty(const VXIchar * key, const VXIchar * value,
PropertyLevel level)
{
if (level == LAST_PROP || key == NULL || value == NULL) return false;
STRINGMAP & propmap = properties[level];
propmap[key] = value;
return true;
}
void PropertyList::SetProperties(const VXMLElement & doc, PropertyLevel level,
const VXIMapHolder & docProps)
{
// (0) Check the arguments
if (doc == 0) return;
if (properties.size() != LAST_PROP) {
log.LogError(999, SimpleLogger::MESSAGE,
L"internal property list corrupted");
throw VXIException::Fatal();
}
// (1) Clear all properties at this level and above.
#if 0
for (unsigned int i = level; i < LAST_PROP; ++i)
properties[i].clear();
#endif
properties[level].clear();
STRINGMAP & propmap = properties[level];
// (2) Add document properties.
if (docProps.GetValue() != NULL) {
const VXIValue * val;
const VXIString * str;
// (2.1) Handle document base URI.
val = VXIMapGetProperty(docProps.GetValue(), PropertyList::BaseURI);
str = reinterpret_cast<const VXIString *>(val);
if (VXIStringLength(str) != 0)
propmap.insert(propmap.end(),
STRINGMAP::value_type(PropertyList::BaseURI,
toString(str)));
// (2.2) Handle document language. If the document property is not
// specified, the value of the xml:lang property will be used.
val = VXIMapGetProperty(docProps.GetValue(), PropertyList::Language);
str = reinterpret_cast<const VXIString *>(val);
if (VXIStringLength(str) != 0)
propmap.insert(propmap.end(),
STRINGMAP::value_type(PropertyList::Language,
toString(str)));
else {
const VXIchar * lang = GetProperty(L"xml:lang");
if (lang != NULL)
propmap.insert(propmap.end(),
STRINGMAP::value_type(PropertyList::Language,
toString(lang)));
}
// (2.3) Handle document absolute URI.
val = VXIMapGetProperty(docProps.GetValue(), PropertyList::AbsoluteURI);
str = reinterpret_cast<const VXIString *>(val);
if (VXIStringLength(str) != 0)
propmap.insert(propmap.end(),
STRINGMAP::value_type(PropertyList::AbsoluteURI,
toString(str)));
}
// (3) Walk through this level. Find all <property> nodes and set the
// corresponding values.
for (VXMLNodeIterator it(doc); it; ++it) {
VXMLNode child = *it;
if (child.GetType() != VXMLNode::Type_VXMLElement) continue;
const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child);
VXMLElementType nodeName = elem.GetName();
if (nodeName == NODE_PROPERTY) {
vxistring name;
vxistring value;
elem.GetAttribute(ATTRIBUTE_NAME, name);
elem.GetAttribute(ATTRIBUTE_VALUE, value);
// This added the name / value pair, converting to vxistrings.
propmap.insert(propmap.end(), STRINGMAP::value_type(name, value));
}
}
}
//****************************************************************
//* Fetchobj building routines
//****************************************************************
bool PropertyList::ConvertTimeToMilliseconds(const SimpleLogger & log,
const vxistring & time,
VXIint & result)
{
result = 0;
if (time.empty()) {
log.LogDiagnostic(0, L"PropertyList::ConvertTimeToMilliseconds - empty");
return false;
}
for (unsigned int i = 0; i < time.length(); ++i) {
char c;
switch (time[i]) {
case L'+': continue;
case L'0': c = 0; break;
case L'1': c = 1; break;
case L'2': c = 2; break;
case L'3': c = 3; break;
case L'4': c = 4; break;
case L'5': c = 5; break;
case L'6': c = 6; break;
case L'7': c = 7; break;
case L'8': c = 8; break;
case L'9': c = 9; break;
default:
const vxistring units = time.substr(i, time.length() - i);
if (units == L"ms")
return true;
if (units == L"s") {
result *= 1000;
return true;
}
// Otherwise the unit type is not recognized.
log.StartDiagnostic(0) << L"PropertyList::ConvertTimeToMilliseconds - "
L"Invalid units in value \"" << time << L"\".";
log.EndDiagnostic();
return false;
}
result = 10*result + c;
}
// No units were specified. Milliseconds are assumed.
return true;
}
bool PropertyList::ConvertValueToFraction(const SimpleLogger & log,
const vxistring & value,
VXIflt32& result)
{
#if defined(__GNUC__)
// The G++ 2.95/3.0 implementation of basic_stringstream is faulty.
VXIchar * temp;
result = VXIflt32(wcstod(value.c_str(), &temp));
if (*temp) {
result = -1.0;
return false;
}
#else
std::basic_stringstream<VXIchar> attrStream(value);
attrStream >> result;
if (attrStream.bad()) {
result = -1.0;
return false;
}
#endif
return true;
}
void PropertyList::GetFetchobjCacheAttrs(const VXMLElement & elem,
PropertyList::CacheAttrType type,
VXIMapHolder & fetchobj) const
{
vxistring attr;
const VXIchar * propName;
// (1) Attribute: maxage
// (1.1) Get the attribute - first locally, then from the defaults.
elem.GetAttribute(ATTRIBUTE_MAXAGE, attr);
if (attr.empty()) {
switch (type) {
case PropertyList::Audio: propName = L"audiomaxage"; break;
case PropertyList::Document: propName = L"documentmaxage"; break;
case PropertyList::Grammar: propName = L"grammarmaxage"; break;
case PropertyList::Object: propName = L"objectmaxage"; break;
case PropertyList::Script: propName = L"scriptmaxage"; break;
}
attr = toString(GetProperty(propName));
}
// (1.2) Process the value.
if (!attr.empty()) {
VXIint value = -1;
#if defined(__GNUC__)
// The G++ 2.95/3.0 implementation of basic_stringstream is faulty.
VXIchar * temp;
value = VXIint(wcstol(attr.c_str(), &temp, 10));
if (*temp) value = -1;
#else
std::basic_stringstream<VXIchar> attrStream(attr);
attrStream >> value;
if (attrStream.bad()) value = -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -