//----------------------------------------------------------------------------- // Загрузка //----------------------------------------------------------------------------- bool cXMLDocument::Load(const char *XMLFileName) { printf("Open XML file: %s\n", XMLFileName); // если что-то было загружено ранее - освобождаем ReleaseXMLDocument(); // читаем данные eFILE *XMLFile = vw_fopen(XMLFileName); if (XMLFile == NULL) { fprintf(stderr, "XML file not found: %s\n", XMLFileName); return false; } // читаем все данные в буфер XMLFile->fseek(0, SEEK_END); unsigned int DataLength = XMLFile->ftell(); XMLFile->fseek(0, SEEK_SET); char *Buffer = new char[DataLength+1]; Buffer[DataLength] = 0; XMLFile->fread(Buffer, DataLength, 1); vw_fclose(XMLFile); // проверяем заголовок if (FindSubString(Buffer, "<?xml") == -1) { fprintf(stderr, "XML file corrupted: %s\n", XMLFileName); return false; } if (FindSubString(Buffer, "?>") == -1) { fprintf(stderr, "XML file corrupted: %s\n", XMLFileName); return false; } // идем на рекурсивную обработку if (!ParseTagContent(Buffer, FindSubString(Buffer, "?>")+strlen("?>"), Buffer+FindSubString(Buffer, "?>")+strlen("?>"), 0)) { fprintf(stderr, "XML file corrupted: %s\n", XMLFileName); delete [] Buffer; return false; } if (RootXMLEntry == 0) { fprintf(stderr, "XML file corrupted, root element not found: %s\n", XMLFileName); delete [] Buffer; return false; } delete [] Buffer; return true; }
// Check for equalit strings but ignore case. UBOOL CheckStringsEqual( const TCHAR* FirstString, const TCHAR* SecondString ) { if( _tcslen(FirstString) != _tcslen(SecondString) ) return false; INT DummyPos; return FindSubString( FirstString, SecondString, DummyPos ); }
// Check for equalit strings but ignore case. UBOOL CheckStringsEqual( const char* FirstString, const char* SecondString ) { if( strlen(FirstString) != strlen(SecondString) ) return false; INT DummyPos; return FindSubString( FirstString, SecondString, DummyPos ); }
int psXMLString::FindTag( const char* tagName, int start ) { psString temp("<"); temp+=tagName; return FindSubString( temp, start, XML_CASE_INSENSITIVE ); }
// // Try to find a DigitNum digits sized number after a certain substring in a string and return the numerical value. // INT FindValueTag(const TCHAR* CheckString, const TCHAR* Fragment, INT DigitNum) { INT SubPos; FindSubString(CheckString,Fragment,SubPos); if( !FindSubString(CheckString,Fragment,SubPos) ) return -1; INT N=0; SubPos += ( INT )_tcslen(Fragment); // move beyond fragment. INT NumPos = 0; while( (CheckString[NumPos+SubPos] >= 0x30) && (CheckString[NumPos+SubPos] <= 0x39) && (NumPos < DigitNum) ) { INT A=CheckString[NumPos+SubPos]-0x30; //0x30..0x39 N= 10*N + A; NumPos++; } return N; }
/* * RemoveFromSystemPath() -- remove specified entry from system PATH variable. */ BOOL RemoveFromSystemPath(char *pszPath) { char *pszCurNls = 0; char *pszNewNls = 0; char *pSemi = 0; char *pCurPath = 0; BOOL bStatus = TRUE; if (!ReadSystemEnv(&pszCurNls, "Path")) return FALSE; /* Is it already not in the path? */ if (!pszCurNls || !FindSubString(pszCurNls, pszPath)) { if (pszCurNls) free(pszCurNls); return TRUE; } pszNewNls = (char *)malloc(strlen(pszCurNls) + 1); if (pszNewNls == 0) { free(pszCurNls); return FALSE; } pszNewNls[0] = 0; pCurPath = pszCurNls; while (1) { pSemi = strchr(pCurPath, ';'); if (pSemi) *pSemi = 0; if (_stricmp(pCurPath, pszPath) != 0) { if (pszNewNls[0] != 0) strcat(pszNewNls, ";"); strcat(pszNewNls, pCurPath); } if (!pSemi) break; pSemi++; pCurPath = pSemi; } bStatus = WriteSystemEnv(pszNewNls, "Path"); free(pszNewNls); free(pszCurNls); return bStatus; }
size_t psXMLString::GetTag( int start, psXMLTag& tag ) { psString tmp(">"); int end = FindSubString(tmp, start); if ( end == -1 ) tag.Empty(); else GetSubString(tag, start, end+1); return tag.Length(); }
bool cXMLDocument::ParseTagLine(char *OriginBuffer, unsigned int StartPosition, char *Buffer, cXMLEntry *XMLEntry) { // 1 - получаем имя тэга (начинается сразу после символа <, а заканчивается пробелом, >, />, или символом таб) int TagNameEnd = FindSubString(Buffer, " "); if (TagNameEnd == -1 || (FindSubString(Buffer, "\t") != -1 && TagNameEnd > FindSubString(Buffer, "\t"))) TagNameEnd = FindSubString(Buffer, "\t"); if (TagNameEnd == -1 || (FindSubString(Buffer, ">") != -1 && TagNameEnd > FindSubString(Buffer, ">"))) TagNameEnd = FindSubString(Buffer, ">"); if (TagNameEnd == -1 || (FindSubString(Buffer, "/>") != -1 && TagNameEnd > FindSubString(Buffer, "/>"))) TagNameEnd = FindSubString(Buffer, "/>"); XMLEntry->Name = CreateSubString(Buffer, 1, TagNameEnd); // 2 - проверяем наличие атрибутов и заносим их в динамический массив unsigned int i = TagNameEnd; while (((Buffer+i)[0] != '>') || ((Buffer+i)[0] != '\0')) { // пропускаем все пробелы и табы while ((((Buffer+i)[0] == ' ') || ((Buffer+i)[0] == '\t')) && ((Buffer+i)[0] != '\0')) i++; if ((Buffer+i)[0] == '\0') {fprintf(stderr, "XML file corrupted, line: %i.", GetLineNumber(OriginBuffer, StartPosition)); break;} // еще раз проверяем, возможно завершение тэга ставили через пробел или таб if (((Buffer+i)[0] == '>') || (!strncmp(Buffer+i, "/>", strlen("/>")))) break; // находим имя атрибута unsigned int AttribNameStart = i; while (((Buffer+i)[0] != '=') && ((Buffer+i)[0] != '\0')) i++; if ((Buffer+i)[0] == '\0') {fprintf(stderr, "XML file corrupted, line: %i.", GetLineNumber(OriginBuffer, StartPosition)); break;} unsigned int AttribNameEnd = i; // пропускаем все до кавычек (они у нас следующие, после знака равенства) i+=2; unsigned int AttribDataStart = i; while ((((Buffer+i)[0] != '\'') && ((Buffer+i)[0] != '\"')) && ((Buffer+i)[0] != '\0')) i++; if ((Buffer+i)[0] == '\0') {fprintf(stderr, "XML file corrupted, line: %i.", GetLineNumber(OriginBuffer, StartPosition)); break;} unsigned int AttribDataEnd = i; i++; // собираем новый атрибут и подключаем его к элементу cXMLAttribute *XMLAttribute = new cXMLAttribute; AttachXMLAttribute(XMLEntry, XMLAttribute); XMLAttribute->Name = CreateSubString(Buffer, AttribNameStart, AttribNameEnd); XMLAttribute->Data = CreateSubString(Buffer, AttribDataStart, AttribDataEnd); } // 3 - определяем и номер строки XMLEntry->LineNumber = GetLineNumber(OriginBuffer, StartPosition); // 4 - определить есть ли в ней атрибут закрытия '/', или у нас есть еще и контент и закрывающий тэг if (FindSubString(Buffer, "/>") != -1) return false; return true; }
// Removes the 'Fragment' (e.g. .max ) and puts result in OutString. UBOOL RemoveExtString(const TCHAR* CheckString, const TCHAR* Fragment, TCHAR* OutString) { INT Pos=0; FindSubString( CheckString, Fragment, Pos); if(Pos == 0) { return 0; OutString[0] = 0; } for(INT t=0; t<Pos; t++) { OutString[t]=CheckString[t]; } OutString[Pos] = 0; return 1; }
/* ModifyString()中 过滤XY,找到第一个回文字段的开始,即BCDCB 中的B,然后跨过回文段 到ABABA,进入FindSubString() 得 ABA,即count=1; sprintf( p2, "%i", count );把B换成1,即A1,然后 *p2++=*p1++ A1BAA */ void ModifyString( char* pText ) { char * p1 = pText; char * p2 = p1; while ( *p1 != '\0' ) { int count = FindSubString( p1 ); if ( count > 0 ) { *p2++ = *p1; sprintf( p2, "%i", count ); while ( *p2 != '\0' ) { p2++; } p1 += count + count + 1; }else { *p2++ = *p1++; } } }
/* * AddToSystemPath() -- add specified entry to system PATH variable. */ BOOL AddToSystemPath(char *pszPath) { char *pszCurPath = 0; char *pszNewPath = 0; BOOL bStatus = TRUE; if (!ReadSystemEnv(&pszCurPath, "Path")) return FALSE; /* Do we need to add it? */ if (!pszCurPath || !FindSubString(pszCurPath, pszPath)) { /* Old path + a semicolon + the new path entry + a null */ pszNewPath = malloc((pszCurPath ? strlen(pszCurPath) + 1 : 0) + strlen(pszPath) + 1); if (pszNewPath == 0) { if (pszCurPath) free(pszCurPath); return FALSE; } pszNewPath[0] = 0; if (pszCurPath) { strcpy(pszNewPath, pszCurPath); strcat(pszNewPath, ";"); } strcat(pszNewPath, pszPath); bStatus = WriteSystemEnv(pszNewPath, "Path"); free(pszNewPath); } if (pszCurPath) free(pszCurPath); return bStatus; }
void psXMLTag::GetTagParm(const char* parm, csString& value ) { psString param(" "); param.Append(parm); param.Append('='); int start = FindSubString(param, 0, XML_CASE_INSENSITIVE); //Checks to see if the parm is getting mixed up with the tag name. if ( start==1 ) { psString tagName; GetTagName(tagName); start = FindSubString(param,(int)tagName.Length(),XML_CASE_INSENSITIVE); } psString tempStr; value=""; const char *myData = GetData(); while ( start != -1 ) { start += (int)param.Length(); if (start >= (int)Length()) return; // skip whitespace after parm name while (myData[start]==' ') { start++; if (start >= (int)Length()) return; } size_t end = start+1; // parm is at least one char // Determine delimiter, if any char chr; if ( myData[start] == '\"') chr = '\"'; else if ( myData[start] == '[') chr = ']'; else if ( myData[start] == '\'') chr = '\''; else chr = ' '; while ( end < Length() && myData[end]!=chr && myData[end] != '>') end++; GetSubString(tempStr, start+(chr!=' '), end); // Replace any xml code with the correct '&' const char* what = "&"; const char* with = "&"; while (tempStr.FindSubString(what) != -1) tempStr.ReplaceSubString(what,with); what = "'"; with = "'"; while (tempStr.FindSubString(what) != -1) tempStr.ReplaceSubString(what,with); value = tempStr; return; } }
bool cXMLDocument::ParseTagContent(char *OriginBuffer, unsigned int StartPosition, char *Buffer, cXMLEntry *ParentXMLEntry) { // проверяем наличие вложенных тэгов bool ChildsFound = true; int DetectTagOpenSymbol = FindSubString(Buffer, "<"); // если символа открытия в строке нет - это просто данные, иначе проверяем, что стоит до этого символа if (DetectTagOpenSymbol > 0) { int CurrentPos = 0; while(CurrentPos != DetectTagOpenSymbol) { // если до открывающего тэга идут не " ", "\t", "\r", "\n", значит у нас просто данные if (((Buffer+CurrentPos)[0] != ' ') && ((Buffer+CurrentPos)[0] != '\t') && ((Buffer+CurrentPos)[0] != '\r') && ((Buffer+CurrentPos)[0] != '\n')) { ChildsFound = false; break; } CurrentPos++; } } else ChildsFound = false; // 1 - это просто контент, заносим данные и выходи из рекурсии if (!ChildsFound) { ParentXMLEntry->Content = CreateSubString(Buffer, 0, strlen(Buffer)); return true; } // 2 - если в строке нашли открывающий символ тэга - идем на рекурсивную обработку строки с хмл данными else { // в цикле, пока не достигнем конца обрабатываемой строки: unsigned int CurrentBufferPosition = 0; while(strlen(Buffer) > 0) { // находим положение открывающего тэг символа и закрывающего DetectTagOpenSymbol = FindSubString(Buffer, "<"); // это может быть комментарий, проверяем if (!strncmp(Buffer+DetectTagOpenSymbol, "<!--", strlen("<!--"))) { // ищем завершающую часть, и сразу перемещаемся к ней int DetectCommentCloseSymbol = FindSubString(Buffer, "-->"); if (DetectCommentCloseSymbol == -1) { fprintf(stderr, "XML file corrupted, can't find comment end in line %i.\n", GetLineNumber(OriginBuffer, StartPosition+DetectTagOpenSymbol+CurrentBufferPosition)); return false; } Buffer += DetectCommentCloseSymbol + strlen("-->"); CurrentBufferPosition += DetectCommentCloseSymbol + strlen("-->"); continue; } // если в строке уже нет открывающих символов - просто выходим, все проверили if (DetectTagOpenSymbol == -1) return true; int DetectTagCloseSymbol = FindSubString(Buffer, ">"); // если был открывающий символ, но нет закрывающего - это ошибка структуры документа if (DetectTagCloseSymbol == -1) { fprintf(stderr, "XML file corrupted, can't find element end for element in line %i.\n", GetLineNumber(OriginBuffer, StartPosition+DetectTagOpenSymbol+CurrentBufferPosition)); return false; } DetectTagCloseSymbol += strlen(">"); // создаем новый элемент и подключаем его к родительскому cXMLEntry *XMLEntry = new cXMLEntry; AttachXMLChildEntry(ParentXMLEntry, XMLEntry); // полученные данные передаем на обработку и анализ строки элемента char *TagString = CreateSubString(Buffer, DetectTagOpenSymbol, DetectTagCloseSymbol); bool ElementHaveContent = ParseTagLine(OriginBuffer, StartPosition+DetectTagOpenSymbol+CurrentBufferPosition, TagString, XMLEntry); delete [] TagString; // если у нас закрытый тэг - с этим элементом закончили, идем искать дальше if (!ElementHaveContent) { Buffer += DetectTagCloseSymbol; CurrentBufferPosition += DetectTagCloseSymbol; continue; } // если тэг открытый - ищем завершающий тэг </имя> char *CloseElement = new char[strlen("</>")+strlen(XMLEntry->Name)+1]; strcpy(CloseElement, "</"); strcat(CloseElement, XMLEntry->Name); strcat(CloseElement, ">"); CloseElement[strlen("</>")+strlen(XMLEntry->Name)] = 0; int CloseElementPosition = FindSubString(Buffer, CloseElement); delete [] CloseElement; // если закрывающего элемента нет - значит файл поврежден if (CloseElementPosition == -1) { fprintf(stderr, "XML file corrupted, can't find element end: %s in line: %i\n", XMLEntry->Name, GetLineNumber(OriginBuffer, StartPosition+DetectTagOpenSymbol+CurrentBufferPosition)); return false; } // передаем данные на рекурсивную обработку (если закрывающий тэг не стоит сразу после открывающего) if (DetectTagCloseSymbol < CloseElementPosition) { char *ElementContent = CreateSubString(Buffer, DetectTagCloseSymbol, CloseElementPosition); if (!ParseTagContent(OriginBuffer, DetectTagCloseSymbol+StartPosition+CurrentBufferPosition, ElementContent, XMLEntry)) { // вернули с ошибкой, выходим delete [] ElementContent; return false; } delete [] ElementContent; } // смещаем буфер Buffer += CloseElementPosition + strlen(XMLEntry->Name) + strlen("</>"); CurrentBufferPosition += CloseElementPosition + strlen(XMLEntry->Name) + strlen("</>"); } } return false; }
UBOOL CheckSubString(const TCHAR* CheckString, const TCHAR* Fragment) { INT DummyPos; return FindSubString(CheckString,Fragment,DummyPos); }