📄 vxirec_utils.cpp
字号:
static void GetNextToken(const vxistring & grammar,
vxistring::size_type pos,
vxistring::size_type end,
vxistring & token)
{
// Find first real character
while (pos != grammar.length() && VXIrecIsSpace(grammar[pos])) ++pos;
if (pos == grammar.length()) {
token.erase();
return;
}
// Extract wordRaw; we know there is at least one character
while (VXIrecIsSpace(grammar[end - 1])) --end;
token = grammar.substr(pos, end - pos);
}
//
// This conversion function is tied to ScanSoft's semantic interpretation
//
bool VXIrecData::JSGFToSRGS(const vxistring & incoming,
vxistring & result,
const VXIMap* props)
{
// These define the symbols used in the JSGF-lite that defines these grammars
const wchar_t NEXT = L'|';
const wchar_t BEGIN_VAL = L'{';
const wchar_t END_VAL = L'}';
// retrieve language id
vxistring xmllang(L"");
const VXIValue *v = VXIMapGetProperty(props, REC_LANGUAGE);
if( v && VXIValueGetType(v) == VALUE_STRING )
xmllang = VXIStringCStr((const VXIString*)v);
// Unable to detect language id
if( xmllang.empty() ) return false;
// retrieve dtmf id
bool isDTMF = false;
v = VXIMapGetProperty(props, REC_INPUT_MODES);
if( v && VXIValueGetType(v) == VALUE_INTEGER)
{
isDTMF = (VXIIntegerValue((const VXIInteger*)v) == REC_INPUT_MODE_DTMF);
}
// create ROOT id, potential bug anyone care???
VXItrdMutexLock(gblMutex);
VXIulong cnt = GRAM_ROOT_COUNTER++;
VXItrdMutexUnlock(gblMutex);
std::basic_stringstream<VXIchar> ROOT_ID;
ROOT_ID << GRAM_ROOT_PREFIX << cnt;
result = L"<?xml version='1.0'?>"
L"<grammar xmlns='http://www.w3.org/2001/06/grammar' "
L"version='1.0' root='";
result += ROOT_ID.str();
result += L"' tag-format='swi-semantics/1.0' xml:lang='";
result += xmllang;
result += L"'";
if (isDTMF)
result += L" mode='dtmf'";
result += L">\n"
L"<meta name=\"swirec_simple_result_key\" content=\"MEANING\"/>"
L"<rule id='";
result += ROOT_ID.str();
result += L"' scope='public'>\n"
L"<one-of>\n";
// These define the units from which we'll build new rules.
const vxistring RULE_BEGIN = L"<item>";
const vxistring RULE_MIDDLE = L"<tag>MEANING=\"";
const vxistring RULE_END = L"\";</tag></item>\n";
// TODO: Must escape values in tags???
// These are positions within the string that we're parsing.
vxistring::size_type pos = 0;
vxistring::size_type next;
vxistring::size_type valmark;
vxistring wordRaw;
vxistring wordValue;
while (pos < incoming.length()) {
// Find the next item
next = incoming.find(NEXT, pos);
if (next == vxistring::npos) next = incoming.length();
// Find the start of the value
valmark = incoming.find(BEGIN_VAL, pos);
if (valmark == vxistring::npos || valmark > next) valmark = next;
// Extract left hand side (raw text)
GetNextToken(incoming, pos, valmark, wordRaw);
if (wordRaw.empty()) {
pos = next + 1;
continue;
}
pos = valmark + 1;
// Extract right hand side (value)
if (valmark != next && pos < incoming.length()) {
valmark = incoming.find(END_VAL, pos);
if (valmark == vxistring::npos || valmark > next) {
LogError(280, L"%s%s", L"Error", L"Mismatched { } pair");
return false;
}
GetNextToken(incoming, pos, valmark, wordValue);
if (wordValue.empty()) {
return false;
}
pos = next + 1;
}
else
wordValue.erase();
// Add word to grammar
FixEscapeChar(wordRaw);
if (!wordValue.empty()) {
// Got tag value
FixEscapeChar(wordValue);
result += RULE_BEGIN + wordRaw + RULE_MIDDLE + wordValue + RULE_END;
} else {
// Didn't get tag value
result += RULE_BEGIN + wordRaw + RULE_MIDDLE + wordRaw + RULE_END;
}
}
// add end tag
result += L"</one-of></rule></grammar>";
return true;
}
bool VXIrecData::OptionToSRGS(const VXIMap * props,
const VXIVector * choices,
const VXIVector * values,
const VXIVector * acceptances,
const VXIbool isDTMF,
vxistring & srgs)
{
static const VXIchar* fnname = L"OptionToSRGS";
srgs = L"";
// (1) Validate vectors.
if (choices == NULL || values == NULL || acceptances == NULL) {
LogError(281, L"%s%s", L"A Vector", L"NULL");
return false;
}
unsigned int len = VXIVectorLength(choices);
if (len != VXIVectorLength(values)) {
LogError(281, L"%s%s", L"Vectors", L"Mismatched vector lengths");
return false;
}
for (unsigned int j = 0; j < len; ++j) {
const VXIValue * c = VXIVectorGetElement(choices, j);
const VXIValue * v = VXIVectorGetElement(values, j);
const VXIValue * a = VXIVectorGetElement(acceptances, j);
if (c == NULL || v == NULL || VXIValueGetType(c) != VALUE_STRING ||
VXIValueGetType(v) != VALUE_STRING)
{
LogError(281, L"%s%s", L"Options", L"Contents not all strings");
return false;
}
LogDiag(4, fnname, L"%s%s%s%s%s%d",
L"choice: ", VXIStringCStr(reinterpret_cast<const VXIString *>(c)),
L", value: ", VXIStringCStr(reinterpret_cast<const VXIString *>(v)),
L", accept: ", VXIIntegerValue(reinterpret_cast<const VXIInteger *>(a)) );
}
// (2) extracting weight (does not meaning anything for simulator ???)
VXIulong weight = 1;
const VXIValue* val = VXIMapGetProperty(props, REC_GRAMMAR_WEIGHT);
if( val && VXIValueGetType(val) == VALUE_FLOAT )
weight *= (VXIulong)VXIFloatValue((const VXIFloat*)val);
// (3) retrieve language id
vxistring xmllang(L"");
const VXIValue *v = VXIMapGetProperty(props, REC_LANGUAGE);
if( v && VXIValueGetType(v) == VALUE_STRING )
xmllang = VXIStringCStr((const VXIString*)v);
// Unable to detect language id
if( xmllang.empty() ) return false;
// (4) create ROOT id, wrap-round potential bug, anyone care???
VXItrdMutexLock(gblMutex);
VXIulong cnt = GRAM_ROOT_COUNTER++;
VXItrdMutexUnlock(gblMutex);
std::basic_stringstream<VXIchar> ROOT_ID;
ROOT_ID << GRAM_ROOT_PREFIX << cnt;
// (4) construct srgs -- NOTES: this construction is tied to SSFT's semantic
srgs = L"<?xml version='1.0'?><grammar "
L"xmlns='http://www.w3.org/2001/06/grammar' "
L"version='1.0' root='";
srgs += ROOT_ID.str();
srgs += L"' tag-format='swi-semantics/1.0' xml:lang='";
srgs += xmllang;
srgs += L"'";
if (isDTMF) srgs += L" mode='dtmf'";
srgs += L"><meta name='swirec_simple_result_key' content='MEANING'/>"
L"<rule id='";
srgs += ROOT_ID.str();
srgs += L"' scope='public'><one-of>";
// (5) Add item for each <option>.
// These define the units from which we'll build new rules.
const vxistring RULE_BEGIN = L"<item>";
const vxistring RULE_MIDDLE = L"<tag>MEANING='";
const vxistring RULE_END = L"';</tag></item>";
for (unsigned int i = 0; i < len; ++i) {
const VXIValue * c = VXIVectorGetElement(choices, i);
const VXIValue * v = VXIVectorGetElement(values, i);
const VXIValue * a = VXIVectorGetElement(acceptances, i);
vxistring aitem( VXIStringCStr(reinterpret_cast<const VXIString *>(c)));
vxistring avalue(VXIStringCStr(reinterpret_cast<const VXIString *>(v)));
// normalize text
FixEscapeChar(aitem);
if( !isDTMF && VXIIntegerValue(reinterpret_cast<const VXIInteger *>(a)) > 0 )
{
// If Recongizer does not support approximate recognition we need to
// split the string into single item based on single space
bool done = false;
vxistring tmpStr(aitem);
vxistring::size_type idx;
VXIchar aWord[1024];
const VXIchar *ptr = tmpStr.c_str();
// search for the 1st white space
// TODO: should take care about tab, multiple spaces!!!
idx = tmpStr.find(L" ", 0);
do
{
// create single item separated by space
if( idx == vxistring::npos )
{
idx = tmpStr.length();
done = true;
}
// create separate <item> for each word
wcsncpy(aWord, ptr, idx);
aWord[idx] = L'\0';
srgs += RULE_BEGIN;
srgs += aWord;
srgs += RULE_MIDDLE;
srgs += avalue;
srgs += RULE_END;
// search for the next word
if( !done )
{
ptr += (idx+1);
tmpStr = ptr;
idx = tmpStr.find(L" ", idx + 1);
}
} while( !done );
} else {
srgs += RULE_BEGIN;
srgs += aitem;
srgs += RULE_MIDDLE;
srgs += avalue;
srgs += RULE_END;
}
}
// (6) Finish everything and add grammar.
srgs += L"</one-of></rule></grammar>";
LogDiag(DIAG_TAG_RECOGNITION, fnname, L"%s%s", L"OPTION GRAMMAR: ", srgs.c_str());
return true;
}
VXIlogResult VXIrecData::LogError(VXIunsigned errorID,
const VXIchar *format, ...) const
{
VXIlogResult rc;
va_list args;
if (!log)
return VXIlog_RESULT_NON_FATAL_ERROR;
if (format) {
va_start(args, format);
rc = (*log->VError)(log, COMPANY_DOMAIN L".VXIrec", errorID, format, args);
va_end(args);
} else {
rc = (*log->Error)(log, COMPANY_DOMAIN L".VXIrec", errorID, NULL);
}
return rc;
}
VXIlogResult VXIrecData::LogDiag(VXIunsigned tag, const VXIchar *subtag,
const VXIchar *format, ...) const
{
VXIlogResult rc;
va_list args;
if (!log)
return VXIlog_RESULT_NON_FATAL_ERROR;
if (format) {
va_start(args, format);
rc = (*log->VDiagnostic)(log, tag + diagLogBase, subtag, format, args);
va_end(args);
} else {
rc = (*log->Diagnostic)(log, tag + diagLogBase, subtag, NULL);
}
return rc;
}
bool VXIrecData::FetchContent(
const VXIchar * name,
const VXIMap * properties,
VXIbyte ** result,
VXIulong & read )
{
*result = NULL;
read = 0;
VXIinetStream *stream;
VXIMapHolder streamInfo;
if (inet->Open(inet,
L"Rec",
name,
INET_MODE_READ,
0,
properties,
streamInfo.GetValue(),
&stream ) != VXIinet_RESULT_SUCCESS ) return false;
const VXIValue * tempSize = NULL;
tempSize = VXIMapGetProperty(streamInfo.GetValue(), INET_INFO_SIZE_BYTES);
if (tempSize == NULL || VXIValueGetType(tempSize) != VALUE_INTEGER) {
inet->Close(inet, &stream);
return false;
}
VXIint32 bufSize
= VXIIntegerValue(reinterpret_cast<const VXIInteger *>(tempSize));
if (bufSize < 2047)
bufSize = 2047;
++bufSize;
VXIbyte * buffer = new VXIbyte[bufSize];
if(buffer == NULL){
inet->Close(inet, &stream);
return false;
}
bool reachedEnd = false;
while (!reachedEnd) {
VXIulong bytesRead = 0;
switch (inet->Read(inet, buffer+read, bufSize-read, &bytesRead, stream)) {
case VXIinet_RESULT_SUCCESS:
read += bytesRead;
break;
case VXIinet_RESULT_END_OF_STREAM:
read += bytesRead;
reachedEnd = true; // exit while
break;
case VXIinet_RESULT_WOULD_BLOCK:
VXItrdThreadYield();
break;
default:
inet->Close(inet, &stream);
delete[] buffer;
return false;
}
if (read == static_cast<VXIulong>(bufSize)) {
// The number of bytes read exceeds the number expected. Double the
// size and keep reading.
VXIbyte * temp = new VXIbyte[2*bufSize];
if(temp == NULL) {
delete [] buffer;
return false;
}
memcpy(static_cast<void *>(temp), static_cast<void *>(buffer),
bufSize * sizeof(VXIbyte));
delete[] buffer;
buffer = temp;
bufSize *= 2;
}
}
inet->Close(inet, &stream);
*result = buffer;
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -