char lineSeparator = '\n' char fieldSeparator = ';' Regexp reSep = regexp (fieldSeparator "|" lineSeparator "") Array textToArray (Buffer buf, int &iLine) { int pos = 0 int iCol = 0 iLine = 0 // add line separator to make sure we find all lines buf += lineSeparator Array result = create(10000, 8) bool lineHasValue = false while (search (reSep, buf, pos)) { int iStart = start 0 int iEnd = end 0 if (iStart > 0) { string val = buf[pos: iStart+pos-1] put (result, val, iLine, iCol) lineHasValue = true } else { put (result, "", iLine, iCol) } // assume our separators are only one character! if (buf [iStart + pos] == fieldSeparator) iCol++ if (buf [iStart + pos] == lineSeparator ) { if (lineHasValue) iLine ++ iCol = 0 lineHasValue = false } // print "Parsed " iCol ":" iLine " at " pos "\n" pos += iEnd + 1 } return result } Buffer bufKey = create() Buffer makeKey (Array ar, int iLine, int arFields[]) { bufKey = "" int i; for (i = 0; i < sizeof arFields; i++) { bufKey += ((get (ar, iLine, arFields[i])) string) bufKey += "_" } return bufKey } // this function will return a subset of the array, counting all lines // that have unique values in the columns in 'arFields'. Example: For the // above Link array, doing arFields[] = { 0, 4 } = source module, target module // you will get an array: // 5, /Base/HRD, /Base/SES // 5, /Base/SRD, /Base/SES Array SelectArray(Array ar, int iMax, int arFields[], int &iCount) { int maxIndex = 0 Skip skKeyIndex = createString() // Key = field key Value = index in array Array result = create (100, 5) int i; for (i = 0; i < iMax; i++) { Buffer bufKey = makeKey(ar, i, arFields) int iArrayLine = 0 // key is not yet in array? create a new line in the array if (!find(skKeyIndex, tempStringOf bufKey, iArrayLine)) { put (skKeyIndex, stringOf bufKey, maxIndex) // put the key to the skip put (result, 1, maxIndex, 0) // put the count at index 0 // now copy the fields int j; for (j = 0; j < sizeof arFields; j++) { string sVal = (get (ar, i, arFields[j])) string put (result, sVal, maxIndex, j+1) } maxIndex++ } else { // just increase the count int iCount = (get(result, iArrayLine, 0)) int put (result, iCount+1, iArrayLine, 0) } } delete skKeyIndex iCount = maxIndex return result } string strVal (Array ar, int y, int x) { string s = (get (ar, y, x)) string return s } int intVal (Array ar, int y, int x) { int i = (get (ar, y, x)) int return i } // string sText = readFile (...) // use your output file instead // Test text string sText = "/Base/HRD;;16;/Base/DOORS Links;;/Base/SES;;2;false /Base/HRD;;16;/Base/DOORS Links;;/Base/SES;;3;false /Base/HRD;;17;/Base/DOORS Links;;/Base/SES;;2;false /Base/HRD;;17;/Base/DOORS Links;;/Base/SES;1.0;3;false /Base/HRD;;18;/Base/DOORS Links;;/Base/SES;;2;false /Base/HRD;;19;/Base/DOORS Links;;/Base/SES;;1;false /Base/SRD;;19;/Base/DOORS Links;;/Base/SES;;2;false /Base/SRD;;19;/Base/DOORS Links;;/Base/SES;;4;false /Base/SRD;;96;/Base/DOORS Links;;/Base/SES;;1;false /Base/SRD;;98;/Base/DOORS Links;;/Base/SES;;1;false /Base/SRD;;99;/Base/DOORS Links;;/Base/SES;;1;false " // Now we have the file in the array --> For big files you need to load only a part of the file // and process that separately, you can also process the file directly for large files int iLinkCount = 0 Buffer buf = create(); buf = sText Array ar = textToArray (buf, iLinkCount) print "We have " iLinkCount " links ...!\n" // Now make your picture int iSrcTgtPairs = 0 int iFields[] = {0,5 } // Source Module, Target Module Array arSrcTgt = SelectArray(ar, iLinkCount, iFields, iSrcTgtPairs) print "We have " iSrcTgtPairs " source / target pairs:\n" int i; for (i = 0; i < iSrcTgtPairs; i++) { print strVal(arSrcTgt, i, 1) " -> " strVal(arSrcTgt, i, 2) " Count: " intVal(arSrcTgt, i, 0) "\n" }