// Sink.cpp : Implementation of CRoutingSinkApp and DLL registration. #include "stdinc.h" //////////////////////////////////////////////////////////////////////////// // Method: CCmdInfo() // Member of: // Arguments: // Returns: // Description: //////////////////////////////////////////////////////////////////////////// CCmdInfo::CCmdInfo(LPSTR szCmd) { nArgNo = 0; pArgs = NULL; ZeroMemory(szDefTag, sizeof(szDefTag)); ZeroMemory(szCmdKey, sizeof(szCmdKey)); ParseLine(szCmd, this); } //////////////////////////////////////////////////////////////////////////// // Method: ~CCmdInfo() // Member of: // Arguments: // Returns: // Description: //////////////////////////////////////////////////////////////////////////// CCmdInfo::~CCmdInfo() { while(NULL != pArgs) { CArgList *tmp = pArgs->pNext; delete pArgs; pArgs = tmp; } } void CCmdInfo::SetDefTag(LPSTR szTag) { if(szTag && szTag[0]) lstrcpy(szDefTag, szTag); for(CArgList *p = pArgs; NULL != p; p = p->pNext) { // set the tag to the default value if not already set if(p->szTag[0] == 0 && szDefTag[0] != 0) lstrcpy(p->szTag, szDefTag); } } //////////////////////////////////////////////////////////////////////////// // Method: GetValue() // Member of: // Arguments: // Returns: // Description: //////////////////////////////////////////////////////////////////////////// HRESULT CCmdInfo::GetValue(LPSTR szTag, LPSTR szVal) { HRESULT hr = E_FAIL; if(NULL != szTag) { // set the search parameters pSearchPos = pArgs; lstrcpy(szSearchTag, szTag); } for(CArgList *p = pSearchPos; NULL != p; p = p->pNext) { if(!lstrcmpi(p->szTag, szSearchTag)) { if(NULL != szVal) lstrcpy(szVal, p->szVal); hr = S_OK; pSearchPos = p->pNext; break; } } return hr; } //////////////////////////////////////////////////////////////////////////// // Method: GetValue() // Member of: // Arguments: // Returns: // Description: //////////////////////////////////////////////////////////////////////////// HRESULT CCmdInfo::AllocValue(LPSTR szTag, LPSTR* pszVal) { HRESULT hr = E_FAIL; if(NULL != szTag) { // set the search parameters pSearchPos = pArgs; lstrcpy(szSearchTag, szTag); } for(CArgList *p = pSearchPos; NULL != p; p = p->pNext) { if(!lstrcmpi(p->szTag, szSearchTag)) { if(NULL != (*pszVal)) delete [] (*pszVal); (*pszVal) = new char[lstrlen(p->szVal) + 1]; if(NULL == (*pszVal)) { hr = E_OUTOFMEMORY; } else { lstrcpy((*pszVal), p->szVal); hr = S_OK; pSearchPos = p->pNext; } break; } } return hr; } //////////////////////////////////////////////////////////////////////////// // Method: ParseLine() // Member of: // Arguments: // Returns: // Description: //////////////////////////////////////////////////////////////////////////// HRESULT CCmdInfo::ParseLine(LPSTR szCmd, CCmdInfo *pCmd) { HRESULT hr = E_FAIL; // quick hack for keeping info on quoted strings unsigned nQStart[64]; unsigned nQEnd[64]; unsigned nQIdx = 0; BOOL fInQ = FALSE; unsigned nFirstEqualPos = 0; char *s, *token; ZeroMemory(&nQStart, sizeof(nQStart)); ZeroMemory(&nQEnd, sizeof(nQEnd)); // find out where the arguments begin for(s = szCmd; !isspace(*s); s++); int nPref = (int) (s - szCmd); // scan the buffer for quoted strings for(s = szCmd; *s; s++) { if(*s == '"') { if(fInQ) { nQEnd[nQIdx++] = (unsigned) (s - szCmd - nPref); fInQ = FALSE; } else { nQStart[nQIdx] = (unsigned) (s - szCmd - nPref); fInQ = TRUE; } } } // get the position of the first equal sign s = strchr(szCmd, '='); nFirstEqualPos = (unsigned) (s - szCmd - nPref); // get the command code token = strtok(szCmd, " "); if(NULL == token) { pCmd->szCmdKey[0] = 0; goto Exit; } else lstrcpy(pCmd->szCmdKey, token); // we have a partial command. return S_OK hr = S_OK; // build the argument list do { char *en, *mid; char buf[1024]; ZeroMemory(buf, sizeof(buf)); char *token = NULL; BOOL fInQ; do { fInQ = FALSE; token = strtok(NULL, ","); if(NULL == token) break; lstrcat(buf, token); // if ',' is in a quoted string concatenate to buf and continue for(unsigned i = 0; i < nQIdx; i++) { unsigned nAux = (unsigned) (token - szCmd + lstrlen(token) - nPref); if(nAux > nQStart[i] && nAux < nQEnd[i]) { lstrcat(buf, ","); fInQ = TRUE; break; } } } while(fInQ); if(buf[0] == '\0') break; else token = (LPSTR)buf; // strip spaces for(; isspace(*token); token++); // check if there's anything left if(!(*token)) continue; for(en = token; *en; en++); for(--en; isspace(*en); en--); // check if there's anything left if(token > en) continue; // allocate a pair object CCmdInfo::CArgList *tmp = new CCmdInfo::CArgList; if(NULL == tmp) { hr = E_OUTOFMEMORY; goto Exit; } // insert into list tmp->pNext = pCmd->pArgs; pCmd->pArgs = tmp; // set the no. of pairs pCmd->nArgNo++; // set the values // if first '=' is in quoted string, treat whole expression as // untagged value. fInQ = FALSE; for(unsigned i = 0; i < nQIdx; i++) { if(nFirstEqualPos > nQStart[i] && nFirstEqualPos < nQEnd[i]) { fInQ = TRUE; break; } } mid = fInQ ? NULL : strchr(token, '='); if(NULL == mid) { // this is not a pair. Treating as un-named value. // remove the quotes around the value if(token[0] == '"' && token[en - token] == '"') { token++; en--; } tmp->SetVal(token, (unsigned) (en - token + 1)); } else { // set the tag for(char *t = mid - 1; isspace(*t); t--); // check if we have a tag (might be something like "..., = value" if(t - token + 1 > 0) CopyMemory(tmp->szTag, token, t - token + 1); // set the value for(t = mid + 1; isspace(*t) && t < en; t++); // remove the quotes around the value if(t[0] == '"' && t[en - t] == '"') { t++; en--; } tmp->SetVal(t, (unsigned) (en - t + 1)); } }while(TRUE); Exit: return hr; } //////////////////////////////////////////////////////////////////////////// // Method: StringToHRES() // Member of: // Arguments: // Returns: // Description: //////////////////////////////////////////////////////////////////////////// HRESULT CCmdInfo::StringToHRES(LPSTR szVal, HRESULT *phrRes) { HRESULT hr = S_OK; if(isdigit(*szVal)) { DWORD hr; int n; if(*szVal == '0' && tolower(*(szVal+1)) == 'x' && isxdigit(*(szVal+2))) // read as hex number n = sscanf(szVal+2, "%lx", &hr); else // read as dec number n = sscanf(szVal, "%lu", &hr); if(n == 1) (*phrRes) = (HRESULT)hr; } else if(isalpha(*szVal)) { // see if this a HRESULT code if(!lstrcmp(szVal, "S_OK")) (*phrRes) = S_OK; else if(!lstrcmp(szVal, "S_FALSE")) (*phrRes) = S_FALSE; else if(!lstrcmp(szVal, "E_FAIL")) (*phrRes) = E_FAIL; else if(!lstrcmp(szVal, "E_OUTOFMEMORY")) (*phrRes) = E_OUTOFMEMORY; else hr = S_FALSE; } else hr = S_FALSE; return hr; }