IFDE_CSSSelector* CFDE_CSSSelector::FromString(IFX_MEMAllocator* pStaticStore, const FX_WCHAR* psz, int32_t iLen) { FXSYS_assert(pStaticStore != NULL && psz != NULL && iLen > 0); const FX_WCHAR* pStart = psz; const FX_WCHAR* pEnd = psz + iLen; for (; psz < pEnd; ++psz) { switch (*psz) { case '>': case '[': case '+': return NULL; } } CFDE_CSSSelector *pFirst = NULL, *pLast = NULL; CFDE_CSSSelector *pPersudoFirst = NULL, *pPersudoLast = NULL; for (psz = pStart; psz < pEnd;) { FX_WCHAR wch = *psz; if (wch == '.' || wch == '#') { if (psz == pStart || psz[-1] == ' ') { CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, L"*", 1, TRUE); if (p == NULL) { return NULL; } if (pFirst != NULL) { pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); p->SetNext(pFirst); } pFirst = pLast = p; } FXSYS_assert(pLast != NULL); int32_t iNameLen = FDE_GetCSSNameLen(++psz, pEnd); if (iNameLen == 0) { return NULL; } FDE_CSSSELECTORTYPE eType = wch == '.' ? FDE_CSSSELECTORTYPE_Class : FDE_CSSSELECTORTYPE_ID; CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) CFDE_CSSSelector(eType, psz, iNameLen, FALSE); if (p == NULL) { return NULL; } p->SetNext(pLast->GetNextSelector()); pLast->SetNext(p); pLast = p; psz += iNameLen; } else if (FDE_IsCSSChar(wch) || wch == '*') { int32_t iNameLen = wch == '*' ? 1 : FDE_GetCSSNameLen(psz, pEnd); if (iNameLen == 0) { return NULL; } CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, psz, iNameLen, TRUE); if (p == NULL) { return NULL; } if (pFirst == NULL) { pFirst = pLast = p; } else { pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); p->SetNext(pFirst); pFirst = pLast = p; } psz += iNameLen; } else if (wch == ':') { int32_t iNameLen = FDE_GetCSSPersudoLen(psz, pEnd); if (iNameLen == 0) { return NULL; } CFDE_CSSSelector* p = FDE_NewWith(pStaticStore) CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Persudo, psz, iNameLen, TRUE); if (p == NULL) { return NULL; } if (pPersudoFirst == NULL) { pPersudoFirst = pPersudoLast = p; } else { pPersudoLast->SetNext(p); pPersudoLast = p; } psz += iNameLen; } else if (wch == ' ') { psz++; } else { return NULL; } } if (pPersudoFirst == NULL) { return pFirst; } else { pPersudoLast->SetNext(pFirst); return pPersudoFirst; } }
CFDE_CSSSelector* CFDE_CSSSelector::FromString( IFX_MemoryAllocator* pStaticStore, const FX_WCHAR* psz, int32_t iLen) { ASSERT(pStaticStore && psz && iLen > 0); const FX_WCHAR* pStart = psz; const FX_WCHAR* pEnd = psz + iLen; for (; psz < pEnd; ++psz) { switch (*psz) { case '>': case '[': case '+': return nullptr; } } CFDE_CSSSelector* pFirst = nullptr; CFDE_CSSSelector* pLast = nullptr; CFDE_CSSSelector* pPersudoFirst = nullptr; CFDE_CSSSelector* pPersudoLast = nullptr; for (psz = pStart; psz < pEnd;) { FX_WCHAR wch = *psz; if (wch == '.' || wch == '#') { if (psz == pStart || psz[-1] == ' ') { CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, L"*", 1, true); if (!p) return nullptr; if (pFirst) { pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); p->SetNext(pFirst); } pFirst = pLast = p; } ASSERT(pLast); int32_t iNameLen = FDE_GetCSSNameLen(++psz, pEnd); if (iNameLen == 0) { return nullptr; } FDE_CSSSELECTORTYPE eType = wch == '.' ? FDE_CSSSELECTORTYPE_Class : FDE_CSSSELECTORTYPE_ID; CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) CFDE_CSSSelector(eType, psz, iNameLen, false); if (!p) return nullptr; p->SetNext(pLast->GetNextSelector()); pLast->SetNext(p); pLast = p; psz += iNameLen; } else if (FDE_IsCSSChar(wch) || wch == '*') { int32_t iNameLen = wch == '*' ? 1 : FDE_GetCSSNameLen(psz, pEnd); if (iNameLen == 0) { return nullptr; } CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Element, psz, iNameLen, true); if (!p) return nullptr; if (pFirst) { pFirst->SetType(FDE_CSSSELECTORTYPE_Descendant); p->SetNext(pFirst); } pFirst = p; pLast = p; psz += iNameLen; } else if (wch == ':') { int32_t iNameLen = FDE_GetCSSPersudoLen(psz, pEnd); if (iNameLen == 0) { return nullptr; } CFDE_CSSSelector* p = FXTARGET_NewWith(pStaticStore) CFDE_CSSSelector(FDE_CSSSELECTORTYPE_Persudo, psz, iNameLen, true); if (!p) return nullptr; if (pPersudoFirst) pPersudoLast->SetNext(p); else pPersudoFirst = p; pPersudoLast = p; psz += iNameLen; } else if (wch == ' ') { psz++; } else { return nullptr; } } if (!pPersudoFirst) return pFirst; pPersudoLast->SetNext(pFirst); return pPersudoFirst; }