📄 staf.cpp
字号:
/*****************************************************************************//* Software Testing Automation Framework (STAF) *//* (C) Copyright IBM Corp. 2001, 2004 *//* *//* This software is licensed under the Common Public License (CPL) V1.0. *//*****************************************************************************/#include "STAF.h"#include "STAFString.h"#include "STAF_iostream.h"#include "STAFUtil.h"#include <stdlib.h>#include <list>#include <vector>// Debugging flagbool gDebug = false;// Print Modeconst unsigned int kPMAuto = 0;const unsigned int kPMVerbose = 1;const unsigned int kPMRaw = 2;bool gPrintModeLocked = false;unsigned int gPrintMode = kPMAuto;unsigned int gUnmarshallingFlags = kSTAFUnmarshallingDefaults;bool gPrintQuotes = false;// Indentationunsigned int gIndentDelta = 2;STAFString gSpaces(" " // 40 Spaces " "); // times 2STAFString gListIndent("[");STAFString gListOutdent("]");STAFString gMapIndent("{");STAFString gMapOutdent("}");// SeparatorsSTAFString gEntrySeparator("");STAFString gMapKeySeparator(": ");// Table dataSTAFString gHyphens("----------------------------------------" // 40 Hyphens "----------------------------------------"); // times 2STAFString gColumnSeparator(" ");STAFString gCRLF = STAFString(kUTF8_CR) + STAFString(kUTF8_LF);STAFString gCR = STAFString(kUTF8_CR);STAFString gLF = STAFString(kUTF8_LF);STAFString gTab = STAFString(kUTF8_TAB);STAFString gSpace(" ");bool gPrintTables = true;bool gStrictTables = true;unsigned int gMaxTableWidth = 79;unsigned int gMaxLinesPerTableRecord = 20;struct TableColumn{ STAFString key; STAFString header; STAFString longHeader; STAFString shortHeader; unsigned int longHeaderLength; unsigned int shortHeaderLength; unsigned int maxValueLength; unsigned int minimumWidth; unsigned int maximumWidth; unsigned int width; unsigned int currTestWidth; unsigned int maxTestWidth; unsigned int bestTestWidth; // sizeCounts[x] = # records with size 'x' std::vector<unsigned int> sizeCounts; // cwLineCounts[x][y] = # records that fit on 'y' lines with 'x' width std::vector<std::vector<unsigned int> > cwLineCounts; // cwLineCountSums[x][y] = # records that fit on <= 'y' lines with 'x' width std::vector<std::vector<unsigned int> > cwLineCountSums; // cwLineSums[x] = # lines used to display all column data using 'x' width std::vector<unsigned int> cwLineSums;};typedef std::vector<TableColumn> TableColumnList;inline unsigned int cwLineCountsIndex(unsigned int columnWidth, unsigned int lineNumber){ return (columnWidth * (gMaxLinesPerTableRecord + 1)) + lineNumber;}inline unsigned int cwLinesNeeded(TableColumnList::iterator &clIter, unsigned int widthToCheck, unsigned int numItems){ for (unsigned int line = 0; line < gMaxLinesPerTableRecord; ++line) { if (clIter->cwLineCountSums[widthToCheck - 1][line] == numItems) return line + 1; } return gMaxLinesPerTableRecord + 1;}bool incColumnTestWidths(TableColumnList &columnList, unsigned int remainingTableWidth){ bool noMoreArrangements = true; int index = 0; // First, start from the next to last index and go back towards the // beginning of the list looking for loop indices that have maxed out. // // 'index' will be set to the index of the innermost column which didn't // max out. for (index = columnList.size() - 2; index >= 0; --index) { TableColumn &currCol = columnList[index]; // Set the column to the next increment that decreases line counts // // XXX: This algorithm could use a little extra help. For example, // it might want to take header lengths into accounts, so that // you might get a full header length, even though the data // won't show up any better. This probably needs to be hooked // into the same data/algorithm that "eval" uses. unsigned int currMax = STAF_MIN(currCol.maxTestWidth, currCol.maximumWidth); unsigned int currLineSums = currCol.cwLineSums[currCol.currTestWidth - 1]; while ((currCol.currTestWidth <= currMax) && (currCol.cwLineSums[currCol.currTestWidth - 1] == currLineSums)) { ++currCol.currTestWidth; } // If this column has maxed out, reset its curr counter to the minimum. // It's max counter is set farther down. // // If it hasn't maxed out, then terminate the loop. if (currCol.currTestWidth > currMax) { currCol.currTestWidth = currCol.minimumWidth; } else { noMoreArrangements = false; break; } } if (noMoreArrangements) return false; // Now, calculate how much width is taken up by the columns that didn't // max out unsigned int currWidth = 0; int i = 0; for (i = 0; i <= index; ++i) currWidth += columnList[i].currTestWidth - columnList[i].minimumWidth; // Next, set the maxed out columns new max values for (i = index + 1; i < (columnList.size() - 1); ++i) { columnList[i].maxTestWidth = columnList[i].minimumWidth + remainingTableWidth - currWidth; } // Finally update the last column // // Note: The last column is not "free". I.e., it's value is completely // dependent on the values of the other columns. // // XXX: Might want to look at being able to set which column is the // dependent column, as currently, the last column can sometimes get // "odd" values, including settings greater than its maximum necessary // width. columnList[i].currTestWidth = columnList[i].minimumWidth + remainingTableWidth - currWidth; return true;}unsigned int evalColumnWidths(TableColumnList &columnList){ if (gDebug) cout << "Evaluating (curr/min/tmax/max): "; unsigned int bestEval = 0; unsigned int currEval = 0; for (unsigned int i = 0; i < columnList.size(); ++i) { if (gDebug) { cout << columnList[i].currTestWidth << "/" << columnList[i].minimumWidth << "/" << columnList[i].maxTestWidth << "/" << columnList[i].maximumWidth << " "; } bestEval += columnList[i].cwLineSums[columnList[i].bestTestWidth - 1]; currEval += columnList[i].cwLineSums[columnList[i].currTestWidth - 1]; } if (gDebug) cout << endl; if (bestEval > currEval) { for (unsigned int j = 0; j < columnList.size(); ++j) columnList[j].bestTestWidth = columnList[j].currTestWidth; } return 1;}void dumpTableColumnList(TableColumnList &tableColumnList){ for (TableColumnList::iterator iter = tableColumnList.begin(); iter != tableColumnList.end(); ++iter) { cout << "Key : " << iter->key << endl; cout << "Header : " << iter->header << endl; cout << "Long header : " << iter->longHeader << endl; cout << "Short header : " << iter->shortHeader << endl; cout << "Long Header Length : " << iter->longHeaderLength << endl; cout << "Short Header Length: " << iter->shortHeaderLength << endl; cout << "Max Value Length : " << iter->maxValueLength << endl; cout << "Minimum width : " << iter->minimumWidth << endl; cout << "Maximum width : " << iter->maximumWidth << endl; cout << "Width : " << iter->width << endl; unsigned int maxSizeCount = gMaxTableWidth * gMaxLinesPerTableRecord; for (unsigned int i = 0; i <= maxSizeCount; ++i) { if (iter->sizeCounts[i]) cout << "Size " << i << ": " << iter->sizeCounts[i] << endl; } for (unsigned int j = 0; j < gMaxTableWidth; ++j) { cout << "Lines need for column width " << (j + 1) << ": " << iter->cwLineSums[j] << endl; } for (unsigned int x = 0; x < gMaxTableWidth + 1; ++x) { cout << "Column width: " << (x + 1) << endl << "Number of lines/records/total-records: " << endl; for (unsigned int y = 0; y < gMaxLinesPerTableRecord + 1; ++y) { cout << (y + 1) << "/" << iter->cwLineCounts[x][y] << "/" << iter->cwLineCountSums[x][y] << " "; } cout << endl; } } cout << endl;}inline void pauseIt(STAFString message = "Enter a number: "){ cout << message << endl; unsigned int a = 0; cin >> a;}// General constantsSTAFString sMapClassKey("staf-map-class-name");STAFString sKey("key");STAFString sDisplayName("display-name");STAFString sShortDisplayName("display-short-name");STAFString sColon(kUTF8_COLON);STAFString sSingleQuote(kUTF8_SQUOTE);STAFString sDoubleQuote(kUTF8_DQUOTE);STAFString sEscapedSingleQuote("\\'");STAFString massageArgument(char *theArg){ STAFString arg(theArg); if (getenv("STAF_OLDCLI") != 0) return arg; if (arg.find(kUTF8_SPACE) != STAFString::kNPos) { if ((arg.find(sDoubleQuote) != 0) || (arg.findLastOf(sDoubleQuote, STAFString::kNPos, STAFString::kChar) != arg.length(STAFString::kChar))) { arg = sColon + STAFString(arg.length(STAFString::kChar)) + sColon + arg; } } return arg;}STAFString quoteString(const STAFString &input){ if (!gPrintQuotes) return input; if (input.find(sSingleQuote) == STAFString::kNPos) return STAFString(sSingleQuote) + input + STAFString(sSingleQuote); if (input.find(sDoubleQuote) == STAFString::kNPos) return STAFString(sDoubleQuote) + input + STAFString(sDoubleQuote); return STAFString(sSingleQuote) + input.replace(sSingleQuote, sEscapedSingleQuote) + STAFString(sSingleQuote);}void printVerbose(const STAFObjectPtr &objPtr, const STAFObjectPtr &context, unsigned int indentLevel){ switch (objPtr->type()) { case kSTAFListObject: { cout << gListIndent; ++indentLevel; if (objPtr->size() > 0) cout << endl; // Print out each object for (STAFObjectIteratorPtr iterPtr = objPtr->iterate(); iterPtr->hasNext();) { STAFObjectPtr thisObj = iterPtr->next(); if ((thisObj->type() == kSTAFListObject) || (thisObj->type() == kSTAFMapObject) || (thisObj->type() == kSTAFMarshallingContextObject)) { cout << gSpaces.subString(0, indentLevel * gIndentDelta); printVerbose(thisObj, context, indentLevel); } else { cout << gSpaces.subString(0, indentLevel * gIndentDelta); if (thisObj->type() == kSTAFNoneObject) cout << thisObj->asString(); else cout << thisObj->asString(); } if (iterPtr->hasNext()) cout << gEntrySeparator; cout << endl; } --indentLevel; if (objPtr->size() > 0) cout << gSpaces.subString(0, indentLevel * gIndentDelta); cout << gListOutdent; break; } case kSTAFMapObject: { cout << gMapIndent; ++indentLevel;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -