// Find COpcBrowseElement* COpcBrowseElement::Find(const COpcString& cPath) { // remove leading separator - if it exists. COpcString cPrefix = GetSeparator(); COpcString cLocalPath = cPath; while (cLocalPath.Find(GetSeparator()) == 0) { cLocalPath = cLocalPath.SubStr(cPrefix.GetLength()); } // recursively search children. OPC_POS pos = m_cChildren.GetHeadPosition(); while (pos != NULL) { COpcBrowseElement* pChild = m_cChildren.GetNext(pos); // check for a child with an exact name match. if (cLocalPath == pChild->m_cName) { return pChild; } // check if the path starts with the child name. COpcString cPrefix = pChild->m_cName + pChild->GetSeparator(); // check for a child with an exact name match plus trailing separator. if (cLocalPath == cPrefix) { return pChild; } UINT uIndex = cLocalPath.Find(cPrefix); // search the child node if there is a match. if (uIndex == 0) { cLocalPath = cLocalPath.SubStr(cPrefix.GetLength()); return pChild->Find(cLocalPath); } } return NULL; }
// ToTime static bool ToTime( const COpcString& cString, WORD& wHour, WORD& wMinute, WORD& wSeconds, WORD& wFraction ) { bool bResult = true; TRY { COpcText cText; COpcTextReader cReader(cString); ULong uValue = 0; // parse hour field. cText.SetType(COpcText::Delimited); cText.SetDelims(L":"); if (!cReader.GetNext(cText)) THROW_(bResult, false); if (!ToUnsigned(cText, uValue, MAX_HOUR, MIN_HOUR, 10)) THROW_(bResult, false); wHour = (WORD)uValue; // parse month field. cText.SetType(COpcText::Delimited); cText.SetDelims(L":"); if (!cReader.GetNext(cText)) THROW_(bResult, false); if (!ToUnsigned(cText, uValue, MAX_MINUTE, MIN_MINUTE, 10)) THROW_(bResult, false); wMinute = (WORD)uValue; // parse seconds field. cText.SetType(COpcText::Delimited); cText.SetDelims(L"."); cText.SetEofDelim(); if (!cReader.GetNext(cText)) THROW_(bResult, false); if (!ToUnsigned(cText, uValue, MAX_SECOND, MIN_SECOND, 10)) THROW_(bResult, false); wSeconds = (WORD)uValue; // parse seconds fraction field. wFraction = 0; if (cText.GetDelimChar() == L'.') { cText.SetType(COpcText::Delimited); cText.SetEofDelim(); if (!cReader.GetNext(cText)) THROW_(bResult, false); // preprocess text. COpcString cFraction = cText; // add trailing zeros. while (cFraction.GetLength() < 3) cFraction += _T("0"); // truncate extra digits. if (cFraction.GetLength() > 3) cFraction = cFraction.SubStr(0,3); if (!ToUnsigned(cFraction, uValue, MAX_ULONG, 0, 10)) { THROW_(bResult, false); } // result is in milliseconds. wFraction = (WORD)uValue; } } CATCH { wHour = 0; wMinute = 0; wSeconds = 0; wFraction = 0; } return bResult; }
// ToUnsigned static bool ToUnsigned( const COpcString& cString, ULong& nValue, ULong nMax, ULong nMin, UINT uBase ) { bool bResult = true; TRY { COpcText cText; COpcTextReader cReader(cString); // extract non-whitespace. cText.SetType(COpcText::NonWhitespace); cText.SetEofDelim(); if (!cReader.GetNext(cText)) { THROW_(bResult, false); } COpcString cValue = cText; nValue = 0; for (UINT ii = 0; ii < cValue.GetLength(); ii++) { UINT uDigit = CharToValue(cValue[ii], uBase); // invalid digit found. if (uDigit == -1) { bResult = false; break; } // detect overflow if (nValue > nMax/uBase) THROW_(bResult, false); // shift result up by base. nValue *= uBase; // detect overflow if (nValue > nMax - uDigit) THROW_(bResult, false); // add digit. nValue += uDigit; } // detect underflow if (nMin > nValue) THROW_(bResult, false); } CATCH { nValue = 0; } return bResult; }