1 /***************************************************************************
2                           ofmt.cpp  -  formatted input/output
3                              -------------------
4     begin                : July 22 2002
5     copyright            : (C) 2002 by Marc Schellens
6     email                : m_schellens@users.sf.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 //#include "datatypes.hpp" // for friend declaration
18 #include "dstructgdl.hpp"
19 #include "real2int.hpp"
20 #include "calendar.hpp"
21 
22 #include "ofmt.hpp"
23 using namespace std;
24 
25 // for double -> string
double2string(DDouble d)26 inline string double2string( DDouble d)
27 {
28   std::ostringstream os;
29   OutAuto( os, d, 16, 8, ' ');
30   return os.str();
31 }
32 
33 // for float -> string
float2string(DFloat f)34 inline string float2string( DFloat f)
35 {
36   std::ostringstream os;
37   OutAuto( os, f, 13, 6, ' ');
38   return os.str();
39 }
40 
41 
42 static const std::string allstars="****************************************************************************************************************************";
43 template< typename Ty>
binstr(const Ty v,int w,int d,int code)44 std::string binstr( const Ty v, int w, int d, int code)
45 {
46   bool dofill=( ( (code & fmtPAD) > 0 ) );
47   SizeT bitsetsize=sizeof(Ty)*8;
48   if ( v==Ty(0.0) ) {
49    if ( w<=0 ) return "0";
50    if ( (code & fmtALIGN_LEFT) > 0 ) {
51     return "0";
52    } else {
53     if (d>0) {
54      if (d<=w) {
55       std::string z(d,'0');
56       std::string s(w-d,' ');
57       s+=z;
58       return s;
59      } else {
60       std::string s(w+10,' '); //overfill to get ***
61       return s;
62      }
63     } else {
64      std::string s(w-1,dofill?'0':' ');
65      s+='0';
66      return s;
67     }
68    }
69   }
70 
71   if (w==0) w=bitsetsize;
72 
73   SizeT first=0;
74     if (bitsetsize == 8) {
75     std::bitset<8> me(v);
76     for (SizeT i=0; i<8; ++i) if (me.test(7-i)) {first=i; break;}
77     if (8-first > w) return allstars.substr(0,w); else
78     return me.to_string<char,char_traits<char>,allocator<char> >().substr(first);
79   } else if (bitsetsize == 16) {
80     std::bitset<16> me(v);
81     for (SizeT i=0; i<16; ++i) if (me.test(15-i)) {first=i; break;}
82     if (16-first > w) return allstars.substr(0,w); else
83     return me.to_string<char,char_traits<char>,allocator<char> >().substr(first);
84   } else  if (bitsetsize == 32) {
85     std::bitset<32> me(v);
86     for (SizeT i=0; i<32; ++i) if (me.test(31-i)) {first=i; break;}
87     if (32-first > w) return allstars.substr(0,w); else
88     return me.to_string<char,char_traits<char>,allocator<char> >().substr(first);
89   } else {
90     std::bitset<64> me(v);
91     for (SizeT i=0; i<64; ++i) if (me.test(63-i)) {first=i; break;}
92     if (64-first > w) return allstars.substr(0,w); else
93     return me.to_string<char,char_traits<char>,allocator<char> >().substr(first);
94  }
95 }
96 
97 #include "ofmt.hpp"
98 
99 template <typename T>
OutInteger(std::ostream & os,const T & val,const int w,const int d,int code,const BaseGDL::IOMode oMode)100 void OutInteger(std::ostream& os, const T &val, const int w, const int d, int code, const BaseGDL::IOMode oMode) {
101  std::ostringstream oss;
102   if (d > 0) {
103    std::ostringstream ossI;
104    if (code & fmtSHOWPOS) ossI << std::showpos;
105    if (oMode == BaseGDL::DEC) ossI << val;
106    else if (oMode == BaseGDL::OCT) ossI << std::oct << val;
107    else if (oMode == BaseGDL::BIN) ossI << binstr(val, w, d, code);
108    else if (oMode == BaseGDL::HEX) ossI << std::uppercase << std::hex << val;
109    else ossI << std::nouppercase << std::hex << val; // HEXL
110    //force PADDING
111    code |= fmtPAD;
112    OutAdjustFill(oss, ossI.str(), d, code);
113    //remove PAD for next treatment ---> must be blanks
114    code &= (~fmtPAD);
115  } else {
116   if (code & fmtSHOWPOS) oss << std::showpos;
117   if (d > 0) oss << std::setw(d) << std::setfill('0');
118   if (oMode == BaseGDL::DEC) oss << val;
119   else if (oMode == BaseGDL::OCT) oss << std::oct << val;
120   else if (oMode == BaseGDL::BIN) oss << binstr(val, w, d, code);
121   else if (oMode == BaseGDL::HEX) oss << std::uppercase << std::hex << val;
122   else oss << std::nouppercase << std::hex << val; // HEXL
123  }
124  if (w == 0)
125   os << oss.str();
126  else if (oss.tellp() > w)
127   OutStars(os, w);
128  else if (code & fmtALIGN_LEFT) {
129   os << std::left;
130   os << std::setw(w);
131   os << oss.str();
132   os << std::right;
133  } else
134   OutFixFill(os, oss.str(), w, code);
135 }
136 
137 
138 template <>
OutFixed(ostream & os,const DComplex & val,const int w,const int d,const int code)139 void OutFixed<DComplex>(ostream& os, const DComplex &val, const int w, const int d, const int code)
140 {
141   OutFixed(os, val.real(), w, d, code);
142   OutFixed(os, val.imag(), w, d, code);
143 }
144 
145 template <>
OutFixed(ostream & os,const DComplexDbl & val,const int w,const int d,const int code)146 void OutFixed<DComplexDbl>( ostream& os, const DComplexDbl &val, const int w, const int d, const int code)
147 {
148   OutFixed(os, val.real(), w, d, code);
149   OutFixed(os, val.imag(), w, d, code);
150 }
151 
152 template <>
OutScientific(ostream & os,const DComplex & val,const int w,const int d,const int code)153 void OutScientific<DComplex>( ostream& os, const DComplex &val, const int w, const int d, const int code)
154 {
155   OutScientific( os, val.real(), w, d, code);
156   OutScientific( os, val.imag(), w, d, code);
157 }
158 
159 template <>
OutScientific(ostream & os,const DComplexDbl & val,const int w,const int d,const int code)160 void OutScientific<DComplexDbl>( ostream& os, const DComplexDbl &val, const int w, const int d, const int code)
161 {
162   OutScientific( os, val.real(), w, d, code);
163   OutScientific( os, val.imag(), w, d, code);
164 }
165 
166 template <>
OutAuto(ostream & os,const DComplex & val,const int w,const int d,const int code)167 void OutAuto<DComplex>( ostream& os, const DComplex &val, const int w, const int d, const int code)
168 {
169   OutAuto( os, val.real(), w, d, code);
170   OutAuto( os, val.imag(), w, d, code);
171 }
172 
173 template <>
OutAuto(ostream & os,const DComplexDbl & val,const int w,const int d,const int code)174 void OutAuto<DComplexDbl>( ostream& os, const DComplexDbl &val, const int w, const int d, const int code)
175 {
176   OutAuto( os, val.real(), w, d, code);
177   OutAuto( os, val.imag(), w, d, code);
178 }
179 
SetDefaultFieldLengths(int & w,int & d,const SizeT defPrec,const SizeT maxPrec,const SizeT wDef)180 void SetDefaultFieldLengths( int& w, int& d, const SizeT defPrec, const SizeT maxPrec, const SizeT wDef)
181 {
182   if( w == -1)     // (X)
183     {
184     d = maxPrec;
185     w = wDef;
186     }
187   else if( w == 0) // (X0)
188     {
189       if( d <= 0) d = defPrec;
190     }
191   else if( d < 0) //should never happen now.
192     d = maxPrec;
193 }
194 
OFmtAll(SizeT offs,SizeT r,SizeT & firstOut,SizeT & firstOffs,SizeT & tCount,SizeT & tCountOut)195 void DStructGDL::OFmtAll( SizeT offs, SizeT r,
196 			  SizeT& firstOut, SizeT& firstOffs,
197 			  SizeT& tCount, SizeT& tCountOut)
198 {
199   SizeT nTrans = ToTransfer();
200 
201   // transfer count
202   tCount = nTrans - offs;
203   if( r < tCount) tCount = r;
204   tCountOut = tCount;
205 
206   // find first Element
207   SizeT oneElTr = nTrans / N_Elements();
208 
209   SizeT firstEl = offs / oneElTr;
210   firstOffs =  offs % oneElTr;
211 
212   // find first tag
213   SizeT nB = 0;
214   SizeT nTags=NTags();
215   SizeT firstTag = 0;
216   for( firstTag=0; firstTag < nTags; firstTag++)
217       {
218 	SizeT tt=(*this)[firstTag]->ToTransfer();
219 	nB += tt;
220 	if( nB > firstOffs)
221 	  {
222 	    nB -= tt;
223 	    break;
224 	  }
225       }
226 
227   firstOut = firstEl * NTags() + firstTag;
228   firstOffs -= nB;
229 }
230 
231 // A code ****************************************************
232 // other
233 template<class Sp> SizeT
OFmtA(ostream * os,SizeT offs,SizeT r,int w,const int code)234 Data_<Sp>::OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code)
235 {
236   DStringGDL* stringVal = static_cast<DStringGDL*> ( this->Convert2( GDL_STRING, BaseGDL::COPY_BYTE_AS_INT));
237   SizeT retVal = stringVal->OFmtA( os, offs, r, w, code);
238   delete stringVal;
239   return retVal;
240 }
241 // string
242 template<> SizeT Data_<SpDString>::
OFmtA(ostream * os,SizeT offs,SizeT r,int w,const int code)243 OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code)
244 {
245   SizeT nTrans = ToTransfer();
246 
247   // transfer count
248   SizeT tCount = nTrans - offs;
249   if( r < tCount) tCount = r;
250 
251   SizeT endEl = offs + tCount;
252 
253 
254   if( w <= 0)
255     {
256       (*os) << left;
257       for( SizeT i=offs; i<endEl; ++i) (*os) << (*this)[ i];
258     }
259   else
260     {
261     if (code & fmtALIGN_LEFT) (*os)<< left ; else (*os) << right;
262     for( SizeT i=offs; i<endEl; ++i) (*os) << setw(w) << (*this)[ i].substr(0,w);
263     }
264 
265   return tCount;
266 }
267 // complex
268 template<> SizeT Data_<SpDComplex>::
OFmtA(ostream * os,SizeT offs,SizeT r,int w,const int code)269 OFmtA(ostream* os, SizeT offs, SizeT r, int w, const int code)
270 {
271 
272   SizeT nTrans = ToTransfer();
273 
274   // transfer count
275   SizeT tCount = nTrans - offs;
276   if (r < tCount) tCount = r;
277   SizeT tCountOut = tCount;
278 
279   SizeT firstEl = offs / 2;
280 
281   (*os) << right;
282 
283   if (offs & 0x01) {
284     if (w <= 0)
285       (*os) << float2string((*this)[ firstEl++].imag());
286     else {
287       if (code & fmtALIGN_LEFT) (*os) << left;
288       else (*os) << right;
289       (*os) << setw(w) << float2string((*this)[ firstEl++].imag()).substr(0,w);
290     }
291     tCount--;
292 
293   }
294 
295   SizeT endEl = firstEl + tCount / 2;
296 
297   if (w <= 0)
298     for (SizeT i = firstEl; i < endEl; ++i) {
299       (*os) << float2string((*this)[ firstEl++].real());
300       (*os) << float2string((*this)[ firstEl++].imag());
301     } else {
302     if (code & fmtALIGN_LEFT) (*os) << left;
303     else (*os) << right;
304     for (SizeT i = firstEl; i < endEl; ++i) {
305       (*os) << setw(w) << float2string((*this)[ firstEl++].real()).substr(0,w);
306       (*os) << setw(w) << float2string((*this)[ firstEl++].imag()).substr(0,w);
307     }
308   }
309 
310   if (tCount & 0x01) {
311     if (w <= 0)
312       (*os) << float2string((*this)[ firstEl++].real());
313     else {
314       if (code & fmtALIGN_LEFT) (*os) << left;
315       else (*os) << right;
316       (*os) << setw(w) << float2string((*this)[ firstEl++].real()).substr(0,w);
317     }
318   }
319 
320   return tCountOut;
321 }
322 template<> SizeT Data_<SpDComplexDbl>::
OFmtA(ostream * os,SizeT offs,SizeT r,int w,const int code)323 OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code)
324 {
325   SizeT nTrans = ToTransfer();
326 
327   // transfer count
328   SizeT tCount = nTrans - offs;
329   if (r < tCount) tCount = r;
330   SizeT tCountOut = tCount;
331 
332   SizeT firstEl = offs / 2;
333 
334   (*os) << right;
335 
336   if (offs & 0x01) {
337     if (w <= 0)
338       (*os) << double2string((*this)[ firstEl++].imag());
339     else {
340       if (code & fmtALIGN_LEFT) (*os) << left;
341       else (*os) << right;
342       (*os) << setw(w) << double2string((*this)[ firstEl++].imag()).substr(0,w);
343     }
344     tCount--;
345 
346   }
347 
348   SizeT endEl = firstEl + tCount / 2;
349 
350   if (w <= 0)
351     for (SizeT i = firstEl; i < endEl; ++i) {
352       (*os) << double2string((*this)[ firstEl++].real());
353       (*os) << double2string((*this)[ firstEl++].imag());
354     } else {
355     if (code & fmtALIGN_LEFT) (*os) << left;
356     else (*os) << right;
357     for (SizeT i = firstEl; i < endEl; ++i) {
358       (*os) << setw(w) << double2string((*this)[ firstEl++].real()).substr(0,w);
359       (*os) << setw(w) << double2string((*this)[ firstEl++].imag()).substr(0,w);
360     }
361   }
362 
363   if (tCount & 0x01) {
364     if (w <= 0)
365       (*os) << double2string((*this)[ firstEl++].real());
366     else {
367       if (code & fmtALIGN_LEFT) (*os) << left;
368       else (*os) << right;
369       (*os) << setw(w) << double2string((*this)[ firstEl++].real()).substr(0,w);
370     }
371   }
372 
373   return tCountOut;
374 }
375 // struct
376 SizeT DStructGDL::
OFmtA(ostream * os,SizeT offs,SizeT r,int w,const int code)377 OFmtA( ostream* os, SizeT offs, SizeT r, int w, const int code)
378 {
379   SizeT firstOut, firstOffs, tCount, tCountOut;
380   OFmtAll( offs, r, firstOut, firstOffs, tCount, tCountOut);
381 
382   SizeT trans = (*this)[ firstOut]->OFmtA( os, firstOffs, tCount, w, code);
383   if( trans >= tCount) return tCountOut;
384   tCount -= trans;
385 
386   SizeT ddSize = dd.size();
387   for( SizeT i = (firstOut+1); i < ddSize; ++i)
388     {
389       trans = (*this)[ i]->OFmtA( os, 0, tCount, w, code);
390       if( trans >= tCount) return tCountOut;
391       tCount -= trans;
392     }
393 
394   return tCountOut;
395 }
396 // F code ****************************************************
397 // other
398 template<class Sp> SizeT Data_<Sp>::
OFmtF(ostream * os,SizeT offs,SizeT r,int w,int d,const int code,const BaseGDL::IOMode oMode)399 OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode)
400 {
401   DDoubleGDL* cVal = static_cast<DDoubleGDL*>
402     ( this->Convert2( GDL_DOUBLE, BaseGDL::COPY));
403   SizeT retVal = cVal->OFmtF( os, offs, r, w, d, code, oMode);
404   delete cVal;
405   return retVal;
406 }
407 // double
408 template<> SizeT Data_<SpDDouble>::
OFmtF(ostream * os,SizeT offs,SizeT r,int w,int d,const int code,const BaseGDL::IOMode oMode)409 OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode)
410 {
411   SizeT nTrans = ToTransfer();
412 
413   // transfer count
414   SizeT tCount = nTrans - offs;
415   if( r < tCount) tCount = r;
416 
417   SizeT endEl = offs + tCount;
418 
419   SetDefaultFieldLengths( w, d, 6,  16, 25);
420 
421   if( oMode == AUTO) // G
422     {
423       for( SizeT i=offs; i<endEl; ++i)
424 	OutAuto( *os, (*this)[ i], w, d, code);
425     }
426   else if( oMode == FIXED) // F, D
427     {
428       for( SizeT i=offs; i<endEl; ++i)
429 	OutFixed(*os, (*this)[ i], w, d, code);
430     }
431   else if ( oMode == SCIENTIFIC) // E
432     {
433       for( SizeT i=offs; i<endEl; ++i)
434 	OutScientific( *os, (*this)[ i], w, d, code);
435     }
436 
437   return tCount;
438 }
439 // float (same code as double)
440 template<> SizeT Data_<SpDFloat>::
OFmtF(ostream * os,SizeT offs,SizeT r,int w,int d,const int code,const BaseGDL::IOMode oMode)441 OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode)
442 {
443   SizeT nTrans = ToTransfer();
444 
445   // transfer count
446   SizeT tCount = nTrans - offs;
447   if( r < tCount) tCount = r;
448 
449   SizeT endEl = offs + tCount;
450 
451   SetDefaultFieldLengths( w, d, 6, 7, 15);
452 
453   if( oMode == AUTO) // G
454     {
455       for( SizeT i=offs; i<endEl; ++i)
456 	OutAuto( *os, (*this)[ i], w, d, code);
457     }
458   else if( oMode == FIXED) // F, D
459     {
460       for( SizeT i=offs; i<endEl; ++i)
461 	OutFixed(*os, (*this)[ i], w, d, code);
462     }
463   else if ( oMode == SCIENTIFIC) // E
464     {
465       for( SizeT i=offs; i<endEl; ++i)
466 	OutScientific( *os, (*this)[ i], w, d, code);
467     }
468 
469   return tCount;
470 }
471 // complex
472 template<> SizeT Data_<SpDComplex>::
OFmtF(ostream * os,SizeT offs,SizeT r,int w,int d,const int code,const BaseGDL::IOMode oMode)473 OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode)
474 {
475   SizeT nTrans = ToTransfer();
476 
477   // transfer count
478   SizeT tCount = nTrans - offs;
479   if( r < tCount) tCount = r;
480   SizeT tCountOut = tCount;
481 
482   SizeT firstEl = offs / 2;
483 
484   SetDefaultFieldLengths( w, d, 6, 7, 15);
485 
486   if( oMode == AUTO)
487     {
488       if( offs & 0x01)
489 	{
490 	  OutAuto( *os, (*this)[ firstEl++].imag(), w, d, code);
491 	  tCount--;
492 	}
493 
494       SizeT endEl = firstEl + tCount / 2;
495 
496       for( SizeT i= firstEl; i<endEl; ++i)
497 	{
498 	  OutAuto( *os, (*this)[ i], w, d, code);
499 	}
500 
501       if( tCount & 0x01)
502 	{
503 	  OutAuto( *os, (*this)[ endEl].real(), w, d, code);
504 	}
505     }
506   else if( oMode == FIXED)
507     {
508       if( offs & 0x01)
509 	{
510 	  OutFixed(*os, (*this)[ firstEl++].imag(), w, d, code);
511 	  tCount--;
512 	}
513 
514       SizeT endEl = firstEl + tCount / 2;
515 
516       for( SizeT i= firstEl; i<endEl; ++i)
517 	{
518 	  OutFixed(*os, (*this)[ i], w, d, code);
519 	}
520 
521       if( tCount & 0x01)
522 	{
523 	  OutFixed(*os, (*this)[ endEl].real(), w, d, code);
524 	}
525     }
526   else if ( oMode == SCIENTIFIC)
527     {
528       if( offs & 0x01)
529 	{
530 	  OutScientific( *os, (*this)[ firstEl++].imag(), w, d, code);
531 	  tCount--;
532 	}
533 
534       SizeT endEl = firstEl + tCount / 2;
535 
536       for( SizeT i= firstEl; i<endEl; ++i)
537 	{
538 	  OutScientific( *os, (*this)[ i], w, d, code);
539 	}
540 
541       if( tCount & 0x01)
542 	{
543 	  OutScientific( *os, (*this)[ endEl].real(), w, d, code);
544 	}
545     }
546 
547   return tCountOut;
548 }
549 // same code a float
550 template<> SizeT Data_<SpDComplexDbl>::
OFmtF(ostream * os,SizeT offs,SizeT r,int w,int d,const int code,const BaseGDL::IOMode oMode)551 OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, const BaseGDL::IOMode oMode)
552 {
553   SizeT nTrans = ToTransfer();
554 
555   // transfer count
556   SizeT tCount = nTrans - offs;
557   if( r < tCount) tCount = r;
558   SizeT tCountOut = tCount;
559 
560   SizeT firstEl = offs / 2;
561 
562   SetDefaultFieldLengths( w, d, 6, 16, 25);
563 
564   if( oMode == AUTO)
565     {
566       if( offs & 0x01)
567 	{
568 	  OutAuto( *os, (*this)[ firstEl++].imag(), w, d, code);
569 	  tCount--;
570 	}
571 
572       SizeT endEl = firstEl + tCount / 2;
573 
574       for( SizeT i= firstEl; i<endEl; ++i)
575 	{
576 	  OutAuto( *os, (*this)[ i], w, d, code);
577 	}
578 
579       if( tCount & 0x01)
580 	{
581 	  OutAuto( *os, (*this)[ endEl].real(), w, d, code);
582 	}
583     }
584   else if( oMode == FIXED)
585     {
586       if( offs & 0x01)
587 	{
588 	  OutFixed(*os, (*this)[ firstEl++].imag(), w, d, code);
589 	  tCount--;
590 	}
591 
592       SizeT endEl = firstEl + tCount / 2;
593 
594       for( SizeT i= firstEl; i<endEl; ++i)
595 	{
596 	  OutFixed(*os, (*this)[ i], w, d, code);
597 	}
598 
599       if( tCount & 0x01)
600 	{
601 	  OutFixed(*os, (*this)[ endEl].real(), w, d, code);
602 	}
603     }
604   else if ( oMode == SCIENTIFIC)
605     {
606       if( offs & 0x01)
607 	{
608 	  OutScientific( *os, (*this)[ firstEl++].imag(), w, d, code);
609 	  tCount--;
610 	}
611 
612       SizeT endEl = firstEl + tCount / 2;
613 
614       for( SizeT i= firstEl; i<endEl; ++i)
615 	{
616 	  OutScientific( *os, (*this)[ i], w, d, code);
617 	}
618 
619       if( tCount & 0x01)
620 	{
621 	  OutScientific( *os, (*this)[ endEl].real(), w, d, code);
622 	}
623     }
624 
625   return tCountOut;
626 }
627 // struct
628 SizeT DStructGDL::
OFmtF(ostream * os,SizeT offs,SizeT r,int w,int d,const int code,BaseGDL::IOMode oMode)629 OFmtF( ostream* os, SizeT offs, SizeT r, int w, int d, const int code, BaseGDL::IOMode oMode)
630 {
631   SizeT firstOut, firstOffs, tCount, tCountOut;
632   OFmtAll( offs, r, firstOut, firstOffs, tCount, tCountOut);
633 
634   SizeT trans = (*this)[ firstOut]->OFmtF( os, firstOffs, tCount, w, d, code, oMode);
635   if( trans >= tCount) return tCountOut;
636   tCount -= trans;
637 
638   SizeT ddSize = dd.size();
639   for( SizeT i = (firstOut+1); i < ddSize; ++i)
640     {
641       trans = (*this)[ i]->OFmtF( os, 0, tCount, w, d, code, oMode);
642       if( trans >= tCount) return tCountOut;
643       tCount -= trans;
644     }
645 
646   return tCountOut;
647 }
648 
649 // I code ****************************************************
650 // other
651 
652 //                         undf byte int lint real dbl cplx str strct dcplx ptr obj uint ulon int64 uint64
653 const int iFmtWidth[] =    { -1,  7,  7,  12,  12,  12,  12, 12,   -1,   12, -1, -1,   7,   12,  22,   22};
654 const int iFmtWidthBIN[] = { -1,  8, 16,  32,  32,  32,  32, 32,   -1,   64, -1, -1,  16,   32,  64,   64};
655 			      // GDL_STRUCT-GDL_ULONG64
656 
657 template<class Sp> SizeT Data_<Sp>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)658 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
659        BaseGDL::IOMode oMode) {
660     if ( this->Sizeof()==2 ) {
661       DIntGDL* cVal = static_cast<DIntGDL*>
662       (this->Convert2( GDL_INT, BaseGDL::COPY ));
663       if ( w < 0 ) w = (oMode == BaseGDL::BIN ? iFmtWidthBIN[ this->t] : iFmtWidth[ this->t]);
664       SizeT retVal = cVal->OFmtI( os, offs, r, w, d, code, oMode);
665       delete cVal;
666       return retVal;
667 //FIXME THIS MAY DEPEND ON THE MACHINE NATURAL SIZE. ON 64 BITS it is promoted to 64 bits.
668 //    } else if ( this->Sizeof()==4 ) {
669 //      DLongGDL* cVal = static_cast<DLongGDL*>
670 //      (this->Convert2( GDL_LONG, BaseGDL::COPY ));
671 //      if ( w < 0 ) w = (oMode == BaseGDL::BIN ? iFmtWidthBIN[ this->t] : iFmtWidth[ this->t]);
672 //      SizeT retVal = cVal->OFmtI( os, offs, r, w, d, code, oMode);
673 //      delete cVal;
674 //      return retVal;
675     } else {
676       DLong64GDL* cVal = static_cast<DLong64GDL*>
677       (this->Convert2( GDL_LONG64, BaseGDL::COPY ));
678       if ( w < 0 ) w = (oMode == BaseGDL::BIN ? iFmtWidthBIN[ this->t] : iFmtWidth[ this->t]);
679       SizeT retVal = cVal->OFmtI( os, offs, r, w, d, code, oMode);
680       delete cVal;
681       return retVal;
682     }
683 }
684 template<> SizeT Data_<SpDByte>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)685 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
686        BaseGDL::IOMode oMode)
687 {
688   if( w < 0) w = (oMode == BIN ? 8 : 7);
689   SizeT nTrans = ToTransfer();
690   DIntGDL* cVal = static_cast<DIntGDL*> (this->Convert2( GDL_INT, BaseGDL::COPY )); //necessary for non-b formats.
691 
692   // transfer count
693   SizeT tCount = nTrans - offs;
694   if( r < tCount) tCount = r;
695 
696   SizeT endEl = offs + tCount;
697 
698   for( SizeT i=offs; i<endEl; ++i)  OutInteger( *os, (*cVal)[ i], w, d, code, oMode);
699   return tCount;
700 }
701 
702 //GDL_UINT
703 template<> SizeT Data_<SpDUInt>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)704 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
705        BaseGDL::IOMode oMode)
706 {
707   if( w < 0) w = (oMode == BIN ? 16 : 7);
708   SizeT nTrans = ToTransfer();
709   DLongGDL* cVal = static_cast<DLongGDL*> (this->Convert2( GDL_LONG, BaseGDL::COPY )); //necessary as IDL affixes the '+' when format="+".
710                                                                                        //meaning it does not pass an unsigned int!
711 
712   // transfer count
713   SizeT tCount = nTrans - offs;
714   if( r < tCount) tCount = r;
715 
716   SizeT endEl = offs + tCount;
717 
718   for( SizeT i=offs; i<endEl; ++i)  OutInteger( *os, (*cVal)[ i], w, d, code, oMode);
719   return tCount;
720 }
721 //GDL_INT
722 template<> SizeT Data_<SpDInt>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)723 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
724        BaseGDL::IOMode oMode)
725 {
726   if( w < 0) w = (oMode == BIN ? 16 : 7);
727   SizeT nTrans = ToTransfer();
728 
729   // transfer count
730   SizeT tCount = nTrans - offs;
731   if( r < tCount) tCount = r;
732 
733   SizeT endEl = offs + tCount;
734 
735   for( SizeT i=offs; i<endEl; ++i)  OutInteger( *os, (*this)[ i], w, d, code, oMode);
736   return tCount;
737 }
738 
739 // GDL_LONG
740 template<> SizeT Data_<SpDLong>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)741 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
742        BaseGDL::IOMode oMode)
743 {
744   if( w < 0) w = (oMode == BIN ? 32 : 12);
745   SizeT nTrans = ToTransfer();
746 
747   // transfer count
748   SizeT tCount = nTrans - offs;
749   if( r < tCount) tCount = r;
750 
751   SizeT endEl = offs + tCount;
752 
753   for( SizeT i=offs; i<endEl; ++i)  OutInteger( *os, (*this)[ i], w, d, code, oMode);
754   return tCount;
755 }
756 // GDL_ULONG
757 template<> SizeT Data_<SpDULong>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)758 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
759        BaseGDL::IOMode oMode)
760 {
761   if( w < 0) w = (oMode == BIN ? 32 : 12);
762   SizeT nTrans = ToTransfer();
763 
764   // transfer count
765   SizeT tCount = nTrans - offs;
766   if( r < tCount) tCount = r;
767 
768   SizeT endEl = offs + tCount;
769 
770   for( SizeT i=offs; i<endEl; ++i)  OutInteger( *os, (*this)[ i], w, d, code, oMode);
771   return tCount;
772 }
773 // GDL_LONG64
774 template<> SizeT Data_<SpDLong64>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)775 OFmtI(ostream* os, SizeT offs, SizeT r, int w, int d, int code,
776     BaseGDL::IOMode oMode)
777 {
778   if (w < 0) w = (oMode == BIN ? 64 : 22);
779   SizeT nTrans = ToTransfer();
780 
781   // transfer count
782   SizeT tCount = nTrans - offs;
783   if (r < tCount) tCount = r;
784 
785   SizeT endEl = offs + tCount;
786 
787   for (SizeT i = offs; i < endEl; ++i) OutInteger(*os, (*this)[ i], w, d, code, oMode);
788   return tCount;
789 }
790 // GDL_ULONG64
791 template<> SizeT Data_<SpDULong64>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)792 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
793        BaseGDL::IOMode oMode)
794 {
795   if( w < 0) w = (oMode == BIN ? 64 : 22);
796   SizeT nTrans = ToTransfer();
797 
798   // transfer count
799   SizeT tCount = nTrans - offs;
800   if( r < tCount) tCount = r;
801 
802   SizeT endEl = offs + tCount;
803 
804   for( SizeT i=offs; i<endEl; ++i)  OutInteger( *os, (*this)[ i], w, d, code, oMode);
805   return tCount;
806 }
807 
808 template<> SizeT Data_<SpDComplex>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)809 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
810        BaseGDL::IOMode oMode)
811 {
812   if( w < 0) w = (oMode == BIN ? 32 : 12);
813   SizeT nTrans = ToTransfer();
814 
815   // transfer count
816   SizeT tCount = nTrans - offs;
817   if( r < tCount) tCount = r;
818   SizeT tCountOut = tCount;
819 
820   SizeT firstEl = offs / 2;
821   if( offs & 0x01)
822     {
823       OutInteger( *os, static_cast<DLong64>((*this)[ firstEl++].imag()), w, d, code, oMode);
824       tCount--;
825     }
826 
827   SizeT endEl = firstEl + tCount / 2;
828 
829     for ( SizeT i = firstEl; i < endEl; ++i ) {
830        OutInteger( *os, static_cast<DLong64>((*this)[ i].real()), w, d, code, oMode);
831        OutInteger( *os, static_cast<DLong64>((*this)[ i].imag()), w, d, code, oMode);
832     }
833 
834   if( tCount & 0x01)
835   {
836       OutInteger( *os, static_cast<DLong64>((*this)[ endEl++].real()), w, d, code, oMode);
837   }
838   return tCountOut;
839 }
840 template<> SizeT Data_<SpDComplexDbl>::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)841 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
842        BaseGDL::IOMode oMode)
843 {
844   if( w < 0) w = (oMode == BIN ? 32 : 12);
845   SizeT nTrans = ToTransfer();
846 
847   // transfer count
848   SizeT tCount = nTrans - offs;
849   if( r < tCount) tCount = r;
850   SizeT tCountOut = tCount;
851 
852   SizeT firstEl = offs / 2;
853   if( offs & 0x01)
854     {
855       OutInteger( *os, static_cast<DLong64>((*this)[ firstEl++].imag()), w, d, code, oMode);
856       tCount--;
857     }
858 
859   SizeT endEl = firstEl + tCount / 2;
860 
861     for ( SizeT i = firstEl; i < endEl; ++i ) {
862        OutInteger( *os, static_cast<DLong64>((*this)[ i].real()), w, d, code, oMode);
863        OutInteger( *os, static_cast<DLong64>((*this)[ i].imag()), w, d, code, oMode);
864     }
865 
866   if( tCount & 0x01)
867   {
868       OutInteger( *os, static_cast<DLong64>((*this)[ endEl++].real()), w, d, code, oMode);
869   }
870   return tCountOut;
871 }
872 
873 SizeT DStructGDL::
OFmtI(ostream * os,SizeT offs,SizeT r,int w,int d,int code,BaseGDL::IOMode oMode)874 OFmtI( ostream* os, SizeT offs, SizeT r, int w, int d, int code,
875        BaseGDL::IOMode oMode)
876 {
877   SizeT firstOut, firstOffs, tCount, tCountOut;
878   OFmtAll( offs, r, firstOut, firstOffs, tCount, tCountOut);
879 
880   SizeT trans = (*this)[ firstOut]->OFmtI( os, firstOffs, tCount, w, d, code, oMode);
881   if( trans >= tCount) return tCountOut;
882   tCount -= trans;
883 
884   SizeT ddSize = dd.size();
885   for( SizeT i = (firstOut+1); i < ddSize; ++i)
886     {
887       trans = (*this)[ i]->OFmtI( os, 0, tCount, w, d, code, oMode);
888       if( trans >= tCount) return tCountOut;
889       tCount -= trans;
890     }
891 
892   return tCountOut;
893 }
894 
outA(ostream * os,string s,int w,const int code)895 void outA( ostream* os, string s, int w, const int code)
896 {
897   if (w <= 0) {
898     (*os) << left;
899     (*os) << s;
900   }
901   else {
902     if (code & fmtALIGN_LEFT) {
903       (*os) << setw(w) << s.substr(0, w);
904     } else {
905       (*os) << right;
906       (*os) << setw(w) << s.substr(0, w);
907     }
908   }
909 }
910 // struct
911 SizeT DStructGDL::
OFmtCal(ostream * os,SizeT offs,SizeT r,int w,int d,char * f,int code,BaseGDL::Cal_IOMode cMode)912 OFmtCal( ostream* os, SizeT offs, SizeT r, int w, int d, char *f, int code, BaseGDL::Cal_IOMode cMode)
913 {
914   SizeT firstOut, firstOffs, tCount, tCountOut;
915   OFmtAll( offs, r, firstOut, firstOffs, tCount, tCountOut);
916 
917   SizeT trans = (*this)[ firstOut]->OFmtCal( os, firstOffs, tCount, w, d, f, code, cMode);
918   if( trans >= tCount) return tCountOut;
919   tCount -= trans;
920 
921   SizeT ddSize = dd.size();
922   for( SizeT i = (firstOut+1); i < ddSize; ++i)
923     {
924       trans = (*this)[ i]->OFmtCal( os, 0, tCount, w, d, f, code, cMode);
925       if( trans >= tCount) return tCountOut;
926       tCount -= trans;
927      }
928 
929   return tCountOut;
930 }
931 
932  template<class Sp> SizeT Data_<Sp>::
OFmtCal(ostream * os,SizeT offs,SizeT repeat,int w,int d,char * fill,int code,BaseGDL::Cal_IOMode cMode)933  OFmtCal( ostream* os, SizeT offs, SizeT repeat, int w, int d, char *fill, int code, BaseGDL::Cal_IOMode cMode)
934  {
935 
936    static string theMonth[12]={"January","February","March","April","May","June",
937           "July","August","September","October","November","December"};
938    static string theMONTH[12]={"JANUARY","FEBRUARY","MARCH","APRIL","MAY","JUNE",
939           "JULY","AUGUST","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"};
940    static string themonth[12]={"january","february","march","april","may","june",
941           "july","august","september","october","november","december"};
942    static string theDAY[7]={"MONDAY","TUESDAY","WEDNESDAY","THURSDAY","FRIDAY","SATURDAY","SUNDAY"};
943    static string theDay[7]={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"};
944    static string theday[7]={"monday","tuesday","wednesday","thursday","friday","saturday","sunday"};
945    static string capa[2]={"am","pm"};
946    static string cApa[2]={"Am","Pm"};
947    static string cAPa[2]={"AM","PM"};
948 
949   static DLong *iMonth, *iDay, *iYear, *iHour, *iMinute, *dow, *icap;
950   static DDouble *Second;
951   static ostringstream **local_os;
952   bool cmplx=FALSE;
953   SizeT nTrans = ToTransfer();
954   // transfer count
955   SizeT tCount = nTrans - offs;
956   SizeT r=tCount;
957   if ( Data_<Sp>::IS_COMPLEX ) { cmplx=TRUE;} //tCount in this case is twice the size of the complex array
958 
959   switch ( cMode ) {
960     case BaseGDL::WRITE:
961         for (SizeT i=0, j=0; j<r; j++){
962           if (i >= repeat) {i=0; (*os)<<'\n';}
963           (*os)<<(local_os[j]->str()).c_str();
964           i++;
965           delete local_os[j];
966         }
967         delete local_os;
968         delete iMonth;
969         delete iDay ;
970         delete iYear;
971         delete iHour;
972         delete iMinute;
973         delete dow;
974         delete icap;
975         delete Second;
976       break;
977     case BaseGDL::COMPUTE:
978       iMonth=(DLong*)calloc(r,sizeof(DLong));
979       iDay=(DLong*)calloc(r,sizeof(DLong));
980       iYear=(DLong*)calloc(r,sizeof(DLong));
981       iHour=(DLong*)calloc(r,sizeof(DLong));
982       iMinute=(DLong*)calloc(r,sizeof(DLong));
983       dow=(DLong*)calloc(r,sizeof(DLong));
984       icap=(DLong*)calloc(r,sizeof(DLong));
985       Second=(DDouble*)calloc(r,sizeof(DDouble));
986       local_os=(ostringstream**)calloc(r,sizeof(ostringstream*));
987       if ( cmplx ) {
988         DComplexDblGDL* cVal = static_cast<DComplexDblGDL*> (this->Convert2( GDL_COMPLEXDBL, BaseGDL::COPY ));
989         for( SizeT i=0, j=0; j<(r/2); ++j)
990         {
991           local_os[i]=new ostringstream();
992           if (!j2ymdhms( (*cVal)[offs +j].real(), iMonth[i], iDay[i], iYear[i], iHour[i], iMinute[i], Second[i], dow[i], icap[i] )) throw GDLException("Value of Julian date is out of allowed range.");
993           i++;
994           local_os[i]=new ostringstream();
995           if (!j2ymdhms( (*cVal)[offs+j].imag(), iMonth[i], iDay[i], iYear[i], iHour[i], iMinute[i], Second[i], dow[i], icap[i] )) throw GDLException("Value of Julian date is out of allowed range.");
996           i++;
997         }
998         delete cVal;
999       } else {
1000         for ( SizeT i = 0; i < r; i++ ) {
1001           local_os[i]=new ostringstream();
1002           DDoubleGDL* cVal = static_cast<DDoubleGDL*> (this->Convert2( GDL_DOUBLE, BaseGDL::COPY ));
1003           if (!j2ymdhms( (*cVal)[offs + i], iMonth[i], iDay[i], iYear[i], iHour[i], iMinute[i], Second[i], dow[i], icap[i] )) throw GDLException("Value of Julian date is out of allowed range.");
1004           delete cVal;
1005 //          cerr<<"Dow="<<dow[i]<<" iDay="<<iDay[i]<<" iMonth="<<iMonth[i]<<" iYear="<<iYear[i]<<" iHour="<<iHour[i]<<" iMinute="<<iMinute[i]<<" Second="<<Second[i]<<" icap="<<icap[i]<<endl;
1006         }
1007       }
1008       break;
1009     case BaseGDL::DEFAULT:
1010       for (SizeT i=0; i<r; i++){
1011       outA( local_os[i], theDay[dow[i]], 3 , code);
1012       (*local_os[i]) << " ";
1013       outA( local_os[i], theMonth[iMonth[i]], 3 , code);
1014       (*local_os[i]) << " ";
1015       OutInteger( *(local_os[i]), iDay[i], 2, 2, code, BaseGDL::DEC);
1016       (*local_os[i]) << " ";
1017       OutInteger( *(local_os[i]), iHour[i], 2, 2, code, BaseGDL::DEC);
1018       (*local_os[i]) << ":";
1019       OutInteger( *(local_os[i]), iMinute[i], 2, 2, code, BaseGDL::DEC);
1020       (*local_os[i]) << ":";
1021       OutInteger( *(local_os[i]), (DLong) (Second[i]) , 2, 2, code, BaseGDL::DEC);
1022       std::stringbuf buffer; // empty buffer
1023       std::ostream os (&buffer); // associate stream buffer to stream
1024       os.width(6);
1025       os << iYear[i];
1026       outA( local_os[i], buffer.str().substr(buffer.str().size()-5,5), 5 , code); //selects the 5 last digits of year.
1027       }
1028       break;
1029     case BaseGDL::STRING:
1030       for (SizeT i=0; i<r; i++){
1031       (*local_os[i]) << *fill;
1032       }
1033       break;
1034     case BaseGDL::CMOA:
1035       for (SizeT i=0; i<r; i++){
1036       outA( local_os[i], theMONTH[iMonth[i]], w, code);
1037       }
1038       break;
1039     case BaseGDL::CMoA:
1040       for (SizeT i=0; i<r; i++){
1041       outA( local_os[i], theMonth[iMonth[i]], w, code);
1042       }
1043       break;
1044     case BaseGDL::CmoA:
1045       for (SizeT i=0; i<r; i++){
1046       outA( local_os[i], themonth[iMonth[i]], w, code);
1047       }
1048       break;
1049     case BaseGDL::CDWA:
1050       for (SizeT i=0; i<r; i++){
1051       outA( local_os[i], theDAY[dow[i]], w, code);
1052       }
1053       break;
1054     case BaseGDL::CDwA:
1055       for (SizeT i=0; i<r; i++){
1056       outA( local_os[i], theDay[dow[i]], w, code);
1057       }
1058       break;
1059     case BaseGDL::CdwA:
1060       for (SizeT i=0; i<r; i++){
1061       outA( local_os[i], theday[dow[i]], w, code );
1062       }
1063       break;
1064     case BaseGDL::CapA:
1065       if ( w == -1 ) w = 2;
1066       for (SizeT i=0; i<r; i++){
1067       outA( local_os[i], capa[icap[i]], w, code );
1068       }
1069       break;
1070     case BaseGDL::CApA:
1071       if ( w == -1 ) w = 2;
1072       for (SizeT i=0; i<r; i++){
1073       outA( local_os[i], cApa[icap[i]], w, code );
1074       }
1075       break;
1076     case BaseGDL::CAPA:
1077       if ( w == -1 ) w = 2;
1078       for (SizeT i=0; i<r; i++){
1079       outA( local_os[i], cAPa[icap[i]], w, code );
1080       }
1081       break;
1082       //integer
1083     case BaseGDL::CMOI:
1084       if ( w == -1 ) w = 2;
1085       for (SizeT i=0; i<r; i++){
1086       OutInteger( *(local_os[i]), iMonth[i]+1, w, d, code, BaseGDL::DEC);
1087       }
1088       break;
1089     case BaseGDL::CYI:
1090       if ( w == -1 ) w = 4;
1091       for (SizeT i=0; i<r; i++){ //convert to string before outing only the w last characters as this is what IDL does.
1092         std::stringbuf buffer; // empty buffer
1093         std::ostream os (&buffer); // associate stream buffer to stream
1094         os.width(w);
1095         os << iYear[i];
1096         outA( local_os[i], buffer.str().substr(buffer.str().size()-w,w), w , code); //CYI2.2 selects the two last digits of year.
1097       }
1098       break;
1099     case BaseGDL::ChI:
1100       if ( w == -1 ) w = 2;
1101       for (SizeT i=0; i<r; i++){
1102       OutInteger( *(local_os[i]), iHour[i]%12, w, d, code, BaseGDL::DEC);
1103       }
1104       break;
1105     case BaseGDL::CHI:
1106       if ( w == -1 ) w = 2;
1107       for (SizeT i=0; i<r; i++){
1108       OutInteger( *(local_os[i]), iHour[i], w, d, code, BaseGDL::DEC);
1109       }
1110       break;
1111     case BaseGDL::CDI:
1112       if ( w == -1 ) w = 2;
1113       for (SizeT i=0; i<r; i++){
1114       OutInteger( *(local_os[i]), iDay[i], w, d, code, BaseGDL::DEC);
1115       }
1116       break;
1117     case BaseGDL::CMI:
1118       if ( w == -1 ) w = 2;
1119       for (SizeT i=0; i<r; i++){
1120       OutInteger( *(local_os[i]), iMinute[i], w, d, code, BaseGDL::DEC);
1121       }
1122       break;
1123     case BaseGDL::CSI:
1124       if ( w == -1 ) {
1125         w = 2;
1126         d = 0;
1127       }
1128       for (SizeT i=0; i<r; i++){
1129       OutInteger( *(local_os[i]), (DLong) (Second[i]), w, d, code, BaseGDL::DEC);
1130       }
1131       break;
1132       //Float
1133     case BaseGDL::CSF:
1134       if ( w == -1 ) {
1135         w = 5;
1136         d = 2;
1137       }
1138       //      SetField( w, d, 6,  16, 25);
1139       for (SizeT i=0; i<r; i++){
1140         //this may print Second as 60.xxx but IDL DOES THE SAME!
1141       OutFixed(*local_os[i], Second[i], w, d, code);
1142       }
1143       break;
1144   }
1145   return tCount;
1146  }
1147 
1148 #include "instantiate_templates.hpp"
1149