ULONG loEnum<BASE,ITEM,IFACE>::grow_list(ULONG newcount)
{
 if (base || total > count) return 0; /* don't grow cloned lists */
 if (newcount <= count) return count;
 newcount = (newcount + 3) & ~3;
 if (!preallocX((void**)&list, sizeof(ITEM) * newcount))
   return 0;
 memset(list + count, 0, sizeof(ITEM) * (newcount - count));
 count = newcount;
 return count;
}
Beispiel #2
0
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;
}