static void StrVecTest() { StrVec v; v.Append(str::Dup(_T("foo"))); v.Append(str::Dup(_T("bar"))); TCHAR *s = v.Join(); assert(v.Count() == 2); assert(str::Eq(_T("foobar"), s)); free(s); s = v.Join(_T(";")); assert(v.Count() == 2); assert(str::Eq(_T("foo;bar"), s)); free(s); v.Append(str::Dup(_T("glee"))); s = v.Join(_T("_ _")); assert(v.Count() == 3); assert(str::Eq(_T("foo_ _bar_ _glee"), s)); free(s); v.Sort(); s = v.Join(); assert(str::Eq(_T("barfooglee"), s)); free(s); { StrVec v2(v); assert(str::Eq(v2.At(1), _T("foo"))); v2.Append(str::Dup(_T("nobar"))); assert(str::Eq(v2.At(3), _T("nobar"))); v2 = v; assert(v2.Count() == 3 && v2.At(0) != v.At(0)); assert(str::Eq(v2.At(1), _T("foo"))); assert(&v2.At(2) == v2.AtPtr(2) && str::Eq(*v2.AtPtr(2), _T("glee"))); } { StrVec v2; size_t count = v2.Split(_T("a,b,,c,"), _T(",")); assert(count == 5 && v2.Find(_T("c")) == 3); assert(v2.Find(_T("")) == 2 && v2.Find(_T(""), 3) == 4 && v2.Find(_T(""), 5) == -1); assert(v2.Find(_T("B")) == -1 && v2.FindI(_T("B")) == 1); ScopedMem<TCHAR> joined(v2.Join(_T(";"))); assert(str::Eq(joined, _T("a;b;;c;"))); } { StrVec v2; size_t count = v2.Split(_T("a,b,,c,"), _T(","), true); assert(count == 3 && v2.Find(_T("c")) == 2); ScopedMem<TCHAR> joined(v2.Join(_T(";"))); assert(str::Eq(joined, _T("a;b;c"))); ScopedMem<TCHAR> last(v2.Pop()); assert(v2.Count() == 2 && str::Eq(last, _T("c"))); } }
/* The html looks like: <li> <object type="text/sitemap"> <param name="Keyword" value="- operator"> <param name="Name" value="Subtraction Operator (-)"> <param name="Local" value="html/vsoprsubtract.htm"> <param name="Name" value="Subtraction Operator (-)"> <param name="Local" value="html/js56jsoprsubtract.htm"> </object> <ul> ... optional children ... </ul> <li> ... siblings ... */ static bool VisitChmIndexItem(EbookTocVisitor *visitor, HtmlElement *el, UINT cp, int level) { CrashIf(!el->NameIs("li")); el = el->GetChildByName("object"); if (!el) return false; StrVec references; ScopedMem<TCHAR> keyword, name; for (el = el->GetChildByName("param"); el; el = el->next) { if (!el->NameIs("param")) continue; ScopedMem<TCHAR> attrName(el->GetAttribute("name")); ScopedMem<TCHAR> attrVal(el->GetAttribute("value")); #ifdef UNICODE if (attrName && attrVal && cp != CP_CHM_DEFAULT) { ScopedMem<char> bytes(str::conv::ToCodePage(attrVal, CP_CHM_DEFAULT)); attrVal.Set(str::conv::FromCodePage(bytes, cp)); } #endif if (!attrName || !attrVal) /* ignore incomplete/unneeded <param> */; else if (str::EqI(attrName, _T("Keyword"))) keyword.Set(attrVal.StealData()); else if (str::EqI(attrName, _T("Name"))) { name.Set(attrVal.StealData()); // some CHM documents seem to use a lonely Name instead of Keyword if (!keyword) keyword.Set(str::Dup(name)); } else if (str::EqI(attrName, _T("Local")) && name) { // remove the ITS protocol and any filename references from the URLs if (str::Find(attrVal, _T("::/"))) attrVal.Set(str::Dup(str::Find(attrVal, _T("::/")) + 3)); references.Append(name.StealData()); references.Append(attrVal.StealData()); } } if (!keyword) return false; if (references.Count() == 2) { visitor->visit(keyword, references.At(1), level); return true; } visitor->visit(keyword, NULL, level); for (size_t i = 0; i < references.Count(); i += 2) { visitor->visit(references.At(i), references.At(i + 1), level + 1); } return true; }
bool StressTest::GoToNextFile() { for (;;) { while (filesToOpen.Count() > 0) { // test next file ScopedMem<TCHAR> path(filesToOpen.At(0)); filesToOpen.RemoveAt(0); if (!IsInRange(fileRanges, ++fileIndex)) continue; if (OpenFile(path)) return true; } if (dirsToVisit.Count() > 0) { // test next directory ScopedMem<TCHAR> path(dirsToVisit.At(0)); dirsToVisit.RemoveAt(0); OpenDir(path); continue; } if (--cycles <= 0) return false; // start next cycle if (file::Exists(basePath)) filesToOpen.Append(str::Dup(basePath)); else OpenDir(basePath); } }
// extract ComicBookInfo metadata // cf. http://code.google.com/p/comicbookinfo/ bool CbxEngineImpl::observe(const char *path, const char *value, json::DataType type) { if (json::Type_String == type && str::Eq(path, "/ComicBookInfo/1.0/title")) propTitle.Set(str::conv::FromUtf8(value)); else if (json::Type_Number == type && str::Eq(path, "/ComicBookInfo/1.0/publicationYear")) propDate.Set(str::Format(_T("%s/%d"), propDate ? propDate : _T(""), atoi(value))); else if (json::Type_Number == type && str::Eq(path, "/ComicBookInfo/1.0/publicationMonth")) propDate.Set(str::Format(_T("%d%s"), atoi(value), propDate ? propDate : _T(""))); else if (json::Type_String == type && str::Eq(path, "/appID")) propCreator.Set(str::conv::FromUtf8(value)); else if (json::Type_String == type && str::Eq(path, "/lastModified")) propModDate.Set(str::conv::FromUtf8(value)); else if (json::Type_String == type && str::Eq(path, "/X-summary")) propSummary.Set(str::conv::FromUtf8(value)); else if (str::StartsWith(path, "/ComicBookInfo/1.0/credits[")) { int idx = -1; const char *prop = str::Parse(path, "/ComicBookInfo/1.0/credits[%d]/", &idx); if (prop) { if (json::Type_String == type && str::Eq(prop, "person")) propAuthorTmp.Set(str::conv::FromUtf8(value)); else if (json::Type_Bool == type && str::Eq(prop, "primary") && propAuthorTmp && propAuthors.Find(propAuthorTmp) == -1) { propAuthors.Append(propAuthorTmp.StealData()); } } return true; } // stop parsing once we have all desired information return !propTitle || propAuthors.Count() == 0 || !propCreator || !propDate || str::FindChar(propDate, '/') <= propDate; }
bool ImageDirEngineImpl::LoadImageDir(const TCHAR *dirName) { fileName = str::Dup(dirName); fileExt = _T(""); ScopedMem<TCHAR> pattern(path::Join(dirName, _T("*"))); WIN32_FIND_DATA fdata; HANDLE hfind = FindFirstFile(pattern, &fdata); if (INVALID_HANDLE_VALUE == hfind) return false; do { if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (ImageEngine::IsSupportedFile(fdata.cFileName)) pageFileNames.Append(path::Join(dirName, fdata.cFileName)); } } while (FindNextFile(hfind, &fdata)); FindClose(hfind); if (pageFileNames.Count() == 0) return false; pageFileNames.SortNatural(); pages.AppendBlanks(pageFileNames.Count()); mediaboxes.AppendBlanks(pageFileNames.Count()); return true; }
static bool CollectStressTestSupportedFilesFromDirectory(const TCHAR *dirPath, const TCHAR *filter, StrVec& paths) { ScopedMem<TCHAR> pattern(path::Join(dirPath, _T("*"))); WIN32_FIND_DATA fdata; HANDLE hfind = FindFirstFile(pattern, &fdata); if (INVALID_HANDLE_VALUE == hfind) return false; do { if (!(fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { if (IsStressTestSupportedFile(fdata.cFileName, filter)) { paths.Append(path::Join(dirPath, fdata.cFileName)); } } } while (FindNextFile(hfind, &fdata)); FindClose(hfind); return paths.Count() > 0; }
bool CollectPathsFromDirectory(const TCHAR *pattern, StrVec& paths, bool dirsInsteadOfFiles) { ScopedMem<TCHAR> dirPath(path::GetDir(pattern)); WIN32_FIND_DATA fdata; HANDLE hfind = FindFirstFile(pattern, &fdata); if (INVALID_HANDLE_VALUE == hfind) return false; do { bool append = !dirsInsteadOfFiles; if ((fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) append = dirsInsteadOfFiles && !IsSpecialDir(fdata.cFileName); if (append) paths.Append(path::Join(dirPath, fdata.cFileName)); } while (FindNextFile(hfind, &fdata)); FindClose(hfind); return paths.Count() > 0; }
void StressTest::Start(const TCHAR *path, const TCHAR *filter, const TCHAR *ranges, int cycles) { srand((unsigned int)time(NULL)); GetSystemTime(&stressStartTime); // forbid entering sleep mode during tests SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); basePath.Set(str::Dup(path)); fileFilter.Set(filter && !str::Eq(filter, _T("*")) ? str::Dup(filter) : NULL); if (file::Exists(basePath)) { filesToOpen.Append(str::Dup(basePath)); ParsePageRanges(ranges, pageRanges); } else if (dir::Exists(basePath)) { OpenDir(basePath); ParsePageRanges(ranges, fileRanges); } else { // Note: dev only, don't translate ScopedMem<TCHAR> s(str::Format(_T("Path '%s' doesn't exist"), path)); ShowNotification(win, s, false /* autoDismiss */, true, NG_STRESS_TEST_SUMMARY); Finished(false); return; } this->cycles = cycles; if (pageRanges.Count() == 0) pageRanges.Append(PageRange()); if (fileRanges.Count() == 0) fileRanges.Append(PageRange()); if (GoToNextFile()) TickTimer(); else Finished(true); }
// see http://itexmac.sourceforge.net/pdfsync.html for the specification int Pdfsync::RebuildIndex() { size_t len; ScopedMem<char> data(file::ReadAll(syncfilepath, &len)); if (!data) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; // convert the file data into a list of zero-terminated strings str::TransChars(data, "\r\n", "\0\0"); // parse preamble (jobname and version marker) char *line = data; char *dataEnd = data + len; // replace star by spaces (TeX uses stars instead of spaces in filenames) str::TransChars(line, "*/", " \\"); ScopedMem<TCHAR> jobName(str::conv::FromAnsi(line)); jobName.Set(str::Join(jobName, _T(".tex"))); jobName.Set(PrependDir(jobName)); line = Advance0Line(line, dataEnd); UINT versionNumber = 0; if (!line || !str::Parse(line, "version %u", &versionNumber) || versionNumber != 1) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; // reset synchronizer database srcfiles.Reset(); lines.Reset(); points.Reset(); fileIndex.Reset(); sheetIndex.Reset(); Vec<size_t> filestack; UINT page = 1; sheetIndex.Append(0); // add the initial tex file to the source file stack filestack.Push(srcfiles.Count()); srcfiles.Append(jobName.StealData()); PdfsyncFileIndex findex = { 0 }; fileIndex.Append(findex); PdfsyncLine psline; PdfsyncPoint pspoint; // parse data UINT maxPageNo = engine->PageCount(); while ((line = Advance0Line(line, dataEnd))) { switch (*line) { case 'l': psline.file = filestack.Last(); if (str::Parse(line, "l %u %u %u", &psline.record, &psline.line, &psline.column)) lines.Append(psline); else if (str::Parse(line, "l %u %u", &psline.record, &psline.line)) { psline.column = 0; lines.Append(psline); } // else dbg("Bad 'l' line in the pdfsync file"); break; case 's': if (str::Parse(line, "s %u", &page)) sheetIndex.Append(points.Count()); // else dbg("Bad 's' line in the pdfsync file"); // if (0 == page || page > maxPageNo) // dbg("'s' line with invalid page number in the pdfsync file"); break; case 'p': pspoint.page = page; if (0 == page || page > maxPageNo) /* ignore point for invalid page number */; else if (str::Parse(line, "p %u %u %u", &pspoint.record, &pspoint.x, &pspoint.y)) points.Append(pspoint); else if (str::Parse(line, "p* %u %u %u", &pspoint.record, &pspoint.x, &pspoint.y)) points.Append(pspoint); // else dbg("Bad 'p' line in the pdfsync file"); break; case '(': { ScopedMem<TCHAR> filename(str::conv::FromAnsi(line + 1)); // if the filename contains quotes then remove them // TODO: this should never happen!? if (filename[0] == '"' && filename[str::Len(filename) - 1] == '"') filename.Set(str::DupN(filename + 1, str::Len(filename) - 2)); // undecorate the filepath: replace * by space and / by \ str::TransChars(filename, _T("*/"), _T(" \\")); // if the file name extension is not specified then add the suffix '.tex' if (str::IsEmpty(path::GetExt(filename))) filename.Set(str::Join(filename, _T(".tex"))); // ensure that the path is absolute if (PathIsRelative(filename)) filename.Set(PrependDir(filename)); filestack.Push(srcfiles.Count()); srcfiles.Append(filename.StealData()); findex.start = findex.end = lines.Count(); fileIndex.Append(findex); } break; case ')': if (filestack.Count() > 1) fileIndex.At(filestack.Pop()).end = lines.Count(); // else dbg("Unbalanced ')' line in the pdfsync file"); break; default: // dbg("Ignoring invalid pdfsync line starting with '%c'", *line); break; } } fileIndex.At(0).end = lines.Count(); assert(filestack.Count() == 1); return Synchronizer::RebuildIndex(); }