📄 vxi.cpp
字号:
/****************License************************************************ * * Copyright 2000-2001. SpeechWorks International, Inc. * * Use of this software is subject to notices and obligations set forth * in the SpeechWorks Public License - Software Version 1.1 which is * included with this software. * * SpeechWorks is a registered trademark, and SpeechWorks Here, * DialogModules and the SpeechWorks logo are trademarks of SpeechWorks * International, Inc. in the United States and other countries. * ***********************************************************************/#include "VXI.hpp"#include "DocumentParser.hpp"#include "SimpleLogger.hpp"#include "Scripter.hpp" // for use in ExecutionContext#include "GrammarManager.hpp" // for use in ExecutionContext#include "Counters.hpp" // for EventCounter#include "PropertyList.hpp" // for PropertyList#include "PromptManager.hpp" // for PromptManager#include "VXML.h" // for node & attribute names#include "VXItel.h" // for VXItelInterface#include "VXIrec.h" // for parameters from rec answer#include "VXIlog.h" // for event IDs#include "VXIobject.h" // for Object type#include <deque> // for deque (used by Prompts)#include <sstream> // by ProcessNameList()#include <algorithm> // for sort, set_intersection, etc.// TBD #pragma message ("Cleanup comments - Did FIA level functions")static const wchar_t * const SCOPE_Session = L"session";static const wchar_t * const SCOPE_Application = L"application";static const wchar_t * const SCOPE_Defaults = L"$_platDefaults_";static const wchar_t * const SCOPE_Document = L"document";static const wchar_t * const SCOPE_Dialog = L"dialog";static const wchar_t * const SCOPE_Local = L"local";static const wchar_t * const SCOPE_Anonymous = L"$_execAnonymous_";static const wchar_t * const GENERIC_DEFAULTS = L"*";// TBD #pragma message ("VXI:: Select better values for these.")const int MAX_LOOP_ITERATIONS = 10;const int MAX_DOCUMENTS = 500;const int MAX_EXE_STACK_DEPTH = 5;// ------*---------*---------*---------*---------*---------*---------*---------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;}// ------*---------*---------*---------*---------*---------*---------*---------class AnswerInformation {public: RecognitionAnswer recAnswer; bool usedDTMF; VXMLElement element; VXMLElement dialog; AnswerInformation(RecognitionAnswer & a, bool u, VXMLElement & e, VXMLElement & d) : recAnswer(a), usedDTMF(u), element(e), dialog(d) { }};class JumpReturn {public: JumpReturn() { }};class JumpItem {public: VXMLElement item; JumpItem(const VXMLElement & i) : item(i) { }};class JumpDialog {public: VXMLElement dialog; JumpDialog(const VXMLElement d) : dialog(d) { }};class JumpDoc {public: VXMLElement defaults; VXMLDocument application; vxistring applicationURI; VXMLDocument document; VXMLElement documentDialog; bool isSubdialog; PropertyList properties; JumpDoc(const VXMLElement & def, const VXMLDocument & app, const vxistring & uri, const VXMLDocument & doc, const VXMLElement & docdial, bool issub, const PropertyList & p) : defaults(def), application(app), applicationURI(uri), document(doc), documentDialog(docdial), isSubdialog(issub), properties(p) { } ~JumpDoc() { }};//#############################################################################// ExecutionContext & Utilities//#############################################################################static std::basic_ostream<VXIchar>& operator<<(std::basic_ostream<VXIchar>& os, const VXIValue * val){ if (val == NULL) return os << L"NULL"; switch (VXIValueGetType(val)) { case VALUE_INTEGER: return os << VXIIntegerValue(reinterpret_cast<const VXIInteger*>(val)); case VALUE_FLOAT: return os << VXIFloatValue(reinterpret_cast<const VXIFloat*>(val)); case VALUE_STRING: return os << VXIStringCStr(reinterpret_cast<const VXIString *>(val)); case VALUE_VECTOR: { const VXIVector * v = reinterpret_cast<const VXIVector *>(val); const VXIunsigned len = VXIVectorLength(v); os << L"{ "; for (VXIunsigned i = 0; i < len; ++i) { if (i != 0) os << L", "; os << VXIVectorGetElement(v, i); } return os << L" }"; } case VALUE_MAP: { const VXIMap * m = reinterpret_cast<const VXIMap *>(val); const VXIchar * key; const VXIValue * value; os << L"{ "; if (VXIMapNumProperties(m) != 0) { VXIMapIterator * i = VXIMapGetFirstProperty(m, &key, &value); os << L"(" << key << L", " << value << L")"; while (VXIMapGetNextProperty(i, &key, &value) == VXIvalue_RESULT_SUCCESS) os << L", (" << key << L", " << value << L")"; VXIMapIteratorDestroy(&i); } return os << L" }"; } default: break; } return os << L"(unprintable result)";}class ExecutionContext {public: // These are used by the main run loops, event handling, and subdialog. // Each of these gets initialized by InstallDocument. VXMLElement platDefaults; VXMLDocument application; vxistring applicationURI; VXMLDocument document; vxistring documentName; VXMLElement currentDialog; // Limited purpose members. VXMLElement eventSource; // For prompting (enumerate) during events VXMLElement lastItem; // Set by <subdialog>public: // These are used more generally. Scripter script; GrammarManager gm; PromptTracker promptcounts; EventCounter eventcounts; PropertyList properties; typedef std::deque<vxistring> STRINGDEQUE; STRINGDEQUE formitems; bool playingPrompts; ExecutionContext * next; ExecutionContext(VXIrecInterface * r, VXIjsiInterface * j, const SimpleLogger & l, ExecutionContext * n) : script(j), gm(r, l), next(n), playingPrompts(true), properties(l) { } // may throw VXIException::OutOfMemory() ~ExecutionContext() { }};typedef std::deque<vxistring> STRINGDEQUE;static void ProcessNameList(const vxistring & namelist, STRINGDEQUE & names){ names.clear(); if (namelist.empty()) return; // The namelist is a series of whitespace delimited strings. Read each in // and insert it into the deque. std::basic_stringstream<VXIchar> namestream(namelist);#if defined(__GNUC__) && __GNUC__ == 2 && __GNUC_MINOR__ <= 95 // G++ 2.95 does not support istream_iterator. while (namestream.good()) { vxistring temp; namestream >> temp; if (!temp.empty()) names.push_back(temp); }#else std::copy(std::istream_iterator<vxistring, VXIchar>(namestream), std::istream_iterator<vxistring, VXIchar>(), std::back_inserter(names));#endif // Now sort the deque and return the unique set of names. if (names.empty()) return; std::sort(names.begin(), names.end()); STRINGDEQUE::iterator i = std::unique(names.begin(), names.end()); if (i != names.end()) names.erase(i, names.end());}//#############################################################################// Creation and Run//#############################################################################VXI::VXI() : parser(NULL), log(NULL), inet(NULL), rec(NULL), jsi(NULL), tel(NULL), exe(NULL), stackDepth(0), sdParams(NULL), sdResult(NULL){ try { parser = new DocumentParser(); } catch (const VXIException::OutOfMemory &) { parser = NULL; throw; } try { pm = new PromptManager(); } catch (...) { delete parser; parser = NULL; pm = NULL; throw; } if (pm == NULL) { delete parser; parser = NULL; throw VXIException::OutOfMemory(); }}VXI::~VXI(){ while (exe != NULL) { ExecutionContext * temp = exe->next; delete exe; exe = temp; } delete pm; delete parser;}bool VXI::SetRuntimeProperty(PropertyID id, const VXIchar * value){ mutex.Lock(); switch (id) { case VXI::BeepURI: if (value == NULL) uriBeep.erase(); else uriBeep = value; break; case VXI::PlatDefaultsURI: if (value == NULL) uriPlatDefaults.erase(); else uriPlatDefaults = value; break; default: mutex.Unlock(); return false; } mutex.Unlock(); return true;}void VXI::GetRuntimeProperty(PropertyID id, vxistring & value) const{ mutex.Lock(); switch (id) { case VXI::BeepURI: value = uriBeep; break; case VXI::PlatDefaultsURI: value = uriPlatDefaults; break; default: value.erase(); } mutex.Unlock();}int VXI::Run(const VXIchar * initialDocument, const VXIMap * args, SimpleLogger * resourceLog, VXIinetInterface * resourceInet, VXIjsiInterface * resourceJsi, VXIrecInterface * resourceRec, VXIpromptInterface * resourcePrompt, VXItelInterface * resourceTel, VXIobjectInterface * resourceObject, VXIValue ** resultValue){ // (1) Check arguments. // (1.1) Check external resources if (resourceLog == NULL || resourceInet == NULL || resourceJsi == NULL || resourceRec == NULL || resourcePrompt == NULL || resourceTel == NULL) return 1; log = resourceLog; inet = resourceInet; jsi = resourceJsi; rec = resourceRec; tel = resourceTel; object = resourceObject; if (!pm->ConnectResources(log, resourcePrompt)) return 1; if (log->IsLogging(2)) { log->StartDiagnostic(2) << L"VXI::Run(" << initialDocument << L")"; log->EndDiagnostic(); } // (1.2) Check document if (initialDocument == NULL || wcslen(initialDocument) == 0) { log->LogError(201); return 1; } // (2) Delegate real work to RunOuterLoop & handle the serious errors. int exitCode; try { exitCode = RunOuterLoop(initialDocument, args, resultValue); pm->PlayAll(); } catch (VXIException::InterpreterEvent & e) { log->LogError(207, SimpleLogger::EXCEPTION, e.GetValue().c_str()); exitCode = 0; } catch (const VXIException::Exit &) { exitCode = 0; } catch (const VXIException::Fatal &) { log->LogError(209); exitCode = -2; } catch (const VXIException::OutOfMemory &) { PopExecutionContext(); log->LogError(202); exitCode = 1; } catch (const VXIException::JavaScriptError &) { log->LogError(212); exitCode = -2; } catch (const JumpDialog &) { log->LogError(999, SimpleLogger::MESSAGE, L"unexpected jump to a dialog"); exitCode = -2; } catch (const JumpDoc &) { log->LogError(999, SimpleLogger::MESSAGE,L"unexpected jump to a document"); exitCode = -2; } catch (const JumpItem &) { log->LogError(999, SimpleLogger::MESSAGE, L"unexpected jump to an item"); exitCode = -2; } catch (const JumpReturn &) { log->LogError(999, SimpleLogger::MESSAGE, L"unexpected jump from a return element"); exitCode = -2; } try { while (exe != NULL) PopExecutionContext(); } catch (const VXIException::JavaScriptError &) { log->LogError(212); return -2; } return exitCode;}int VXI::RunOuterLoop(const vxistring & initialDocument, const VXIMap * args, VXIValue ** resultValue){ // (1) Load the document containing the default handlers. log->LogDiagnostic(2, L"VXI::RunOuterLoop - loading defaultDoc."); // (1.1) Get URI if possible.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -