1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File : SALOMEDSImpl_AttributeTableOfInteger.cxx
24 // Author : Michael Ponikarov
27 #include "SALOMEDSImpl_AttributeTableOfInteger.hxx"
32 #define SEPARATOR '\1'
33 typedef std::map<int, int>::const_iterator MI;
35 static std::string getUnit(std::string theString)
37 std::string aString(theString);
38 int aPos = aString.find(SEPARATOR);
39 if(aPos <= 0 || aPos == aString.size() ) return std::string();
40 return aString.substr(aPos+1, aString.size());
43 static std::string getTitle(std::string theString)
45 std::string aString(theString);
46 int aPos = aString.find(SEPARATOR);
47 if(aPos < 1) return aString;
48 if(aPos == 0) return std::string();
49 return aString.substr(0, aPos);
52 const std::string& SALOMEDSImpl_AttributeTableOfInteger::GetID()
54 static std::string SALOMEDSImpl_AttributeTableOfIntegerID ("128371A0-8F52-11d6-A8A3-0001021E8C7F");
55 return SALOMEDSImpl_AttributeTableOfIntegerID;
58 SALOMEDSImpl_AttributeTableOfInteger* SALOMEDSImpl_AttributeTableOfInteger::Set(const DF_Label& label)
60 SALOMEDSImpl_AttributeTableOfInteger* A = NULL;
61 if (!(A=(SALOMEDSImpl_AttributeTableOfInteger*)label.FindAttribute(SALOMEDSImpl_AttributeTableOfInteger::GetID()))) {
62 A = new SALOMEDSImpl_AttributeTableOfInteger();
63 label.AddAttribute(A);
68 SALOMEDSImpl_AttributeTableOfInteger::SALOMEDSImpl_AttributeTableOfInteger()
69 :SALOMEDSImpl_GenericAttribute("AttributeTableOfInteger")
75 void SALOMEDSImpl_AttributeTableOfInteger::SetNbColumns(const int theNbColumns)
80 std::map<int, int> aMap;
84 for(MI p = aMap.begin(); p != aMap.end(); p++) {
85 int aRow = (int)(p->first/myNbColumns) + 1;
86 int aCol = (int)(p->first - myNbColumns*(aRow-1));
87 if(aCol == 0) { aCol = myNbColumns; aRow--; }
88 if(aCol > theNbColumns) continue;
89 int aKey = (aRow-1)*theNbColumns+aCol;
90 myTable[aKey] = p->second;
93 myNbColumns = theNbColumns;
95 while (myCols.size() < myNbColumns) { // append empty columns titles
96 myCols.push_back(std::string(""));
99 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
102 void SALOMEDSImpl_AttributeTableOfInteger::SetTitle(const std::string& theTitle)
108 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
111 std::string SALOMEDSImpl_AttributeTableOfInteger::GetTitle() const
116 void SALOMEDSImpl_AttributeTableOfInteger::SetRowData(const int theRow,
117 const std::vector<int>& theData)
120 if(theData.size() > myNbColumns) SetNbColumns(theData.size());
124 while (myRows.size() < theRow) { // append new row titles
125 myRows.push_back(std::string(""));
128 int i, aShift = (theRow-1)*myNbColumns, aLength = theData.size();
129 for(i = 1; i <= aLength; i++) {
130 myTable[aShift + i] = theData[i-1];
133 if(theRow > myNbRows) myNbRows = theRow;
135 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
138 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetRowData(const int theRow)
140 std::vector<int> aSeq;
141 int i, aShift = (theRow-1)*myNbColumns;
142 for(i = 1; i <= myNbColumns; i++) {
143 if(myTable.find(aShift+i) != myTable.end())
144 aSeq.push_back(myTable[aShift+i]);
152 void SALOMEDSImpl_AttributeTableOfInteger::SetRowTitle(const int theRow,
153 const std::string& theTitle)
157 std::string aTitle(theTitle), aUnit = GetRowUnit(theRow);
162 myRows[theRow-1] = aTitle;
164 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
167 void SALOMEDSImpl_AttributeTableOfInteger::SetRowUnit(const int theRow,
168 const std::string& theUnit)
172 std::string aTitle = GetRowTitle(theRow);
176 myRows[theRow-1] = aTitle;
178 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
181 void SALOMEDSImpl_AttributeTableOfInteger::SetRowUnits(const std::vector<std::string>& theUnits)
183 if (theUnits.size() != GetNbRows()) throw DFexception("Invalid number of rows");
184 int aLength = theUnits.size(), i;
185 for(i = 1; i <= aLength; i++) SetRowUnit(i, theUnits[i-1]);
187 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
190 std::vector<std::string> SALOMEDSImpl_AttributeTableOfInteger::GetRowUnits()
192 std::vector<std::string> aSeq;
193 int aLength = myRows.size(), i;
194 for(i=0; i<aLength; i++) aSeq.push_back(getUnit(myRows[i]));
198 void SALOMEDSImpl_AttributeTableOfInteger::SetRowTitles(const std::vector<std::string>& theTitles)
200 if (theTitles.size() != GetNbRows()) throw DFexception("Invalid number of rows");
201 int aLength = theTitles.size(), i;
202 for(i = 1; i <= aLength; i++) SetRowTitle(i, theTitles[i-1]);
204 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
207 std::vector<std::string> SALOMEDSImpl_AttributeTableOfInteger::GetRowTitles()
209 std::vector<std::string> aSeq;
210 int aLength = myRows.size(), i;
211 for(i=0; i<aLength; i++) aSeq.push_back(getTitle(myRows[i]));
215 std::string SALOMEDSImpl_AttributeTableOfInteger::GetRowTitle(const int theRow) const
217 return getTitle(myRows[theRow-1]);
220 std::string SALOMEDSImpl_AttributeTableOfInteger::GetRowUnit(const int theRow) const
222 return getUnit(myRows[theRow-1]);
225 void SALOMEDSImpl_AttributeTableOfInteger::SetColumnData(const int theColumn,
226 const std::vector<int>& theData)
229 if(theColumn > myNbColumns) SetNbColumns(theColumn);
233 int i, aLength = theData.size();
234 for(i = 1; i <= aLength; i++) {
235 myTable[myNbColumns*(i-1)+theColumn] = theData[i-1];
238 if(aLength > myNbRows) {
240 while (myRows.size() < myNbRows) { // append empty row titles
241 myRows.push_back(std::string(""));
245 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
249 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetColumnData(const int theColumn)
251 std::vector<int> aSeq;
253 for(i = 1; i <= myNbRows; i++) {
254 anIndex = myNbColumns*(i-1) + theColumn;
255 if(myTable.find(anIndex) != myTable.end())
256 aSeq.push_back(myTable[anIndex]);
264 void SALOMEDSImpl_AttributeTableOfInteger::SetColumnTitle(const int theColumn,
265 const std::string& theTitle)
269 while(myCols.size() < theColumn) myCols.push_back(std::string(""));
270 myCols[theColumn-1] = theTitle;
272 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
275 std::string SALOMEDSImpl_AttributeTableOfInteger::GetColumnTitle(const int theColumn) const
277 if(myCols.empty()) return "";
278 if(myCols.size() < theColumn) return "";
279 return myCols[theColumn-1];
282 void SALOMEDSImpl_AttributeTableOfInteger::SetColumnTitles(const std::vector<std::string>& theTitles)
284 if (theTitles.size() != myNbColumns) throw DFexception("Invalid number of columns");
285 int aLength = theTitles.size(), i;
286 for(i = 0; i < aLength; i++) myCols[i] = theTitles[i];
288 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
291 std::vector<std::string> SALOMEDSImpl_AttributeTableOfInteger::GetColumnTitles()
293 std::vector<std::string> aSeq;
294 int aLength = myCols.size(), i;
295 for(i=0; i<aLength; i++) aSeq.push_back(myCols[i]);
299 int SALOMEDSImpl_AttributeTableOfInteger::GetNbRows() const
304 int SALOMEDSImpl_AttributeTableOfInteger::GetNbColumns() const
309 void SALOMEDSImpl_AttributeTableOfInteger::PutValue(const int theValue,
315 if(theColumn > myNbColumns) SetNbColumns(theColumn);
317 int anIndex = (theRow-1)*myNbColumns + theColumn;
318 myTable[anIndex] = theValue;
320 if(theRow > myNbRows) {
321 while (myRows.size() < theRow) { // append empty row titles
322 myRows.push_back(std::string(""));
327 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
330 bool SALOMEDSImpl_AttributeTableOfInteger::HasValue(const int theRow,
333 if(theRow > myNbRows || theRow < 1) return false;
334 if(theColumn > myNbColumns || theColumn < 1) return false;
335 int anIndex = (theRow-1)*myNbColumns + theColumn;
336 return (myTable.find(anIndex) != myTable.end());
339 int SALOMEDSImpl_AttributeTableOfInteger::GetValue(const int theRow,
342 if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
343 if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
345 int anIndex = (theRow-1)*myNbColumns + theColumn;
346 if(myTable.find(anIndex) != myTable.end()) return myTable[anIndex];
348 throw DFexception("Invalid cell index");
352 void SALOMEDSImpl_AttributeTableOfInteger::RemoveValue(const int theRow, const int theColumn)
355 if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
356 if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
358 int anIndex = (theRow-1)*myNbColumns + theColumn;
359 if (myTable.find(anIndex) != myTable.end()) {
361 myTable.erase(anIndex);
362 SetModifyFlag(); // table is modified
366 const std::string& SALOMEDSImpl_AttributeTableOfInteger::ID() const
371 void SALOMEDSImpl_AttributeTableOfInteger::Restore(DF_Attribute* with)
374 SALOMEDSImpl_AttributeTableOfInteger* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfInteger*>(with);
375 if(!aTable) throw DFexception("Can't Restore from a null attribute");
381 myTable = aTable->myTable;
382 myNbRows = aTable->myNbRows;
383 myNbColumns = aTable->myNbColumns;
384 myTitle = aTable->myTitle;
386 for(anIndex = 1; anIndex <= aTable->GetNbRows();anIndex++)
387 myRows.push_back(aTable->GetRowTitle(anIndex));
389 for(anIndex = 1; anIndex <= aTable->GetNbColumns(); anIndex++)
390 myCols.push_back(aTable->GetColumnTitle(anIndex));
393 DF_Attribute* SALOMEDSImpl_AttributeTableOfInteger::NewEmpty() const
395 return new SALOMEDSImpl_AttributeTableOfInteger();
398 void SALOMEDSImpl_AttributeTableOfInteger::Paste(DF_Attribute* into)
401 SALOMEDSImpl_AttributeTableOfInteger* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfInteger*>(into);
402 if(!aTable) throw DFexception("Can't Paste into a null attribute");
404 aTable->myTable.clear();
405 aTable->myCols.clear();
406 aTable->myRows.clear();
408 aTable->myTable = myTable;
409 aTable->myTitle = myTitle;
410 aTable->myNbRows = myNbRows;
411 aTable->myNbColumns = myNbColumns;
413 for(anIndex = 1; anIndex <= GetNbRows();anIndex++)
414 aTable->myRows.push_back(GetRowTitle(anIndex));
415 for(anIndex = 1; anIndex <= GetNbColumns(); anIndex++)
416 aTable->myCols.push_back(GetColumnTitle(anIndex));
419 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetSetRowIndices(const int theRow)
421 std::vector<int> aSeq;
423 int i, aShift = myNbColumns*(theRow-1);
424 for(i = 1; i <= myNbColumns; i++) {
425 if(myTable.find(aShift + i) != myTable.end()) aSeq.push_back(i);
431 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::GetSetColumnIndices(const int theColumn)
433 std::vector<int> aSeq;
436 for(i = 1; i <= myNbRows; i++) {
437 anIndex = myNbColumns*(i-1)+theColumn;
438 if(myTable.find(anIndex) != myTable.end()) aSeq.push_back(i);
444 std::string SALOMEDSImpl_AttributeTableOfInteger::Save()
447 char* buffer = new char[1024];
452 sprintf(buffer, "%d\n", l);
455 aString += myTitle[i];
460 sprintf(buffer, "%d\n", myNbRows);
464 for(i=0; i<myNbRows; i++) {
465 l = myRows[i].size();
466 sprintf(buffer, "%d\n", l);
469 aString += myRows[i][j];
475 sprintf(buffer, "%d\n", myNbColumns);
479 for(i=0; i<myNbColumns; i++) {
480 l = myCols[i].size();
481 sprintf(buffer, "%d\n", l);
484 aString += myCols[i][j];
489 //Store the table values
491 sprintf(buffer, "%d\n", l);
493 for(MI p = myTable.begin(); p != myTable.end(); p++) {
494 sprintf(buffer, "%d\n%d\n", p->first, p->second);
502 void SALOMEDSImpl_AttributeTableOfInteger::Load(const std::string& value)
504 std::vector<std::string> v;
505 int i, j, l, pos, aSize = (int)value.size();
506 for(i = 0, pos = 0; i<aSize; i++) {
507 if(value[i] == '\n') {
508 v.push_back(value.substr(pos, i-pos));
519 l = strtol(v[pos++].c_str(), NULL, 10);
521 myTitle = std::string(l, 0);
523 myTitle[i] = v[pos++][0];
527 myNbRows = strtol(v[pos++].c_str(), NULL, 10);
531 for(i=1; i<=myNbRows; i++) {
532 l = strtol(v[pos++].c_str(), NULL, 10);
533 aStr = std::string(l,0);
535 aStr[j] = v[pos++][0];
537 myRows.push_back(aStr);
541 myNbColumns = strtol(v[pos++].c_str(), NULL, 10);
545 for(i=1; i<=myNbColumns; i++) {
546 l = strtol(v[pos++].c_str(), NULL, 10);
547 aStr = std::string(l,0);
549 aStr[j] = v[pos++][0];
551 myCols.push_back(aStr);
554 //Restore the table values
555 l = strtol(v[pos++].c_str(), NULL, 10);
557 for(i=1; i<=l; i++) {
558 int aKey = strtol(v[pos++].c_str(), NULL, 10);
559 int aValue = strtol(v[pos++].c_str(), NULL, 10);
560 myTable[aKey] = aValue;
564 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
567 std::vector<int> result;
568 if ( theRow > 0 && theRow <= myNbRows ) {
569 std::vector<int> indices( myNbColumns );
571 for ( int i = 0; i < myNbColumns; i++ ) {
572 if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
573 indices[cnt++] = i+1;
578 TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theRow, true );
579 std::stable_sort( indices.begin(), indices.end(), sorter );
581 if ( sortPolicy == EmptyIgnore ) {
582 std::vector<int> other( myNbColumns );
584 for( int i = 0; i < myNbColumns; i++ )
585 other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
590 for ( int col = 0; col < indices.size(); col++ ) {
591 int idx = indices[col];
592 if ( col+1 == idx ) continue;
593 SwapCells(theRow, col+1, theRow, idx);
595 for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
596 if ( indices[i] == col+1 ) idx1 = i;
599 // no need for SetModifyFlag(), since it is done by SwapCells()
604 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
607 std::vector<int> result;
608 if ( theColumn > 0 && theColumn <= myNbColumns ) {
609 std::vector<int> indices( myNbRows );
611 for ( int i = 0; i < myNbRows; i++ ) {
612 if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
613 indices[cnt++] = i+1;
618 TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theColumn, false );
619 std::stable_sort( indices.begin(), indices.end(), sorter );
621 if ( sortPolicy == EmptyIgnore ) {
622 std::vector<int> other( myNbRows );
624 for( int i = 0; i < myNbRows; i++ )
625 other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
630 for ( int row = 0; row < indices.size(); row++ ) {
631 int idx = indices[row];
632 if ( row+1 == idx ) continue;
633 SwapCells(row+1, theColumn, idx, theColumn);
635 for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
636 if ( indices[i] == row+1 ) idx1 = i;
639 // no need for SetModifyFlag(), since it is done by SwapCells()
644 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortByRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
647 std::vector<int> result;
648 if ( theRow > 0 && theRow <= myNbRows ) {
649 std::vector<int> indices( myNbColumns );
651 for ( int i = 0; i < myNbColumns; i++ ) {
652 if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
653 indices[cnt++] = i+1;
658 TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theRow, true );
659 std::stable_sort( indices.begin(), indices.end(), sorter );
661 if ( sortPolicy == EmptyIgnore ) {
662 std::vector<int> other( myNbColumns );
664 for( int i = 0; i < myNbColumns; i++ )
665 other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
670 for ( int col = 0; col < indices.size(); col++ ) {
671 int idx = indices[col];
672 if ( col+1 == idx ) continue;
673 SwapColumns(col+1, idx);
675 for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
676 if ( indices[i] == col+1 ) idx1 = i;
679 // no need for SetModifyFlag(), since it is done by SwapColumns()
684 std::vector<int> SALOMEDSImpl_AttributeTableOfInteger::SortByColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
687 std::vector<int> result;
688 if ( theColumn > 0 && theColumn <= myNbColumns ) {
689 std::vector<int> indices( myNbRows );
691 for ( int i = 0; i < myNbRows; i++ ) {
692 if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
693 indices[cnt++] = i+1;
698 TableSorter<SALOMEDSImpl_AttributeTableOfInteger> sorter( this, sortOrder, sortPolicy, theColumn, false );
699 std::stable_sort( indices.begin(), indices.end(), sorter );
701 if ( sortPolicy == EmptyIgnore ) {
702 std::vector<int> other( myNbRows );
704 for( int i = 0; i < myNbRows; i++ )
705 other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
710 for ( int row = 0; row < indices.size(); row++ ) {
711 int idx = indices[row];
712 if ( row+1 == idx ) continue;
713 SwapRows(row+1, idx);
715 for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
716 if ( indices[i] == row+1 ) idx1 = i;
719 // no need for SetModifyFlag(), since it is done by SwapRows()
724 void SALOMEDSImpl_AttributeTableOfInteger::SwapCells(const int theRow1, const int theColumn1,
725 const int theRow2, const int theColumn2)
728 if (theRow1 > myNbRows || theRow1 < 1) throw DFexception("Invalid cell index");
729 if (theRow2 > myNbRows || theRow2 < 1) throw DFexception("Invalid cell index");
730 if (theColumn1 > myNbColumns || theColumn1 < 1) throw DFexception("Invalid cell index");
731 if (theColumn2 > myNbColumns || theColumn2 < 1) throw DFexception("Invalid cell index");
733 int anIndex1 = (theRow1-1)*myNbColumns + theColumn1;
734 int anIndex2 = (theRow2-1)*myNbColumns + theColumn2;
736 bool hasValue1 = myTable.find(anIndex1) != myTable.end();
737 bool hasValue2 = myTable.find(anIndex2) != myTable.end();
739 if (!hasValue1 && !hasValue2) return; // nothing changed
741 int value1 = hasValue1 ? myTable[anIndex1] : 0;
742 int value2 = hasValue2 ? myTable[anIndex2] : 0;
744 if (hasValue1 && hasValue2 && value1 == value2) return; // nothing changed
746 if (hasValue1) myTable[anIndex2] = value1;
747 else myTable.erase(anIndex2);
748 if (hasValue2) myTable[anIndex1] = value2;
749 else myTable.erase(anIndex1);
751 SetModifyFlag(); // table is modified
754 void SALOMEDSImpl_AttributeTableOfInteger::SwapRows(const int theRow1, const int theRow2)
757 for (int i = 1; i <= myNbColumns; i++)
758 SwapCells(theRow1, i, theRow2, i);
760 std::string tmp = myRows[theRow1-1];
761 myRows[theRow1-1] = myRows[theRow2-1];
762 myRows[theRow2-1] = tmp;
763 // no need for SetModifyFlag(), since it is done by SwapCells()
766 void SALOMEDSImpl_AttributeTableOfInteger::SwapColumns(const int theColumn1, const int theColumn2)
769 for (int i = 1; i <= myNbRows; i++)
770 SwapCells(i, theColumn1, i, theColumn2);
771 // swap column titles
772 std::string tmp = myCols[theColumn1-1];
773 myCols[theColumn1-1] = myCols[theColumn2-1];
774 myCols[theColumn2-1] = tmp;
775 // no need for SetModifyFlag(), since it is done by SwapCells()