Salome HOME
Merging from V3_2_6pre4
[modules/kernel.git] / src / SALOMEDSImpl / SALOMEDSImpl_AttributeParameter.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 //  File   : SALOMEDSImpl_AttributeParameter.cxx
21 //  Author : Sergey RUIN
22 //  Module : SALOME
23
24
25 #include "SALOMEDSImpl_AttributeParameter.hxx"
26 #include <Standard_Failure.hxx>
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <strstream>
31
32 using namespace std;
33
34
35
36 IMPLEMENT_STANDARD_HANDLE( SALOMEDSImpl_AttributeParameter, SALOMEDSImpl_GenericAttribute )
37 IMPLEMENT_STANDARD_RTTIEXT( SALOMEDSImpl_AttributeParameter, SALOMEDSImpl_GenericAttribute )
38
39
40 // Purpose: Each character in the string is replaced by 3 characters: '%' and hex number 
41 //          of the character (2 characters)
42 string convertString(const string& S)
43 {
44   int length = S.size();
45   const char *s = S.c_str();
46   char *c = new char[3], *buffer = new char[length*3+1];
47   buffer[length*3] = (char)0;
48   for(int i = 0, pos = 0; i<length; i++, pos+=3) {
49     int val = (int)s[i];
50     buffer[pos] = '%';
51     sprintf(c, "%x", val);
52     buffer[pos+1] = c[0]; 
53     buffer[pos+2] = c[1];
54   }
55
56   string RS(buffer); 
57   delete c;
58   delete buffer;
59   return RS;
60 }
61
62 //Restors a string converted by the function convertString
63 string restoreString(const string& S)
64 {
65   int length = S.size();
66   char *c = new char[3], *buffer = new char[length/3+1];
67   buffer[length/3] = (char)0;
68   const char *s = S.c_str();
69   for(int i = 0, pos = 0; i<length; i+=3, pos++) {
70     c[0] = s[i+1];
71     c[1] = s[i+2];
72     c[2] = (char)0;
73     int val = strtol(c, NULL, 16);
74     buffer[pos] = (char)val;
75   }
76
77   string RS(buffer); 
78   delete c;
79   delete buffer;
80   return RS;
81 }
82
83 //=======================================================================
84 /*!
85  * Function : GetID
86  * Purpose  : Returns GUID of the attribute
87  */
88 //=======================================================================
89 const Standard_GUID& SALOMEDSImpl_AttributeParameter::GetID ()
90 {
91   static Standard_GUID ParemeterID ("BA75F3A1-E40B-46b8-8D24-B1D3C3BB1A8C");
92   return ParemeterID;
93 }   
94
95 //=======================================================================
96 /*!
97  * Function : Set
98  * Purpose  : Adds an attribute to the label
99  */
100 //=======================================================================
101 Handle(SALOMEDSImpl_AttributeParameter) SALOMEDSImpl_AttributeParameter::Set (const TDF_Label& L) 
102 {
103   Handle(SALOMEDSImpl_AttributeParameter) A;
104   if (!L.FindAttribute(SALOMEDSImpl_AttributeParameter::GetID(), A)) {
105     A = new  SALOMEDSImpl_AttributeParameter(); 
106     L.AddAttribute(A);
107   }
108
109   return A;
110 }
111
112 //=======================================================================
113 /*!
114  * Function : SetInt
115  * Purpose  : Associates a integer value with the ID
116  */
117 //=======================================================================
118 void SALOMEDSImpl_AttributeParameter::SetInt(const string& theID, const int& theValue)
119 {
120   CheckLocked();
121
122   if(theID.size() == 0) return;
123
124   Backup();
125
126   _ints[theID] = theValue;
127
128   SetModifyFlag(); 
129 }
130
131 //=======================================================================
132 /*!
133  * Function : GetInt
134  * Purpose  : Returns a int value associated with the given ID
135  */
136 //=======================================================================
137 int SALOMEDSImpl_AttributeParameter::GetInt(const string& theID)
138 {
139   if(!IsSet(theID, PT_INTEGER)) Standard_Failure::Raise("Invalid ID");
140   return _ints[theID];
141 }
142
143 //=======================================================================
144 /*!
145  * Function : SetReal
146  * Purpose  : Associates a double value with the ID
147  */
148 //=======================================================================
149 void SALOMEDSImpl_AttributeParameter::SetReal(const string& theID, const double& theValue)
150 {
151   CheckLocked();
152
153   if(theID.size() == 0) return;
154
155   Backup();
156
157   _reals[theID] = theValue;
158
159   SetModifyFlag(); 
160 }
161
162 //=======================================================================
163 /*!
164  * Function : GetReal
165  * Purpose  : Returns a double value associated with the given ID
166  */
167 //=======================================================================
168 double SALOMEDSImpl_AttributeParameter::GetReal(const string& theID)
169 {
170   if(!IsSet(theID, PT_REAL)) Standard_Failure::Raise("Invalid ID");
171   return _reals[theID];
172 }
173
174 //=======================================================================
175 /*!
176  * Function : SetString
177  * Purpose  : Associates a string with the ID
178  */
179 //=======================================================================
180 void SALOMEDSImpl_AttributeParameter::SetString(const string& theID, const string& theValue)
181 {
182   CheckLocked();
183
184   if(theID.size() == 0) return;
185
186   Backup();
187
188   _strings[theID] = theValue;
189
190   SetModifyFlag(); 
191 }
192
193 //=======================================================================
194 /*!
195  * Function : GetString
196  * Purpose  : Returns a string associated with the given ID
197  */
198 //=======================================================================
199 string SALOMEDSImpl_AttributeParameter::GetString(const string& theID)
200 {
201   if(!IsSet(theID, PT_STRING)) Standard_Failure::Raise("Invalid ID");
202   return _strings[theID];
203 }
204
205 //=======================================================================
206 /*!
207  * Function : SetBool
208  * Purpose  : Associates a bool value with the ID
209  */
210 //=======================================================================
211 void SALOMEDSImpl_AttributeParameter::SetBool(const string& theID, const bool& theValue)
212 {
213   CheckLocked();
214
215   if(theID.size() == 0) return;
216
217   Backup();
218
219   _bools[theID] = theValue;
220
221   SetModifyFlag(); 
222 }
223
224 //=======================================================================
225 /*!
226  * Function : GetBool
227  * Purpose  : Returns a bool value associated with the ID
228  */
229 //=======================================================================
230 bool SALOMEDSImpl_AttributeParameter::GetBool(const string& theID)
231 {
232   if(!IsSet(theID, PT_BOOLEAN)) Standard_Failure::Raise("Invalid ID");
233   return _bools[theID];
234 }
235
236 //=======================================================================
237 /*!
238  * Function : SetRealArray
239  * Purpose  : Associates an array of double values with the given ID
240  */
241 //=======================================================================
242 void SALOMEDSImpl_AttributeParameter::SetRealArray(const string& theID, const vector<double>& theArray)
243 {
244   CheckLocked();
245
246   if(theID.size() == 0) return;
247
248   Backup();
249
250   _realarrays[theID] = theArray;
251
252   SetModifyFlag(); 
253 }
254
255 //=======================================================================
256 /*!
257  * Function : GetRealArray
258  * Purpose  : Returns double values associated with the ID
259  */
260 //=======================================================================
261 vector<double> SALOMEDSImpl_AttributeParameter::GetRealArray(const string& theID)
262 {
263   if(!IsSet(theID, PT_REALARRAY)) Standard_Failure::Raise("Invalid ID");
264   return _realarrays[theID];
265 }
266  
267
268 //=======================================================================
269 /*!
270  * Function : SetIntArray
271  * Purpose  : Associates an array of int values with the given ID
272  */
273 //=======================================================================
274 void SALOMEDSImpl_AttributeParameter::SetIntArray(const string& theID, const vector<int>& theArray)
275 {
276   CheckLocked();
277
278   if(theID.size() == 0) return;
279
280   Backup();
281
282   _intarrays[theID] = theArray;
283
284   SetModifyFlag(); 
285 }
286
287 //=======================================================================
288 /*!
289  * Function : GetIntArray
290  * Purpose  : Returns int values associated with the ID
291  */
292 //=======================================================================
293 vector<int> SALOMEDSImpl_AttributeParameter::GetIntArray(const string& theID)
294 {
295   if(!IsSet(theID, PT_INTARRAY)) Standard_Failure::Raise("Invalid ID");
296   return _intarrays[theID];
297 }
298  
299
300 //=======================================================================
301 /*!
302  * Function : SetStrArray
303  * Purpose  : Associates an array of string values with the given ID
304  */
305 //=======================================================================
306 void SALOMEDSImpl_AttributeParameter::SetStrArray(const string& theID, const vector<string>& theArray)
307 {
308   CheckLocked();
309
310   if(theID.size() == 0) return;
311
312   Backup();
313
314   _strarrays[theID] = theArray;
315
316   SetModifyFlag(); 
317 }
318
319 //=======================================================================
320 /*!
321  * Function : GetStrArray
322  * Purpose  : Returns string values associated with the ID
323  */
324 //=======================================================================
325 vector<string> SALOMEDSImpl_AttributeParameter::GetStrArray(const string& theID)
326 {
327   if(!IsSet(theID, PT_STRARRAY)) Standard_Failure::Raise("Invalid ID");
328   return _strarrays[theID];
329 }
330  
331
332 //=======================================================================
333 /*!
334  * Function : IsSet
335  * Purpose  : Returns true if for the ID of given type was assigned \n
336  *            a value in the attribute
337  */
338 //=======================================================================
339 bool SALOMEDSImpl_AttributeParameter::IsSet(const string& theID, const Parameter_Types theType)
340 {
341   switch(theType) {
342   case PT_INTEGER: {
343     if(_ints.find(theID) != _ints.end()) return true;
344     break;
345   }
346   case PT_REAL: {
347     if(_reals.find(theID) != _reals.end()) return true;
348     break;
349   }
350   case PT_BOOLEAN: {
351     if(_bools.find(theID) != _bools.end()) return true;
352     break;
353   }
354   case PT_STRING: {
355     if(_strings.find(theID) != _strings.end()) return true;
356     break;
357   }
358   case PT_REALARRAY: {
359     if(_realarrays.find(theID) != _realarrays.end()) return true;
360     break;
361   }
362   case PT_INTARRAY: {
363     if(_intarrays.find(theID) != _intarrays.end()) return true;
364     break;
365   }
366   case PT_STRARRAY: {
367     if(_strarrays.find(theID) != _strarrays.end()) return true;
368     break;
369   }
370   default: return false;
371   }
372
373   return false;
374 }
375
376 //=======================================================================
377 /*!
378  * Function : RemoveID
379  * Purpose  : Removes a parameter with given ID
380  */
381 //=======================================================================
382 bool SALOMEDSImpl_AttributeParameter::RemoveID(const string& theID, const Parameter_Types theType)
383 {
384   Backup();
385   SetModifyFlag(); 
386
387   switch(theType) {
388   case PT_INTEGER: {
389     if(_ints.erase(theID)) return true;
390     break;
391   }
392   case PT_REAL: {
393     if(_reals.erase(theID)) return true;
394     break;
395   }
396   case PT_BOOLEAN: {
397     if(_bools.erase(theID)) return true;
398     break;
399   }
400   case PT_STRING: {
401     if(_strings.erase(theID)) return true;
402     break;
403   }
404   case PT_REALARRAY: {
405     if(_realarrays.erase(theID)) return true;
406     break;
407   }
408   case PT_INTARRAY: {
409     if(_intarrays.erase(theID)) return true;
410     break;
411   }
412   case PT_STRARRAY: {
413     if(_strarrays.erase(theID)) return true;
414     break;
415   }
416   default: return false;
417   }
418
419
420   return false;
421 }
422
423
424 //=======================================================================
425 /*!
426  * Function : GetFather
427  * Purpose  : Returns a father attribute for this attribute
428  */
429 //=======================================================================
430 Handle(SALOMEDSImpl_AttributeParameter) SALOMEDSImpl_AttributeParameter::GetFather()
431 {
432   Handle(SALOMEDSImpl_AttributeParameter) aFather;
433   TDF_Label L = Label();
434   if(L.IsRoot()) return aFather;
435
436   while(!L.IsRoot()) {
437     L = L.Father();
438     if(L.FindAttribute(SALOMEDSImpl_AttributeParameter::GetID(), aFather)) break; 
439   }
440
441   return aFather;
442 }
443
444 //=======================================================================
445 /*!
446  * Function : HasFather
447  * Purpose  : Returns True if the attribute has a father attribute
448  */
449 //=======================================================================
450 bool SALOMEDSImpl_AttributeParameter::HasFather()
451 {
452   TDF_Label L = Label();
453   if(L.IsRoot()) return false;
454   while(!L.IsRoot()) {
455     L = L.Father();
456     if(L.IsAttribute(SALOMEDSImpl_AttributeParameter::GetID())) return true; 
457   }
458
459   return false;
460 }
461
462 //=======================================================================
463 /*!
464  * Function : IsRoot
465  * Purpose  : Returns True is the attribute is highest in an hierachy
466  */
467 //=======================================================================
468 bool SALOMEDSImpl_AttributeParameter::IsRoot()
469 {
470   return ((HasFather())?false:true);
471 }           
472
473 //=======================================================================
474 /*!
475  * Function : Clear
476  * Purpose  : Clears the content of the attribute
477  */
478 //=======================================================================
479 void SALOMEDSImpl_AttributeParameter::Clear()
480 {
481   Backup();
482
483   _ints.clear();
484   _reals.clear();
485   _bools.clear();
486   _strings.clear();
487   _realarrays.clear();
488   _intarrays.clear();
489   _strarrays.clear();
490
491   SetModifyFlag(); 
492 }
493
494 //=======================================================================
495 /*!
496  * Function : GetIDs
497  * Purpose  : Returns an array of all ID's of the given type
498  */
499 //=======================================================================
500 vector<string> SALOMEDSImpl_AttributeParameter::GetIDs(const Parameter_Types theType)
501 {
502   
503   vector<string> anArray;
504   int i = 0;
505
506   switch(theType) {
507   case PT_INTEGER: {
508     if(_ints.size()) {
509       anArray.resize(_ints.size());
510       for(map<string,int>::const_iterator p = _ints.begin(); p != _ints.end(); p++, i++) 
511         anArray[i] =  p->first;
512     }
513     break;
514   }
515   case PT_REAL: {
516     if(_reals.size()) {
517       anArray.resize(_reals.size());
518       for(map<string,double>::const_iterator p = _reals.begin(); p != _reals.end(); p++, i++) 
519         anArray[i] = p->first;
520     }
521     break;
522   }
523   case PT_BOOLEAN: {
524     if(_bools.size()) {
525       anArray.resize(_bools.size());
526       for(map<string,bool>::const_iterator p = _bools.begin(); p != _bools.end(); p++, i++) 
527         anArray[i] = p->first;
528     }
529     break;
530   }
531   case PT_STRING: {
532     if(_strings.size()) {
533       anArray.resize(_strings.size());
534       for(map<string,string>::const_iterator p = _strings.begin(); p!= _strings.end(); p++) 
535         anArray[i] = p->first;
536     }
537     break;
538   }
539   case PT_REALARRAY: {
540     if(_realarrays.size()) {
541       anArray.resize(_realarrays.size());
542       for(map< string, vector<double> >::const_iterator p = _realarrays.begin(); p!= _realarrays.end(); p++) 
543         anArray[i] = p->first;
544     }
545     break;
546   }
547   case PT_INTARRAY: {
548     if(_intarrays.size()) {
549       anArray.resize(_intarrays.size());
550       for(map< string, vector<int> >::const_iterator p = _intarrays.begin(); p!= _intarrays.end(); p++) 
551         anArray[i] = p->first;
552     }
553     break;
554   }
555   case PT_STRARRAY: {
556     if(_strarrays.size()) {
557       anArray.resize(_strarrays.size());
558       for(map< string, vector<string> >::const_iterator p = _strarrays.begin(); p!= _strarrays.end(); p++) 
559         anArray[i] = p->first;
560     }
561     break;
562   }
563   default: return anArray;
564   }
565
566   return anArray;
567 }
568
569 //=======================================================================
570 /*!
571  * Function : ID
572  * Purpose  : Rteurns an GUID of the attribute
573  */
574 //=======================================================================
575 const Standard_GUID& SALOMEDSImpl_AttributeParameter::ID () const { return GetID(); } 
576
577
578 Handle(TDF_Attribute) SALOMEDSImpl_AttributeParameter::NewEmpty () const
579 {  
580   return new SALOMEDSImpl_AttributeParameter(); 
581 }
582
583 //=======================================================================
584 /*!
585  * Function : Restore
586  * Purpose  : Restors the content of the attribute from another
587  */
588 //=======================================================================
589 void SALOMEDSImpl_AttributeParameter::Restore(const Handle(TDF_Attribute)& with) 
590 {
591   Handle(SALOMEDSImpl_AttributeParameter) A = Handle(SALOMEDSImpl_AttributeParameter)::DownCast (with);
592   _ints.clear();
593   _reals.clear();
594   _bools.clear();
595   _strings.clear();
596   _realarrays.clear();
597   _intarrays.clear();
598   _strarrays.clear();
599   
600   for(map<string,int>::const_iterator p = A->_ints.begin(); p!= A->_ints.end(); p++)
601     if(p->first.size()) _ints[p->first] = p->second;
602   for(map<string,double>::const_iterator p = A->_reals.begin(); p!= A->_reals.end(); p++) 
603     if(p->first.size()) _reals[p->first] = p->second;
604   for(map<string,bool>::const_iterator p = A->_bools.begin(); p!= A->_bools.end(); p++) 
605     if(p->first.size()) _bools[p->first] = p->second;
606   for(map<string,string>::const_iterator p = A->_strings.begin(); p!= A->_strings.end(); p++) 
607     if(p->first.size()) _strings[p->first] = p->second;
608   for(map< string,vector<double> >::const_iterator p = A->_realarrays.begin(); p!= A->_realarrays.end(); p++) 
609     if(p->first.size()) _realarrays[p->first] = p->second;  
610   for(map< string,vector<int> >::const_iterator p = A->_intarrays.begin(); p!= A->_intarrays.end(); p++) 
611     if(p->first.size()) _intarrays[p->first] = p->second;  
612   for(map< string,vector<string> >::const_iterator p = A->_strarrays.begin(); p!= A->_strarrays.end(); p++) 
613     if(p->first.size()) _strarrays[p->first] = p->second; 
614 }
615
616 //=======================================================================
617 /*!
618  * Function : Paste
619  * Purpose  : Pastes the content of attribute to another
620  */
621 //=======================================================================
622 void SALOMEDSImpl_AttributeParameter::Paste (const Handle(TDF_Attribute)& into,
623                                              const Handle(TDF_RelocationTable)& RT) const
624 {
625   into->Restore(this);
626 }
627
628 //=======================================================================
629 /*!
630  * Function : Save
631  * Purpose  : Saves a content of the attribute as a string
632  */
633 //=======================================================================
634 TCollection_AsciiString SALOMEDSImpl_AttributeParameter::Save() 
635
636   ostrstream buffer;
637   char *tmpBuffer = new char[255];
638
639   buffer << _ints.size() << " ";
640
641   for(map<string,int>::const_iterator p = _ints.begin(); p != _ints.end(); p++) {
642     buffer << convertString(p->first) << " " << p->second << " ";
643   }
644
645   buffer << _reals.size() << " ";
646   for(map<string,double>::const_iterator p =_reals.begin(); p != _reals.end(); p++) {
647     sprintf(tmpBuffer, "%.64e", p->second);
648     buffer << convertString(p->first) << " " << tmpBuffer << " ";
649   }
650
651   buffer << _bools.size() << " ";
652   for(map<string,bool>::const_iterator p = _bools.begin(); p != _bools.end(); p++) {
653      buffer << convertString(p->first) << " " << p->second << " ";
654   }
655
656   buffer << _strings.size() << " ";
657   for(map<string,string>::const_iterator p = _strings.begin(); p != _strings.end(); p++) {
658     buffer << convertString(p->first) << " " <<  convertString(p->second) << " ";
659   }
660
661   buffer << _realarrays.size() << " ";
662   for(map< string,vector<double> >::const_iterator p = _realarrays.begin(); p != _realarrays.end(); p++) {
663     vector<double> v(p->second);
664     sprintf(tmpBuffer, " %s %d ", convertString(p->first).c_str(), v.size());
665     buffer << tmpBuffer;
666     for(int i = 0; i<v.size(); i++) {
667       sprintf(tmpBuffer, " %.64e ", v[i]);
668       buffer << tmpBuffer;
669     }
670   }
671
672   buffer << _intarrays.size() << " ";
673   for(map< string,vector<int> >::const_iterator p = _intarrays.begin(); p != _intarrays.end(); p++) {
674     vector<int> v(p->second);
675     sprintf(tmpBuffer, " %s %d ", convertString(p->first).c_str(), v.size());
676     buffer << tmpBuffer;
677     for(int i = 0; i<v.size(); i++) {
678       sprintf(tmpBuffer, " %d ", v[i]);
679       buffer << tmpBuffer;
680     }
681   }
682
683   buffer << _strarrays.size() << " ";
684   for(map< string,vector<string> >::const_iterator p = _strarrays.begin(); p != _strarrays.end(); p++) {
685     vector<string> v(p->second);
686     sprintf(tmpBuffer, " %s %d ", convertString(p->first).c_str(), v.size());
687     buffer << tmpBuffer;
688     for(int i = 0; i<v.size(); i++) {
689       buffer << " " << convertString(v[i]) << " ";
690     }
691   }
692
693   delete tmpBuffer;
694
695   TCollection_AsciiString AS((char*)buffer.rdbuf()->str());
696
697   return AS; 
698 }
699
700 //=======================================================================
701 /*!
702  * Function : Load
703  * Purpose  : Restores the attribute from the string
704  */
705 //=======================================================================
706 void SALOMEDSImpl_AttributeParameter::Load(const TCollection_AsciiString& theValue) 
707
708   Backup();
709
710   _ints.clear();
711   _reals.clear();
712   _bools.clear();
713   _strings.clear();
714   _realarrays.clear();
715   _intarrays.clear();
716
717   istrstream buffer(theValue.ToCString(), strlen(theValue.ToCString()));
718
719   int size, val, ival;
720   double val2;
721   string s, id;
722
723   buffer >> size;
724   for(int i = 1; i<=size; i++) {
725     buffer >> id >> val;
726     _ints[restoreString(id)] = val;
727   }
728
729   buffer >> size;
730   for(int i = 1; i<=size; i++) {
731     buffer >> id >> val2;
732     _reals[restoreString(id)] = val2;
733   }
734
735   buffer >> size;
736   for(int i = 1; i<=size; i++) {
737     buffer >> id >> val;
738     _bools[restoreString(id)] = val;
739   }
740
741   buffer >> size;
742   for(int i = 1; i<=size; i++) {
743     buffer >> id >> s;
744     _strings[restoreString(id)] = restoreString(s);
745   }
746   
747   buffer >> size;
748   for(int i = 1; i<=size; i++) {
749     buffer >> id >> val;
750     vector<double> v;
751     v.resize(val);
752     for(int j = 0; j<val; j++) {
753       buffer >> val2;
754       v[j] = val2;
755     }
756     _realarrays[restoreString(id)] = v;
757   }
758
759   buffer >> size;
760   for(int i = 1; i<=size; i++) {
761     buffer >> id >> val;
762     vector<int> v;
763     v.resize(val);
764     for(int j = 0; j<val; j++) {
765       buffer >> ival;
766       v[j] = ival;
767     }
768     _intarrays[restoreString(id)] = v;
769   }
770   
771   buffer >> size;
772   for(int i = 1; i<=size; i++) {
773     buffer >> id >> val;
774     vector<string> v;
775     v.resize(val);
776     for(int j = 0; j<val; j++) {
777       buffer >> s;
778       v[j] = restoreString(s);
779     }
780     _strarrays[restoreString(id)] = v;
781   }
782