📄 browse.cpp
字号:
/**************************************************************************
* *
* Light OPC Server development library *
* *
* Copyright (c) 2000 Timofei Bondarenko *
*
IOPCBrowseServerAddressSpace
**************************************************************************/
#include <opcerror.h>
#include "privopc.h"
#include "enum.h"
extern BOOL MatchPattern(LPCWSTR String, LPCWSTR Pattern, BOOL bCaseSensitive);
/**************************************************************************/
static loTagId lo_browse_tag(loService *se, loTagId first,
const loWchar *name, unsigned len,
OPCBROWSETYPE btype);
static loTagId lo_browse_branch(loService *se, const loWchar *name);
#if 1
#define loLOCK_MGMT_I(x) lw_rw_rdlock(&se->lkMgmt)
#define loLOCK_MGMT_O(x)
#define loUnLOCK_MGMT_I(x) lw_rw_unlock(&se->lkMgmt)
#define loUnLOCK_MGMT_O(x)
#else
#define loLOCK_MGMT_I(x)
#define loLOCK_MGMT_O(x) lw_rw_rdlock(&se->lkMgmt)
#define loUnLOCK_MGMT_I(x)
#define loUnLOCK_MGMT_O(x) lw_rw_unlock(&se->lkMgmt)
#endif
/**************************************************************************/
int lo_name_level(loWchar brsep, const loWchar *name)
{
int ii;
const loWchar *ls;
if (!name || !*name) return 0; /* root */
if (!brsep) return 1;
for(ii = 1, ls = name; 0 != (ls = wcschr(ls, brsep)); ls++) ii++;
return ii;
}
int lo_name_levlen(loWchar brsep, const loWchar *name, int level)
{
const loWchar *ls;
if (!name) return 0;
if (level <= 0) return 0;
for(ls = name; (ls = wcschr(ls, brsep)) && --level > 0; ls++);
return ls? ls - name: wcslen(name);
}
/**************************************************************************/
STDMETHODIMP LightOPCServer::QueryOrganization(OPCNAMESPACETYPE *pNameSpaceType)
{
HRESULT hr = S_OK;
LO_CHECK_STATEz0("QueryOrganisation");
if (!pNameSpaceType) hr = E_INVALIDARG;
else
{
*pNameSpaceType = se->branch_sep? OPC_NS_HIERARCHIAL: OPC_NS_FLAT;
}
LO_FINISH();
return hr;
}
STDMETHODIMP LightOPCServer::BrowseAccessPaths(
/* [string][in] */ LPCWSTR szItemID,
/* [out] */ LPENUMSTRING *ppIEnumString)
{
HRESULT hr = E_NOTIMPL;
LO_CHECK_STATEz1("BrowseAccessPath", ppIEnumString);
if (!ppIEnumString) hr = E_INVALIDARG;
else
{
if (se->driver.ldBrowseAccessPath)
{
loEnumString *es = new loEnumString(0);
if (es)
{
*ppIEnumString = es;
hr = se->driver.ldBrowseAccessPath(&ctxt.cactx, szItemID, ppIEnumString);
if (!*ppIEnumString && !FAILED(hr)) hr = E_FAIL;
if (FAILED(hr))
{
if (*ppIEnumString == (LPENUMSTRING)es) *ppIEnumString = 0;
delete es;
}
else if (*ppIEnumString != (LPENUMSTRING)es)
delete es;
else if (S_OK != (hr = es->initiate(&otrk)))
delete es;
}
else hr = E_OUTOFMEMORY;
}
}
UL_NOTICE((LOG_SR("BrowseAccessPath(%ls) = %s"),
loWnul(szItemID), loStrError(hr)));
LO_FINISH();
return hr;
}
/**************************************************************************/
HRESULT LightOPCServer::set_browsepos(const loWchar *pos, int len)
{
loWchar *opos;
if (!pos) pos = L"";
if (-1 == len) len = wcslen(pos);
opos = browsepos.sb_str;
if (!loStringBuf_REALLOC(&browsepos, (unsigned)len + 1))
return E_OUTOFMEMORY;
if (opos != pos) wcsncpy(browsepos.sb_str, pos, len);
browsepos.sb_str[len] = 0;
// UL_DEBUG((LOG_SR("SetBrowsePosition(%p=%ls)"), browsepos.sb_str, browsepos.sb_str));
return S_OK;
}
int LightOPCServer::cat_browsepos(const loWchar *cpos)
{
int len_n, len_o, len_b;
loWchar brsep;
if (!cpos) cpos = L"";
len_n = wcslen(cpos);
len_o = len_b = 0;
if (browsepos.sb_str &&
(len_o = wcslen(browsepos.sb_str)) && len_n &&
(brsep = se->branch_sep)) len_b = 1;
if (S_OK != set_browsepos(browsepos.sb_str, len_o + len_b + len_n)) return -1;
if (len_b) browsepos.sb_str[len_o] = brsep;
memcpy(browsepos.sb_str + len_o + len_b, cpos, len_n * sizeof(loWchar));
browsepos.sb_str[len_o + len_b + len_n] = 0;
// UL_DEBUG((LOG_SR("CatBrowsePosition( %ls + %ls)"), browsepos.sb_str, cpos));
return len_o;
}
/**************************************************************************/
STDMETHODIMP LightOPCServer::ChangeBrowsePosition(
/* [in] */ OPCBROWSEDIRECTION dwBrowseDirection,
/* [string][in] */ LPCWSTR szString)
{
HRESULT hr = S_OK;
LO_CHECK_STATEz0("ChangeBrowsePosition");
lock_browse();
{
loWchar brsep;
int ii;
//UL_WARNING((LOG_SR("ChangeBrowsePosition->(%ls)(%ls)"), loWnul(browsepos.sb_str),loWnul(szString)));
if (!(brsep = se->branch_sep))
{
hr = E_FAIL;
UL_TRACE((LOG_SR("ChangeBrowsePosition() on the FLAT")));
}
else
switch(dwBrowseDirection)
{
case OPC_BROWSE_UP:
if (0 >= (ii = lo_name_level(brsep, browsepos.sb_str)))
{
hr = E_FAIL; /* already on root */
UL_TRACE((LOG_SR("ChangeBrowsePosition() already on root")));
}
else
{
hr = set_browsepos(browsepos.sb_str,
lo_name_levlen(brsep, browsepos.sb_str, ii - 1));
}
break;
case OPC_BROWSE_DOWN:
if (!szString || !*szString) hr = E_INVALIDARG;//loOPC_E_NOTFOUND;
else if (0 > (ii = cat_browsepos(szString))) hr = E_OUTOFMEMORY;
else if (!lo_browse_branch(se, browsepos.sb_str))
{
browsepos.sb_str[ii] = 0;
hr = E_INVALIDARG;//loOPC_E_NOTFOUND;
}
break;
case OPC_BROWSE_TO:
if (!szString || !*szString) hr = set_browsepos(0);
else
hr = lo_browse_branch(se, szString)?
set_browsepos(szString): E_INVALIDARG;//loOPC_E_NOTFOUND;
break;
default: hr = E_INVALIDARG;
UL_TRACE((LOG_SR("ChangeBrowsePosition() unknown direction")));
break;
}
}
UL_TRACE((LOG_SR("ChangeBrowsePosition(%X <%ls>) = %ls"),
dwBrowseDirection, loWnul(szString), loWnul(browsepos.sb_str)));
unlock_browse();
if (S_OK != hr)
{
UL_INFO((LOG_SR("ChangeBrowsePosition(%X <%ls>) = %s"),
dwBrowseDirection, loWnul(szString), loStrError(hr)));
}
LO_FINISH();
return hr;
}
/**************************************************************************/
STDMETHODIMP LightOPCServer::GetItemID(
/* [in] */ LPWSTR szItemDataID,
/* [string][out] */ LPWSTR *szItemID)
{
HRESULT hr = S_OK;
LO_CHECK_STATEz1("GetItemID", szItemID);
if (!szItemID) hr = E_INVALIDARG;
else
{
loWchar *itemid = 0;
int ii = -1;
lock_browse();
// UL_DEBUG((LOG_SR("GetItemID->(%ls)(%ls)"), loWnul(browsepos.sb_str),loWnul(szItemDataID)));
if (0 <= (ii = cat_browsepos(szItemDataID)))
{
itemid = loComWstrdup(browsepos.sb_str/*? browsepos.sb_str: L""*/);
browsepos.sb_str[ii] = 0;
}
unlock_browse();
if (!itemid)
{
hr = E_OUTOFMEMORY;
UL_INFO((LOG_SR("GetItemID(%ls) = %s"),
loWnul(szItemDataID), loStrError(hr)));
}
else
{
/* loFindItemID() will go faster */
if (loFindItemID(se, &ctxt.cactx, 0, itemid, 0,
VT_EMPTY, loDAIG_BROWSE, 0, &hr) ||
lo_browse_branch(se, itemid) )
*szItemID = itemid, hr = S_OK;
else
{
//if (!FAILED(hr)) loOPC_E_NOTFOUND;
hr = E_INVALIDARG;
UL_INFO((LOG_SR("GetItemID(%ls)(%ls) = %s"),
loWnul(szItemDataID), loWnul(itemid), loStrError(hr)));
loComFree(itemid);
}
}
}
if (S_OK == hr)
{
UL_NOTICE((LOG_SR("GetItemID(%ls) = %ls"), loWnul(szItemDataID), *szItemID));
}
LO_FINISH();
return hr;
}
/**************************************************************************/
STDMETHODIMP LightOPCServer::BrowseOPCItemIDs(
/* [in] */ OPCBROWSETYPE dwBrowseFilterType,
/* [string][in] */ LPCWSTR szFilterCriteria,
/* [in] */ VARTYPE vtDataTypeFilter,
/* [in] */ DWORD dwAccessRightsFilter,
/* [out] */ LPENUMSTRING *ppIEnumString)
{
HRESULT hr = S_OK;
loEnumString *ulist = 0;
LO_CHECK_STATEz1("BrowseOPCItemIDs", ppIEnumString);
if (szFilterCriteria && !*szFilterCriteria) szFilterCriteria = 0;
if (!ppIEnumString ||
dwBrowseFilterType != OPC_FLAT &&
dwBrowseFilterType != OPC_BRANCH &&
dwBrowseFilterType != OPC_LEAF) { hr = E_INVALIDARG; goto Return; }
if (!(ulist = new loEnumString(0)))
{ hr = E_OUTOFMEMORY; goto Return; }
{
loTagId ti;
lo_hash *hash_list = 0;
loWchar brsep = se->branch_sep;
BOOL casesens = 0 == (/*se->driver.*/ldFlags & loDF_IGNCASE);
loWchar *brpos = 0;
unsigned brlen = 0;
int am_mask;
loCallerx cctx = ctxt;
loStringBuf aname;
loStringBuf_init(&aname);
lock_browse();
if (browsepos.sb_str)
{
brlen = wcslen(browsepos.sb_str);
brpos = loWstrdup(browsepos.sb_str);
}
cctx.cta.vc_lcid = ctxt.cta.vc_lcid;
unlock_browse();
if (brlen && !brpos) { hr = E_OUTOFMEMORY; goto Return; }
if (!brsep) dwBrowseFilterType = OPC_FLAT;
// level = lo_name_level(brsep, browsepos.sb_str);
UL_TRACE((LOG_SR("Browse for: %u/%ls/ access %d"),
brlen, loWnul(brpos), dwAccessRightsFilter));
dwAccessRightsFilter &= loOPC_RIGHTS;
if (dwAccessRightsFilter == (OPC_READABLE | OPC_WRITEABLE))
dwAccessRightsFilter = 0;
am_mask = dwAccessRightsFilter;
if (access_mode & loAM_RDONLY_BROWSE) am_mask &= ~OPC_WRITEABLE;
//loMilliSec stst = lo_millisec();
loLOCK_MGMT_O(&se->lkMgmt);
for(ti = 0; ti = lo_browse_tag(se, ti, brpos, brlen, dwBrowseFilterType); ti++)
{
unsigned alen;
loTagEntry *te = &se->tags[ti];
const loWchar *item = te->attr.taName + brlen;
if (!*item) continue; /* don't return itself */
if (brsep == *item) item++;
switch(dwBrowseFilterType)
{
case OPC_LEAF:
if (wcschr(item, brsep)) continue;
//if (1 < lo_name_level(brsep, item)) continue;
case OPC_FLAT:
alen = wcslen(item);
if (dwAccessRightsFilter &&
!(am_mask/*dwAccessRightsFilter*/ & te->attr.taRights)) continue;
if (vtDataTypeFilter != VT_EMPTY &&
S_OK != lo_checktype(&cctx, &te->attr,
vtDataTypeFilter)) continue;
break;
case OPC_BRANCH:
if (!wcschr(item, brsep)) continue;
//if (1 >= lo_name_level(brsep, item)) continue;
alen = lo_name_levlen(brsep, item, 1);
{
loWchar *uit;
if (ulist->total &&
!se->wstrncmp(item, uit = ulist->list[ulist->total - 1], alen) &&
0 == uit[alen]) continue; /* duplicate */
}
break;
}
if (!loStringBuf_REALLOC(&aname, alen + 1))
{
hr = E_OUTOFMEMORY; break;
}
wcsncpy(aname.sb_str, item, alen); aname.sb_str[alen] = 0;
if (szFilterCriteria &&
!MatchPattern(aname.sb_str, szFilterCriteria, casesens))
continue;
if (OPC_BRANCH == dwBrowseFilterType)
{
unsigned uu;
lo_hash a_hash = loSTRHASH(se, aname.sb_str);
for(uu = ulist->total; uu; uu--)
if (a_hash == hash_list[uu-1] &&
!se->wstrcmp(aname.sb_str, ulist->list[uu-1]) ) break;
if (uu) continue;
if (!preallocX((void**)&hash_list,
sizeof(*hash_list)*(ulist->total+1)))
{
hr = E_OUTOFMEMORY; break;
}
hash_list[ulist->total] = a_hash;
}
//UL_DEBUG((LOG_SR("Browse %ls"), aname.sb_str));
hr = ulist->add_item(&aname.sb_str);
if (S_OK != hr) break;
} /* end of for() */
loUnLOCK_MGMT_O(&se->lkMgmt);
/*
UL_WARNING((LOG_SR("BrowseOPC <%ls> %d TIME %d"),
loWnul(brpos), ulist->total, lo_millisec() - stst));
//*/
if (brpos) freeX(brpos);
if (hash_list) freeX(hash_list);
loStringBuf_clear(&aname);
}
Return:
if (S_OK == hr &&
S_OK == (hr = ulist->initiate(&otrk)))
{
*ppIEnumString = (LPENUMSTRING)ulist;
UL_NOTICE((LOG_SR("BrowseOPCItemIDs() = %u"), ulist->total));
if (!ulist->total) { ENUM_EMPTY(hr, ldFlags, ppIEnumString); }
}
else
{
if (ulist) { delete ulist; ulist = 0; }
UL_INFO((LOG_SR("BrowseOPCItemIDs() = %s"), loStrError(hr)));
}
LO_FINISH();
return hr;
}
/***************************************************************************/
loTagId lo_browse_tag(loService *se, loTagId first,
const loWchar *name, unsigned len,
OPCBROWSETYPE btype)
{
loTagEntry *te, *stop;
if (!loSERVICE_OK(se)) return 0;
if (-1 == len) len = name? wcslen(name): 0;
else if (!name && len) return 0;
loLOCK_MGMT_I(&se->lkMgmt);
// if (!first) first = 1;
te = &se->tags[first];
stop = &se->tags[se->lastnamed];
while(te <= stop)
{
loWchar *tail;
if ((loTt_VISIBLE & te->attr.taFlags) && /* loTE_USED(te) && */
(tail = te->attr.taName) &&
!se->wstrncmp(tail, name, len) &&
(0 == len ||
0 != *(tail += len) && /* only branches allowed */
*(tail++) == se->branch_sep))
{
switch(btype)
{
case OPC_BRANCH:
if (0 != wcschr(tail, se->branch_sep)) goto Found;
break;
case OPC_LEAF:
if (!se->branch_sep ||
0 == wcschr(tail, se->branch_sep)) goto Found;
break;
case OPC_FLAT:
default:
goto Found;
}
}
te++;
}
te = se->tags;
Found:
first = te - se->tags;
loUnLOCK_MGMT_I(&se->lkMgmt);
return first;
}
loTagId lo_browse_branch(loService *se, const loWchar *name)
{
loTagId ti;
unsigned len;
if (!loSERVICE_OK(se) || !se->branch_sep) return 0;
len = name? wcslen(name): 0;
loLOCK_MGMT_O(&se->lkMgmt);
for(ti = 0; ti = lo_browse_tag(se, ti, name, len, OPC_FLAT); ti++)
if (wcslen(se->tags[ti].attr.taName) > len) goto Break;
ti = 0;
Break:
loUnLOCK_MGMT_O(&se->lkMgmt);
return ti;
}
/* end of browse.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -