1 // Copyright (C) 2007-2010 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.
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_AttributeTableOfString.cxx
24 // Author : Sergey Ruin
27 #include "SALOMEDSImpl_AttributeTableOfString.hxx"
32 #define SEPARATOR '\1'
33 typedef std::map<int, std::string>::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_AttributeTableOfString::GetID()
54 static std::string SALOMEDSImpl_AttributeTableOfStringID ("128371A4-8F52-11d6-A8A3-0001021E8C7F");
55 return SALOMEDSImpl_AttributeTableOfStringID;
58 SALOMEDSImpl_AttributeTableOfString* SALOMEDSImpl_AttributeTableOfString::Set(const DF_Label& label)
60 SALOMEDSImpl_AttributeTableOfString* A = NULL;
61 if (!(A=(SALOMEDSImpl_AttributeTableOfString*)label.FindAttribute(SALOMEDSImpl_AttributeTableOfString::GetID()))) {
62 A = new SALOMEDSImpl_AttributeTableOfString();
63 label.AddAttribute(A);
68 SALOMEDSImpl_AttributeTableOfString::SALOMEDSImpl_AttributeTableOfString()
69 :SALOMEDSImpl_GenericAttribute("AttributeTableOfString")
75 void SALOMEDSImpl_AttributeTableOfString::SetNbColumns(const int theNbColumns)
80 std::map<int, std::string> 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_AttributeTableOfString::SetRowTitle(const int theRow,
103 const std::string& theTitle)
107 std::string aTitle(theTitle), aUnit = GetRowUnit(theRow);
112 myRows[theRow-1] = aTitle;
114 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
117 void SALOMEDSImpl_AttributeTableOfString::SetRowUnit(const int theRow,
118 const std::string& theUnit)
122 std::string aTitle = GetRowTitle(theRow);
126 myRows[theRow-1] = aTitle;
128 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
131 void SALOMEDSImpl_AttributeTableOfString::SetRowUnits(const std::vector<std::string>& theUnits)
133 if (theUnits.size() != GetNbRows()) throw DFexception("Invalid number of rows");
134 int aLength = theUnits.size(), i;
135 for(i = 1; i <= aLength; i++) SetRowUnit(i, theUnits[i-1]);
138 std::vector<std::string> SALOMEDSImpl_AttributeTableOfString::GetRowUnits()
140 std::vector<std::string> aSeq;
141 int aLength = myRows.size(), i;
142 for(i=0; i<aLength; i++) aSeq.push_back(getUnit(myRows[i]));
146 void SALOMEDSImpl_AttributeTableOfString::SetRowTitles(const std::vector<std::string>& theTitles)
148 if (theTitles.size() != GetNbRows()) throw DFexception("Invalid number of rows");
149 int aLength = theTitles.size(), i;
150 for(i = 1; i <= aLength; i++) SetRowTitle(i, theTitles[i-1]);
152 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
155 std::vector<std::string> SALOMEDSImpl_AttributeTableOfString::GetRowTitles()
157 std::vector<std::string> aSeq;
158 int aLength = myRows.size(), i;
159 for(i=0; i<aLength; i++) aSeq.push_back(getTitle(myRows[i]));
163 std::string SALOMEDSImpl_AttributeTableOfString::GetRowTitle(const int theRow) const
165 return getTitle(myRows[theRow-1]);
168 std::string SALOMEDSImpl_AttributeTableOfString::GetRowUnit(const int theRow) const
170 return getUnit(myRows[theRow-1]);
173 void SALOMEDSImpl_AttributeTableOfString::SetRowData(const int theRow,
174 const std::vector<std::string>& theData)
177 if(theData.size() > myNbColumns) SetNbColumns(theData.size());
181 while (myRows.size() < theRow) { // append new row titles
182 myRows.push_back(std::string(""));
185 int i, aShift = (theRow-1)*myNbColumns, aLength = theData.size();
186 for(i = 1; i <= aLength; i++) {
187 myTable[aShift + i] = theData[i-1];
190 if(theRow > myNbRows) myNbRows = theRow;
192 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
195 void SALOMEDSImpl_AttributeTableOfString::SetTitle(const std::string& theTitle)
201 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
204 std::string SALOMEDSImpl_AttributeTableOfString::GetTitle() const
209 std::vector<std::string> SALOMEDSImpl_AttributeTableOfString::GetRowData(const int theRow)
211 std::vector<std::string> aSeq;
212 int i, aShift = (theRow-1)*myNbColumns;
213 for(i = 1; i <= myNbColumns; i++) {
214 if(myTable.find(aShift+i) != myTable.end())
215 aSeq.push_back(myTable[aShift+i]);
223 void SALOMEDSImpl_AttributeTableOfString::SetColumnData(const int theColumn,
224 const std::vector<std::string>& theData)
227 if(theColumn > myNbColumns) SetNbColumns(theColumn);
231 int i, aLength = theData.size();
232 for(i = 1; i <= aLength; i++) {
233 myTable[myNbColumns*(i-1)+theColumn] = theData[i-1];
236 if(aLength > myNbRows) {
238 while (myRows.size() < myNbRows) { // append empty row titles
239 myRows.push_back(std::string(""));
243 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
246 std::vector<std::string> SALOMEDSImpl_AttributeTableOfString::GetColumnData(const int theColumn)
248 std::vector<std::string> aSeq;
251 for(i = 1; i <= myNbRows; i++) {
252 anIndex = myNbColumns*(i-1) + theColumn;
253 if(myTable.find(anIndex) != myTable.end())
254 aSeq.push_back(myTable[anIndex]);
262 void SALOMEDSImpl_AttributeTableOfString::SetColumnTitle(const int theColumn,
263 const std::string& theTitle)
267 while(myCols.size() < theColumn) myCols.push_back(std::string(""));
268 myCols[theColumn-1] = theTitle;
270 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
273 std::string SALOMEDSImpl_AttributeTableOfString::GetColumnTitle(const int theColumn) const
275 if(myCols.empty()) return "";
276 if(myCols.size() < theColumn) return "";
277 return myCols[theColumn-1];
280 void SALOMEDSImpl_AttributeTableOfString::SetColumnTitles(const std::vector<std::string>& theTitles)
282 if (theTitles.size() != myNbColumns) throw DFexception("Invalid number of columns");
283 int aLength = theTitles.size(), i;
284 for(i = 0; i < aLength; i++) myCols[i] = theTitles[i];
286 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
289 std::vector<std::string> SALOMEDSImpl_AttributeTableOfString::GetColumnTitles()
291 std::vector<std::string> aSeq;
292 int aLength = myCols.size(), i;
293 for(i=0; i<aLength; i++) aSeq.push_back(myCols[i]);
297 int SALOMEDSImpl_AttributeTableOfString::GetNbRows() const
302 int SALOMEDSImpl_AttributeTableOfString::GetNbColumns() const
307 void SALOMEDSImpl_AttributeTableOfString::PutValue(const std::string& theValue,
313 if(theColumn > myNbColumns) SetNbColumns(theColumn);
315 int anIndex = (theRow-1)*myNbColumns + theColumn;
316 myTable[anIndex] = theValue;
318 if(theRow > myNbRows) {
319 while (myRows.size() < theRow) { // append empty row titles
320 myRows.push_back(std::string(""));
325 SetModifyFlag(); //SRN: Mark the study as being modified, so it could be saved
328 bool SALOMEDSImpl_AttributeTableOfString::HasValue(const int theRow,
331 if(theRow > myNbRows || theRow < 1) return false;
332 if(theColumn > myNbColumns || theColumn < 1) return false;
334 int anIndex = (theRow-1)*myNbColumns + theColumn;
335 return (myTable.find(anIndex) != myTable.end());
338 std::string SALOMEDSImpl_AttributeTableOfString::GetValue(const int theRow,
341 if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
342 if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
344 int anIndex = (theRow-1)*myNbColumns + theColumn;
345 if(myTable.find(anIndex) != myTable.end()) return myTable[anIndex];
347 throw DFexception("Invalid cell index");
351 void SALOMEDSImpl_AttributeTableOfString::RemoveValue(const int theRow, const int theColumn)
354 if(theRow > myNbRows || theRow < 1) throw DFexception("Invalid cell index");
355 if(theColumn > myNbColumns || theColumn < 1) throw DFexception("Invalid cell index");
357 int anIndex = (theRow-1)*myNbColumns + theColumn;
358 if (myTable.find(anIndex) != myTable.end()) {
360 myTable.erase(anIndex);
361 SetModifyFlag(); // table is modified
365 const std::string& SALOMEDSImpl_AttributeTableOfString::ID() const
370 void SALOMEDSImpl_AttributeTableOfString::Restore(DF_Attribute* with)
373 SALOMEDSImpl_AttributeTableOfString* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfString*>(with);
379 myTable = aTable->myTable;
380 myNbRows = aTable->myNbRows;
381 myNbColumns = aTable->myNbColumns;
382 myTitle = aTable->myTitle;
384 for(anIndex = 1; anIndex <= aTable->GetNbRows();anIndex++)
385 myRows.push_back(aTable->GetRowTitle(anIndex));
387 for(anIndex = 1; anIndex <= aTable->GetNbColumns(); anIndex++)
388 myCols.push_back(aTable->GetColumnTitle(anIndex));
391 DF_Attribute* SALOMEDSImpl_AttributeTableOfString::NewEmpty() const
393 return new SALOMEDSImpl_AttributeTableOfString();
396 void SALOMEDSImpl_AttributeTableOfString::Paste(DF_Attribute* into)
399 SALOMEDSImpl_AttributeTableOfString* aTable = dynamic_cast<SALOMEDSImpl_AttributeTableOfString*>(into);
401 aTable->myTable.clear();
402 aTable->myCols.clear();
403 aTable->myRows.clear();
405 aTable->myTable = myTable;
406 aTable->myTitle = myTitle;
407 aTable->myNbRows = myNbRows;
408 aTable->myNbColumns = myNbColumns;
410 for(anIndex = 1; anIndex <= GetNbRows();anIndex++)
411 aTable->myRows.push_back(GetRowTitle(anIndex));
412 for(anIndex = 1; anIndex <= GetNbColumns(); anIndex++)
413 aTable->myCols.push_back(GetColumnTitle(anIndex));
416 std::vector<int> SALOMEDSImpl_AttributeTableOfString::GetSetRowIndices(const int theRow)
418 std::vector<int> aSeq;
420 int i, aShift = myNbColumns*(theRow-1);
421 for(i = 1; i <= myNbColumns; i++) {
422 if(myTable.find(aShift + i) != myTable.end()) aSeq.push_back(i);
428 std::vector<int> SALOMEDSImpl_AttributeTableOfString::GetSetColumnIndices(const int theColumn)
430 std::vector<int> aSeq;
433 for(i = 1; i <= myNbRows; i++) {
434 anIndex = myNbColumns*(i-1)+theColumn;
435 if(myTable.find(anIndex) != myTable.end()) aSeq.push_back(i);
441 std::string SALOMEDSImpl_AttributeTableOfString::Save()
444 char* buffer = new char[1024];
449 sprintf(buffer, "%d\n", l);
452 aString += myTitle[i];
457 sprintf(buffer, "%d\n", myNbRows);
461 for(i=0; i<myNbRows; i++) {
462 l = myRows[i].size();
463 sprintf(buffer, "%d\n", l);
466 aString += myRows[i][j];
472 sprintf(buffer, "%d\n", myNbColumns);
476 for(i=0; i<myNbColumns; i++) {
477 l = myCols[i].size();
478 sprintf(buffer, "%d\n", l);
481 aString += myCols[i][j];
486 //Store the table values
488 sprintf(buffer, "%d\n", l);
490 for(MI p = myTable.begin(); p!=myTable.end(); p++) {
491 if (p->second.size()) { // check empty string in the value table
492 sprintf(buffer, "%d\n", p->first);
494 unsigned long aValueSize = p->second.size();
495 sprintf(buffer, "%ld\n", aValueSize);
497 aString += p->second;
499 } else { // write index only of kind: "0key"; "05", for an example
500 sprintf(buffer, "0%d\n", p->first);
509 void SALOMEDSImpl_AttributeTableOfString::Load(const std::string& value)
511 std::vector<std::string> v;
512 int i, j, l, pos, aSize = (int)value.size();
513 for(i = 0, pos = 0; i<aSize; i++) {
514 if(value[i] == '\n') {
515 v.push_back(value.substr(pos, i-pos));
526 l = strtol(v[pos++].c_str(), NULL, 10);
528 myTitle = std::string(l, 0);
530 myTitle[i] = v[pos++][0];
534 myNbRows = strtol(v[pos++].c_str(), NULL, 10);
538 for(i=1; i<=myNbRows; i++) {
539 l = strtol(v[pos++].c_str(), NULL, 10);
540 aStr = std::string(l,0);
542 aStr[j] = v[pos++][0];
544 myRows.push_back(aStr);
548 myNbColumns = strtol(v[pos++].c_str(), NULL, 10);
552 for(i=1; i<=myNbColumns; i++) {
553 l = strtol(v[pos++].c_str(), NULL, 10);
554 aStr = std::string(l,0);
556 aStr[j] = v[pos++][0];
558 myCols.push_back(aStr);
561 //Restore the table values
562 l = strtol(v[pos++].c_str(), NULL, 10);
564 for(i=1; i<=l; i++) {
565 aStr = v[pos++]; //Ket as a string
566 int aKey = strtol(aStr.c_str(), NULL, 10);
568 if(aStr[0] == '0') //If the first character of the key is 0, then empty value
571 strtol(v[pos++].c_str(), NULL, 10);
574 myTable[aKey] = aValue;
578 std::vector<int> SALOMEDSImpl_AttributeTableOfString::SortRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
581 std::vector<int> result;
582 if ( theRow > 0 && theRow <= myNbRows ) {
583 std::vector<int> indices( myNbColumns );
585 for ( int i = 0; i < myNbColumns; i++ ) {
586 if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
587 indices[cnt++] = i+1;
592 TableSorter<SALOMEDSImpl_AttributeTableOfString> sorter( this, sortOrder, sortPolicy, theRow, true );
593 std::stable_sort( indices.begin(), indices.end(), sorter );
595 if ( sortPolicy == EmptyIgnore ) {
596 std::vector<int> other( myNbColumns );
598 for( int i = 0; i < myNbColumns; i++ )
599 other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
604 for ( int col = 0; col < indices.size(); col++ ) {
605 int idx = indices[col];
606 if ( col+1 == idx ) continue;
607 SwapCells(theRow, col+1, theRow, idx);
609 for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
610 if ( indices[i] == col+1 ) idx1 = i;
613 // no need for SetModifyFlag(), since it is done by SwapCells()
618 std::vector<int> SALOMEDSImpl_AttributeTableOfString::SortColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
621 std::vector<int> result;
622 if ( theColumn > 0 && theColumn <= myNbColumns ) {
623 std::vector<int> indices( myNbRows );
625 for ( int i = 0; i < myNbRows; i++ ) {
626 if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
627 indices[cnt++] = i+1;
632 TableSorter<SALOMEDSImpl_AttributeTableOfString> sorter( this, sortOrder, sortPolicy, theColumn, false );
633 std::stable_sort( indices.begin(), indices.end(), sorter );
635 if ( sortPolicy == EmptyIgnore ) {
636 std::vector<int> other( myNbRows );
638 for( int i = 0; i < myNbRows; i++ )
639 other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
644 for ( int row = 0; row < indices.size(); row++ ) {
645 int idx = indices[row];
646 if ( row+1 == idx ) continue;
647 SwapCells(row+1, theColumn, idx, theColumn);
649 for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
650 if ( indices[i] == row+1 ) idx1 = i;
653 // no need for SetModifyFlag(), since it is done by SwapCells()
658 std::vector<int> SALOMEDSImpl_AttributeTableOfString::SortByRow(const int theRow, SortOrder sortOrder, SortPolicy sortPolicy )
661 std::vector<int> result;
662 if ( theRow > 0 && theRow <= myNbRows ) {
663 std::vector<int> indices( myNbColumns );
665 for ( int i = 0; i < myNbColumns; i++ ) {
666 if ( sortPolicy != EmptyIgnore || HasValue(theRow, i+1) ) {
667 indices[cnt++] = i+1;
672 TableSorter<SALOMEDSImpl_AttributeTableOfString> sorter( this, sortOrder, sortPolicy, theRow, true );
673 std::stable_sort( indices.begin(), indices.end(), sorter );
675 if ( sortPolicy == EmptyIgnore ) {
676 std::vector<int> other( myNbColumns );
678 for( int i = 0; i < myNbColumns; i++ )
679 other[i] = HasValue(theRow, i+1) ? indices[cnt++] : i+1;
684 for ( int col = 0; col < indices.size(); col++ ) {
685 int idx = indices[col];
686 if ( col+1 == idx ) continue;
687 SwapColumns(col+1, idx);
689 for ( int i = col+1; i < indices.size() && idx1 == 0; i++)
690 if ( indices[i] == col+1 ) idx1 = i;
693 // no need for SetModifyFlag(), since it is done by SwapColumns()
698 std::vector<int> SALOMEDSImpl_AttributeTableOfString::SortByColumn(const int theColumn, SortOrder sortOrder, SortPolicy sortPolicy )
701 std::vector<int> result;
702 if ( theColumn > 0 && theColumn <= myNbColumns ) {
703 std::vector<int> indices( myNbRows );
705 for ( int i = 0; i < myNbRows; i++ ) {
706 if ( sortPolicy != EmptyIgnore || HasValue(i+1, theColumn) ) {
707 indices[cnt++] = i+1;
712 TableSorter<SALOMEDSImpl_AttributeTableOfString> sorter( this, sortOrder, sortPolicy, theColumn, false );
713 std::stable_sort( indices.begin(), indices.end(), sorter );
715 if ( sortPolicy == EmptyIgnore ) {
716 std::vector<int> other( myNbRows );
718 for( int i = 0; i < myNbRows; i++ )
719 other[i] = HasValue(i+1, theColumn) ? indices[cnt++] : i+1;
724 for ( int row = 0; row < indices.size(); row++ ) {
725 int idx = indices[row];
726 if ( row+1 == idx ) continue;
727 SwapRows(row+1, idx);
729 for ( int i = row+1; i < indices.size() && idx1 == 0; i++)
730 if ( indices[i] == row+1 ) idx1 = i;
733 // no need for SetModifyFlag(), since it is done by SwapRows()
738 void SALOMEDSImpl_AttributeTableOfString::SwapCells(const int theRow1, const int theColumn1,
739 const int theRow2, const int theColumn2)
742 if (theRow1 > myNbRows || theRow1 < 1) throw DFexception("Invalid cell index");
743 if (theRow2 > myNbRows || theRow2 < 1) throw DFexception("Invalid cell index");
744 if (theColumn1 > myNbColumns || theColumn1 < 1) throw DFexception("Invalid cell index");
745 if (theColumn2 > myNbColumns || theColumn2 < 1) throw DFexception("Invalid cell index");
747 int anIndex1 = (theRow1-1)*myNbColumns + theColumn1;
748 int anIndex2 = (theRow2-1)*myNbColumns + theColumn2;
750 bool hasValue1 = myTable.find(anIndex1) != myTable.end();
751 bool hasValue2 = myTable.find(anIndex2) != myTable.end();
753 if (!hasValue1 && !hasValue2) return; // nothing changed
755 std::string value1 = hasValue1 ? myTable[anIndex1] : 0;
756 std::string value2 = hasValue2 ? myTable[anIndex2] : 0;
758 if (hasValue1 && hasValue2 && value1 == value2) return; // nothing changed
760 if (hasValue1) myTable[anIndex2] = value1;
761 else myTable.erase(anIndex2);
762 if (hasValue2) myTable[anIndex1] = value2;
763 else myTable.erase(anIndex1);
765 SetModifyFlag(); // table is modified
768 void SALOMEDSImpl_AttributeTableOfString::SwapRows(const int theRow1, const int theRow2)
771 for (int i = 1; i <= myNbColumns; i++)
772 SwapCells(theRow1, i, theRow2, i);
774 std::string tmp = myRows[theRow1-1];
775 myRows[theRow1-1] = myRows[theRow2-1];
776 myRows[theRow2-1] = tmp;
777 // no need for SetModifyFlag(), since it is done by SwapCells()
780 void SALOMEDSImpl_AttributeTableOfString::SwapColumns(const int theColumn1, const int theColumn2)
783 for (int i = 1; i <= myNbRows; i++)
784 SwapCells(i, theColumn1, i, theColumn2);
785 // swap column titles
786 std::string tmp = myCols[theColumn1-1];
787 myCols[theColumn1-1] = myCols[theColumn2-1];
788 myCols[theColumn2-1] = tmp;
789 // no need for SetModifyFlag(), since it is done by SwapCells()