1 /******************************************************************************
2  * $Id: ogrdodssequencelayer.cpp 28375 2015-01-30 12:06:11Z rouault $
3  *
4  * Project:  OGR/DODS Interface
5  * Purpose:  Implements OGRDODSSequenceLayer class, which implements the
6  *           "Simple Sequence" access strategy.
7  * Author:   Frank Warmerdam, warmerdam@pobox.com
8  *
9  ******************************************************************************
10  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ****************************************************************************/
30 
31 #include "cpl_conv.h"
32 #include "ogr_dods.h"
33 #include "cpl_string.h"
34 
35 CPL_CVSID("$Id: ogrdodssequencelayer.cpp 28375 2015-01-30 12:06:11Z rouault $");
36 
37 /************************************************************************/
38 /*                        OGRDODSSequenceLayer()                        */
39 /************************************************************************/
40 
OGRDODSSequenceLayer(OGRDODSDataSource * poDSIn,const char * pszTargetIn,AttrTable * poOGRLayerInfoIn)41 OGRDODSSequenceLayer::OGRDODSSequenceLayer( OGRDODSDataSource *poDSIn,
42                                             const char *pszTargetIn,
43                                             AttrTable *poOGRLayerInfoIn )
44 
45         : OGRDODSLayer( poDSIn, pszTargetIn, poOGRLayerInfoIn )
46 
47 {
48     pszSubSeqPath = "profile"; // hardcode for now.
49     panSubSeqSize = NULL;
50     iLastSuperSeq = -1;
51 
52 /* -------------------------------------------------------------------- */
53 /*      What is the layer name?                                         */
54 /* -------------------------------------------------------------------- */
55     string oLayerName;
56     const char *pszLayerName = pszTargetIn;
57 
58     if( poOGRLayerInfo != NULL )
59     {
60         oLayerName = poOGRLayerInfo->get_attr( "layer_name" );
61         if( strlen(oLayerName.c_str()) > 0 )
62             pszLayerName = oLayerName.c_str();
63     }
64 
65     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
66     poFeatureDefn->Reference();
67 
68 /* -------------------------------------------------------------------- */
69 /*      Fetch the target variable.                                      */
70 /* -------------------------------------------------------------------- */
71     Sequence *seq = dynamic_cast<Sequence *>(poDS->poDDS->var( pszTargetIn ));
72 
73     poTargetVar = seq;
74     poSuperSeq = FindSuperSequence( seq );
75 
76 /* -------------------------------------------------------------------- */
77 /*      X/Y/Z fields.                                                   */
78 /* -------------------------------------------------------------------- */
79     if( poOGRLayerInfo != NULL )
80     {
81         AttrTable *poField = poOGRLayerInfo->find_container("x_field");
82         if( poField != NULL )
83             oXField.Initialize( poField, poTargetVar, poSuperSeq );
84 
85         poField = poOGRLayerInfo->find_container("y_field");
86         if( poField != NULL )
87             oYField.Initialize( poField, poTargetVar, poSuperSeq );
88 
89         poField = poOGRLayerInfo->find_container("z_field");
90         if( poField != NULL )
91             oZField.Initialize( poField, poTargetVar, poSuperSeq );
92     }
93 
94 /* -------------------------------------------------------------------- */
95 /*      If we have no layerinfo, then check if there are obvious x/y    */
96 /*      fields.                                                         */
97 /* -------------------------------------------------------------------- */
98     else
99     {
100         string oTargName = pszTargetIn;
101         string oSSTargName;
102         string x, y;
103 
104         if( poSuperSeq != NULL )
105             oSSTargName = OGRDODSGetVarPath( poSuperSeq );
106         else
107             oSSTargName = "impossiblexxx";
108 
109         if( poDS->poDDS->var( oTargName + ".lon" ) != NULL
110             && poDS->poDDS->var( oTargName + ".lat" ) != NULL )
111         {
112             oXField.Initialize( (oTargName + ".lon").c_str(), "dds",
113                                 poTargetVar, poSuperSeq );
114             oYField.Initialize( (oTargName + ".lat").c_str(), "dds",
115                                 poTargetVar, poSuperSeq );
116         }
117         else if( poDS->poDDS->var( oSSTargName + ".lon" ) != NULL
118                  && poDS->poDDS->var( oSSTargName + ".lat" ) != NULL )
119         {
120             oXField.Initialize( (oSSTargName + ".lon").c_str(), "dds",
121                                 poTargetVar, poSuperSeq );
122             oYField.Initialize( (oSSTargName + ".lat").c_str(), "dds",
123                                 poTargetVar, poSuperSeq );
124         }
125     }
126 
127 /* -------------------------------------------------------------------- */
128 /*      Add fields for the contents of the sequence.                    */
129 /* -------------------------------------------------------------------- */
130     Sequence::Vars_iter v_i;
131 
132     for( v_i = seq->var_begin(); v_i != seq->var_end(); v_i++ )
133         BuildFields( *v_i, NULL, NULL );
134 
135 /* -------------------------------------------------------------------- */
136 /*      Add fields for the contents of the super-sequence if we have    */
137 /*      one.                                                            */
138 /* -------------------------------------------------------------------- */
139     if( poSuperSeq != NULL )
140     {
141         for( v_i = poSuperSeq->var_begin();
142              v_i != poSuperSeq->var_end();
143              v_i++ )
144             BuildFields( *v_i, NULL, NULL );
145     }
146 }
147 
148 /************************************************************************/
149 /*                       ~OGRDODSSequenceLayer()                        */
150 /************************************************************************/
151 
~OGRDODSSequenceLayer()152 OGRDODSSequenceLayer::~OGRDODSSequenceLayer()
153 
154 {
155 }
156 
157 /************************************************************************/
158 /*                         FindSuperSequence()                          */
159 /*									*/
160 /*      Are we a subsequence of a sequence?                             */
161 /************************************************************************/
162 
FindSuperSequence(BaseType * poChild)163 Sequence *OGRDODSSequenceLayer::FindSuperSequence( BaseType *poChild )
164 
165 {
166     BaseType *poParent;
167 
168     for( poParent = poChild->get_parent();
169          poParent != NULL;
170          poParent = poParent->get_parent() )
171     {
172         if( poParent->type() == dods_sequence_c )
173         {
174             return dynamic_cast<Sequence *>( poParent );
175         }
176     }
177 
178     return NULL;
179 }
180 
181 /************************************************************************/
182 /*                            BuildFields()                             */
183 /*                                                                      */
184 /*      Build the field definition or definitions corresponding to      */
185 /*      the passed variable and it's children (if it has them).         */
186 /************************************************************************/
187 
BuildFields(BaseType * poFieldVar,const char * pszPathToVar,const char * pszPathToSequence)188 int OGRDODSSequenceLayer::BuildFields( BaseType *poFieldVar,
189                                        const char *pszPathToVar,
190                                        const char *pszPathToSequence )
191 
192 {
193     OGRFieldDefn oField( "", OFTInteger );
194 
195 /* -------------------------------------------------------------------- */
196 /*      Setup field name, including path if non-local.                  */
197 /* -------------------------------------------------------------------- */
198     if( pszPathToVar == NULL )
199         oField.SetName( poFieldVar->name().c_str() );
200     else
201         oField.SetName( CPLSPrintf( "%s.%s", pszPathToVar,
202                                     poFieldVar->name().c_str() ) );
203 
204 /* -------------------------------------------------------------------- */
205 /*      Capture this field definition.                                  */
206 /* -------------------------------------------------------------------- */
207     switch( poFieldVar->type() )
208     {
209       case dods_byte_c:
210       case dods_int16_c:
211       case dods_uint16_c:
212       case dods_int32_c:
213       case dods_uint32_c:
214         if( pszPathToSequence )
215             oField.SetType( OFTIntegerList );
216         else
217             oField.SetType( OFTInteger );
218         break;
219 
220       case dods_float32_c:
221       case dods_float64_c:
222         if( pszPathToSequence )
223             oField.SetType( OFTRealList );
224         else
225             oField.SetType( OFTReal );
226         break;
227 
228       case dods_str_c:
229       case dods_url_c:
230         if( pszPathToSequence )
231             oField.SetType( OFTStringList );
232         else
233             oField.SetType( OFTString );
234         break;
235 
236       case dods_sequence_c:
237       {
238           Sequence *seq = dynamic_cast<Sequence *>( poFieldVar );
239           Sequence::Vars_iter v_i;
240 
241           // We don't support a 3rd level of sequence nesting.
242           if( pszPathToSequence != NULL )
243               return FALSE;
244 
245           // We don't explore down into the target sequence if we
246           // are recursing from a supersequence.
247           if( poFieldVar == this->poTargetVar )
248               return FALSE;
249 
250           for( v_i = seq->var_begin(); v_i != seq->var_end(); v_i++ )
251           {
252               BuildFields( *v_i, oField.GetNameRef(), oField.GetNameRef() );
253           }
254       }
255       return FALSE;
256 
257       default:
258         return FALSE;
259     }
260 
261 /* -------------------------------------------------------------------- */
262 /*      Add field to feature defn, and capture mapping.                 */
263 /* -------------------------------------------------------------------- */
264     poFeatureDefn->AddFieldDefn( &oField );
265 
266     papoFields = (OGRDODSFieldDefn **)
267         CPLRealloc( papoFields, sizeof(void*) * poFeatureDefn->GetFieldCount());
268 
269     papoFields[poFeatureDefn->GetFieldCount()-1] =
270         new OGRDODSFieldDefn();
271 
272     papoFields[poFeatureDefn->GetFieldCount()-1]->Initialize(
273         OGRDODSGetVarPath(poFieldVar).c_str(), "dds",
274         poTargetVar, poSuperSeq );
275 
276 
277     if( pszPathToSequence )
278         papoFields[poFeatureDefn->GetFieldCount()-1]->pszPathToSequence
279             = CPLStrdup( pszPathToSequence );
280 
281     return TRUE;
282 }
283 
284 /************************************************************************/
285 /*                           GetFieldValue()                            */
286 /************************************************************************/
287 
GetFieldValue(OGRDODSFieldDefn * poFDefn,int nFeatureId,Sequence * seq)288 BaseType *OGRDODSSequenceLayer::GetFieldValue( OGRDODSFieldDefn *poFDefn,
289                                                int nFeatureId,
290                                                Sequence *seq )
291 
292 {
293     if( seq == NULL )
294         seq = dynamic_cast<Sequence *>(poTargetVar);
295 
296     if( !poFDefn->bValid )
297         return NULL;
298 
299 /* ==================================================================== */
300 /*      Fetch the actual value.                                         */
301 /* ==================================================================== */
302 
303 /* -------------------------------------------------------------------- */
304 /*      Simple case of a direct field within the sequence object.       */
305 /* -------------------------------------------------------------------- */
306     if( poFDefn->iFieldIndex >= 0 && poFDefn->bRelativeToSequence )
307     {
308         return seq->var_value( nFeatureId, poFDefn->iFieldIndex );
309     }
310     else if( poFDefn->iFieldIndex >= 0 && poFDefn->bRelativeToSuperSequence )
311     {
312         return poSuperSeq->var_value( iLastSuperSeq, poFDefn->iFieldIndex );
313     }
314 
315 /* -------------------------------------------------------------------- */
316 /*      More complex case where we need to drill down by name.          */
317 /* -------------------------------------------------------------------- */
318     if( poFDefn->bRelativeToSequence )
319         return seq->var_value( nFeatureId, poFDefn->pszFieldName );
320     else if( poSuperSeq != NULL && poFDefn->bRelativeToSuperSequence )
321         return poSuperSeq->var_value( iLastSuperSeq, poFDefn->pszFieldName );
322     else
323         return poDataDDS->var( poFDefn->pszFieldName );
324 }
325 
326 /************************************************************************/
327 /*                          BaseTypeToDouble()                          */
328 /************************************************************************/
329 
BaseTypeToDouble(BaseType * poBT)330 double OGRDODSSequenceLayer::BaseTypeToDouble( BaseType *poBT )
331 
332 {
333     switch( poBT->type() )
334     {
335       case dods_byte_c:
336       {
337           signed char byVal;
338           void *pValPtr = &byVal;
339 
340           poBT->buf2val( &pValPtr );
341           return (double) byVal;
342       }
343       break;
344 
345       case dods_int16_c:
346       {
347           GInt16 nIntVal;
348           void *pValPtr = &nIntVal;
349 
350           poBT->buf2val( &pValPtr );
351           return (double) nIntVal;
352       }
353       break;
354 
355       case dods_uint16_c:
356       {
357           GUInt16 nIntVal;
358           void *pValPtr = &nIntVal;
359 
360           poBT->buf2val( &pValPtr );
361           return (double) nIntVal;
362       }
363       break;
364 
365       case dods_int32_c:
366       {
367           GInt32 nIntVal;
368           void *pValPtr = &nIntVal;
369 
370           poBT->buf2val( &pValPtr );
371           return (double) nIntVal;
372       }
373       break;
374 
375       case dods_uint32_c:
376       {
377           GUInt32 nIntVal;
378           void *pValPtr = &nIntVal;
379 
380           poBT->buf2val( &pValPtr );
381           return (double) nIntVal;
382       }
383       break;
384 
385       case dods_float32_c:
386         return dynamic_cast<Float32 *>(poBT)->value();
387 
388       case dods_float64_c:
389         return dynamic_cast<Float64 *>(poBT)->value();
390 
391       case dods_str_c:
392       case dods_url_c:
393       {
394           string *poStrVal = NULL;
395           double dfResult;
396 
397           poBT->buf2val( (void **) &poStrVal );
398           dfResult = CPLAtof(poStrVal->c_str());
399           delete poStrVal;
400           return dfResult;
401       }
402       break;
403 
404       default:
405         CPLAssert( FALSE );
406         break;
407     }
408 
409     return 0.0;
410 }
411 
412 /************************************************************************/
413 /*                       GetFieldValueAsDouble()                        */
414 /************************************************************************/
415 
GetFieldValueAsDouble(OGRDODSFieldDefn * poFDefn,int nFeatureId)416 double OGRDODSSequenceLayer::GetFieldValueAsDouble( OGRDODSFieldDefn *poFDefn,
417                                                     int nFeatureId )
418 
419 {
420     BaseType *poBT;
421 
422     poBT = GetFieldValue( poFDefn, nFeatureId, NULL );
423     if( poBT == NULL )
424         return 0.0;
425 
426     return BaseTypeToDouble( poBT );
427 }
428 
429 /************************************************************************/
430 /*                             GetFeature()                             */
431 /************************************************************************/
432 
GetFeature(GIntBig nFeatureId)433 OGRFeature *OGRDODSSequenceLayer::GetFeature( GIntBig nFeatureId )
434 
435 {
436 /* -------------------------------------------------------------------- */
437 /*      Ensure we have the dataset.                                     */
438 /* -------------------------------------------------------------------- */
439     if( !ProvideDataDDS() )
440         return NULL;
441 
442     Sequence *seq = dynamic_cast<Sequence *>(poTargetVar);
443 
444 /* -------------------------------------------------------------------- */
445 /*      Figure out what the super and subsequence number this           */
446 /*      feature will be, and validate it.  If there is not super        */
447 /*      sequence the feature id is the subsequence number.              */
448 /* -------------------------------------------------------------------- */
449     int iSubSeq = -1;
450 
451     if( nFeatureId < 0 || nFeatureId >= nRecordCount )
452         return NULL;
453 
454     if( poSuperSeq == NULL )
455         iSubSeq = nFeatureId;
456     else
457     {
458         int nSeqOffset = 0, iSuperSeq;
459 
460         // for now we just scan through till find find out what
461         // super sequence this in.  In the long term we need a better (cached)
462         // approach that doesn't involve this quadratic cost.
463         for( iSuperSeq = 0;
464              iSuperSeq < nSuperSeqCount;
465              iSuperSeq++ )
466         {
467             if( nSeqOffset + panSubSeqSize[iSuperSeq] > nFeatureId )
468             {
469                 iSubSeq = nFeatureId - nSeqOffset;
470                 break;
471             }
472             nSeqOffset += panSubSeqSize[iSuperSeq];
473         }
474 
475         CPLAssert( iSubSeq != -1 );
476 
477         // Make sure we have the right target var ... the one
478         // corresponding to our current super sequence.
479         if( iSuperSeq != iLastSuperSeq )
480         {
481             iLastSuperSeq = iSuperSeq;
482             poTargetVar = poSuperSeq->var_value( iSuperSeq, pszSubSeqPath );
483             seq = dynamic_cast<Sequence *>(poTargetVar);
484         }
485     }
486 
487 /* -------------------------------------------------------------------- */
488 /*      Create the feature being read.                                  */
489 /* -------------------------------------------------------------------- */
490     OGRFeature *poFeature;
491 
492     poFeature = new OGRFeature( poFeatureDefn );
493     poFeature->SetFID( nFeatureId );
494     m_nFeaturesRead++;
495 
496 /* -------------------------------------------------------------------- */
497 /*      Process all the regular data fields.                            */
498 /* -------------------------------------------------------------------- */
499     int      iField;
500 
501     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
502     {
503         if( papoFields[iField]->pszPathToSequence )
504             continue;
505 
506         BaseType *poFieldVar = GetFieldValue( papoFields[iField], iSubSeq,
507                                               NULL );
508 
509         if( poFieldVar == NULL )
510             continue;
511 
512         switch( poFieldVar->type() )
513         {
514           case dods_byte_c:
515           {
516               signed char byVal;
517               void *pValPtr = &byVal;
518 
519               poFieldVar->buf2val( &pValPtr );
520               poFeature->SetField( iField, byVal );
521           }
522           break;
523 
524           case dods_int16_c:
525           {
526               GInt16 nIntVal;
527               void *pValPtr = &nIntVal;
528 
529               poFieldVar->buf2val( &pValPtr );
530               poFeature->SetField( iField, nIntVal );
531           }
532           break;
533 
534           case dods_uint16_c:
535           {
536               GUInt16 nIntVal;
537               void *pValPtr = &nIntVal;
538 
539               poFieldVar->buf2val( &pValPtr );
540               poFeature->SetField( iField, nIntVal );
541           }
542           break;
543 
544           case dods_int32_c:
545           {
546               GInt32 nIntVal;
547               void *pValPtr = &nIntVal;
548 
549               poFieldVar->buf2val( &pValPtr );
550               poFeature->SetField( iField, nIntVal );
551           }
552           break;
553 
554           case dods_uint32_c:
555           {
556               GUInt32 nIntVal;
557               void *pValPtr = &nIntVal;
558 
559               poFieldVar->buf2val( &pValPtr );
560               poFeature->SetField( iField, (int) nIntVal );
561           }
562           break;
563 
564           case dods_float32_c:
565             poFeature->SetField( iField,
566                                  dynamic_cast<Float32 *>(poFieldVar)->value());
567             break;
568 
569           case dods_float64_c:
570             poFeature->SetField( iField,
571                                  dynamic_cast<Float64 *>(poFieldVar)->value());
572             break;
573 
574           case dods_str_c:
575           case dods_url_c:
576           {
577               string *poStrVal = NULL;
578               poFieldVar->buf2val( (void **) &poStrVal );
579               poFeature->SetField( iField, poStrVal->c_str() );
580               delete poStrVal;
581           }
582           break;
583 
584           default:
585             break;
586         }
587     }
588 
589 /* -------------------------------------------------------------------- */
590 /*      Handle data nested in sequences.                                */
591 /* -------------------------------------------------------------------- */
592     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
593     {
594         OGRDODSFieldDefn *poFD = papoFields[iField];
595         const char *pszPathFromSubSeq;
596 
597         if( poFD->pszPathToSequence == NULL )
598             continue;
599 
600         CPLAssert( strlen(poFD->pszPathToSequence)
601                    < strlen(poFD->pszFieldName)-1 );
602 
603         if( strstr(poFD->pszFieldName,poFD->pszPathToSequence) != NULL )
604             pszPathFromSubSeq =
605                 strstr(poFD->pszFieldName,poFD->pszPathToSequence)
606                 + strlen(poFD->pszPathToSequence) + 1;
607         else
608             continue;
609 
610 /* -------------------------------------------------------------------- */
611 /*      Get the sequence out of which this variable will be collected.  */
612 /* -------------------------------------------------------------------- */
613         BaseType *poFieldVar = seq->var_value( iSubSeq,
614                                                poFD->pszPathToSequence );
615         Sequence *poSubSeq;
616         int nSubSeqCount;
617 
618         if( poFieldVar == NULL )
619             continue;
620 
621         poSubSeq = dynamic_cast<Sequence *>( poFieldVar );
622         if( poSubSeq == NULL )
623             continue;
624 
625         nSubSeqCount = poSubSeq->number_of_rows();
626 
627 /* -------------------------------------------------------------------- */
628 /*      Allocate array to put values into.                              */
629 /* -------------------------------------------------------------------- */
630         OGRFieldDefn *poOFD = poFeature->GetFieldDefnRef( iField );
631         int *panIntList = NULL;
632         double *padfDblList = NULL;
633         char **papszStrList = NULL;
634 
635         if( poOFD->GetType() == OFTIntegerList )
636         {
637             panIntList = (int *) CPLCalloc(sizeof(int),nSubSeqCount);
638         }
639         else if( poOFD->GetType() == OFTRealList )
640         {
641             padfDblList = (double *) CPLCalloc(sizeof(double),nSubSeqCount);
642         }
643         else if( poOFD->GetType() == OFTStringList )
644         {
645             papszStrList = (char **) CPLCalloc(sizeof(char*),nSubSeqCount+1);
646         }
647         else
648             continue;
649 
650 /* -------------------------------------------------------------------- */
651 /*      Loop, fetching subsequence values.                              */
652 /* -------------------------------------------------------------------- */
653         int iSubIndex;
654         for( iSubIndex = 0; iSubIndex < nSubSeqCount; iSubIndex++ )
655         {
656             poFieldVar = poSubSeq->var_value( iSubIndex, pszPathFromSubSeq );
657 
658             if( poFieldVar == NULL )
659                 continue;
660 
661             switch( poFieldVar->type() )
662             {
663               case dods_byte_c:
664               {
665                   signed char byVal;
666                   void *pValPtr = &byVal;
667 
668                   poFieldVar->buf2val( &pValPtr );
669                   panIntList[iSubIndex] = byVal;
670               }
671               break;
672 
673               case dods_int16_c:
674               {
675                   GInt16 nIntVal;
676                   void *pValPtr = &nIntVal;
677 
678                   poFieldVar->buf2val( &pValPtr );
679                   panIntList[iSubIndex] = nIntVal;
680               }
681               break;
682 
683               case dods_uint16_c:
684               {
685                   GUInt16 nIntVal;
686                   void *pValPtr = &nIntVal;
687 
688                   poFieldVar->buf2val( &pValPtr );
689                   panIntList[iSubIndex] = nIntVal;
690               }
691               break;
692 
693               case dods_int32_c:
694               {
695                   GInt32 nIntVal;
696                   void *pValPtr = &nIntVal;
697 
698                   poFieldVar->buf2val( &pValPtr );
699                   panIntList[iSubIndex] = nIntVal;
700               }
701               break;
702 
703               case dods_uint32_c:
704               {
705                   GUInt32 nIntVal;
706                   void *pValPtr = &nIntVal;
707 
708                   poFieldVar->buf2val( &pValPtr );
709                   panIntList[iSubIndex] = nIntVal;
710               }
711               break;
712 
713               case dods_float32_c:
714                 padfDblList[iSubIndex] =
715                     dynamic_cast<Float32 *>(poFieldVar)->value();
716                 break;
717 
718               case dods_float64_c:
719                 padfDblList[iSubIndex] =
720                     dynamic_cast<Float64 *>(poFieldVar)->value();
721                 break;
722 
723               case dods_str_c:
724               case dods_url_c:
725               {
726                   string *poStrVal = NULL;
727                   poFieldVar->buf2val( (void **) &poStrVal );
728                   papszStrList[iSubIndex] = CPLStrdup( poStrVal->c_str() );
729                   delete poStrVal;
730               }
731               break;
732 
733               default:
734                 break;
735             }
736         }
737 
738 /* -------------------------------------------------------------------- */
739 /*      Apply back to feature.                                          */
740 /* -------------------------------------------------------------------- */
741         if( poOFD->GetType() == OFTIntegerList )
742         {
743             poFeature->SetField( iField, nSubSeqCount, panIntList );
744             CPLFree(panIntList);
745         }
746         else if( poOFD->GetType() == OFTRealList )
747         {
748             poFeature->SetField( iField, nSubSeqCount, padfDblList );
749             CPLFree(padfDblList);
750         }
751         else if( poOFD->GetType() == OFTStringList )
752         {
753             poFeature->SetField( iField, papszStrList );
754             CSLDestroy( papszStrList );
755         }
756     }
757 
758 /* ==================================================================== */
759 /*      Fetch the geometry.                                             */
760 /* ==================================================================== */
761     if( oXField.bValid && oYField.bValid )
762     {
763         int iXField = poFeature->GetFieldIndex( oXField.pszFieldName );
764         int iYField = poFeature->GetFieldIndex( oYField.pszFieldName );
765         int iZField = -1;
766 
767         if( oZField.bValid )
768             iZField = poFeature->GetFieldIndex(oZField.pszFieldName);
769 
770 /* -------------------------------------------------------------------- */
771 /*      If we can't find the values in attributes then use the more     */
772 /*      general mechanism to fetch the value.                           */
773 /* -------------------------------------------------------------------- */
774 
775         if( iXField == -1 || iYField == -1
776             || (oZField.bValid && iZField == -1) )
777         {
778             poFeature->SetGeometryDirectly(
779                 new OGRPoint( GetFieldValueAsDouble( &oXField, iSubSeq ),
780                               GetFieldValueAsDouble( &oYField, iSubSeq ),
781                               GetFieldValueAsDouble( &oZField, iSubSeq ) ) );
782         }
783 /* -------------------------------------------------------------------- */
784 /*      If the fields are list values, then build a linestring.         */
785 /* -------------------------------------------------------------------- */
786         else if( poFeature->GetFieldDefnRef(iXField)->GetType() == OFTRealList
787             && poFeature->GetFieldDefnRef(iYField)->GetType() == OFTRealList )
788         {
789             const double *padfX, *padfY, *padfZ = NULL;
790             int nPointCount, i;
791             OGRLineString *poLS = new OGRLineString();
792 
793             padfX = poFeature->GetFieldAsDoubleList( iXField, &nPointCount );
794             padfY = poFeature->GetFieldAsDoubleList( iYField, &nPointCount );
795             if( iZField != -1 )
796                 padfZ = poFeature->GetFieldAsDoubleList(iZField,&nPointCount);
797 
798             poLS->setPoints( nPointCount, (double *) padfX, (double *) padfY,
799                              (double *) padfZ );
800 
801             // Make a pass clearing out NaN or Inf values.
802             for( i = 0; i < nPointCount; i++ )
803             {
804                 double dfX = poLS->getX(i);
805                 double dfY = poLS->getY(i);
806                 double dfZ = poLS->getZ(i);
807                 int bReset = FALSE;
808 
809                 if( OGRDODSIsDoubleInvalid( &dfX ) )
810                 {
811                     dfX = 0.0;
812                     bReset = TRUE;
813                 }
814                 if( OGRDODSIsDoubleInvalid( &dfY ) )
815                 {
816                     dfY = 0.0;
817                     bReset = TRUE;
818                 }
819                 if( OGRDODSIsDoubleInvalid( &dfZ ) )
820                 {
821                     dfZ = 0.0;
822                     bReset = TRUE;
823                 }
824 
825                 if( bReset )
826                     poLS->setPoint( i, dfX, dfY, dfZ );
827             }
828 
829             poFeature->SetGeometryDirectly( poLS );
830         }
831 
832 /* -------------------------------------------------------------------- */
833 /*      Otherwise build a point.                                        */
834 /* -------------------------------------------------------------------- */
835         else
836         {
837             poFeature->SetGeometryDirectly(
838                 new OGRPoint(
839                     poFeature->GetFieldAsDouble( iXField ),
840                     poFeature->GetFieldAsDouble( iYField ),
841                     poFeature->GetFieldAsDouble( iZField ) ) );
842         }
843     }
844 
845     return poFeature;
846 }
847 
848 /************************************************************************/
849 /*                          GetFeatureCount()                           */
850 /************************************************************************/
851 
GetFeatureCount(int bForce)852 GIntBig OGRDODSSequenceLayer::GetFeatureCount( int bForce )
853 
854 {
855     if( !bDataLoaded && !bForce )
856         return -1;
857 
858     ProvideDataDDS();
859 
860     return nRecordCount;
861 }
862 
863 /************************************************************************/
864 /*                           ProvideDataDDS()                           */
865 /************************************************************************/
866 
ProvideDataDDS()867 int OGRDODSSequenceLayer::ProvideDataDDS()
868 
869 {
870     if( bDataLoaded )
871         return poTargetVar != NULL;
872 
873     int bResult = OGRDODSLayer::ProvideDataDDS();
874 
875     if( !bResult )
876         return bResult;
877 
878     // If we are in nested sequence mode, we now need to properly set
879     // the poTargetVar based on the current step in the supersequence.
880     poSuperSeq = FindSuperSequence( poTargetVar );
881 
882 /* ==================================================================== */
883 /*      Figure out the record count.                                    */
884 /* ==================================================================== */
885 /* -------------------------------------------------------------------- */
886 /*      For simple sequences without a supersequence just return the    */
887 /*      count of elements.                                              */
888 /* -------------------------------------------------------------------- */
889     if( poSuperSeq == NULL )
890         nRecordCount = dynamic_cast<Sequence *>(poTargetVar)->number_of_rows();
891 
892 /* -------------------------------------------------------------------- */
893 /*      Otherwise we have to count up all the target sequence           */
894 /*      instances for each of the super sequence items.                 */
895 /* -------------------------------------------------------------------- */
896     else
897     {
898         int iSuper;
899 
900         nSuperSeqCount = poSuperSeq->number_of_rows();
901         panSubSeqSize = (int *) calloc(sizeof(int),nSuperSeqCount);
902         nRecordCount = 0;
903         for( iSuper = 0; iSuper < nSuperSeqCount; iSuper++ )
904         {
905             Sequence *poSubSeq = dynamic_cast<Sequence *>(
906                 poSuperSeq->var_value( iSuper, pszSubSeqPath ) );
907 
908             panSubSeqSize[iSuper] = poSubSeq->number_of_rows();
909             nRecordCount += poSubSeq->number_of_rows();
910         }
911     }
912 
913     return poTargetVar != NULL;
914 }
915 
916 /* IEEE Constants:
917 
918   http://www.psc.edu/general/software/packages/ieee/ieee.html
919 
920 Single Precision:
921 
922   S EEEEEEEE FFFFFFFFFFFFFFFFFFFFFFF
923   0 1      8 9                    31
924 
925 The value V represented by the word may be determined as follows:
926 
927     * If E=255 and F is nonzero, then V=NaN ("Not a number")
928     * If E=255 and F is zero and S is 1, then V=-Infinity
929     * If E=255 and F is zero and S is 0, then V=Infinity
930     * If 0<E<255 then V=(-1)**S * 2 ** (E-127) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
931     * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-126) * (0.F) These are "unnormalized" values.
932     * If E=0 and F is zero and S is 1, then V=-0
933     * If E=0 and F is zero and S is 0, then V=0
934 
935 In particular,
936 
937   0 00000000 00000000000000000000000 = 0
938   1 00000000 00000000000000000000000 = -0
939 
940   0 11111111 00000000000000000000000 = Infinity
941   1 11111111 00000000000000000000000 = -Infinity
942 
943   0 11111111 00000100000000000000000 = NaN
944   1 11111111 00100010001001010101010 = NaN
945 
946   0 10000000 00000000000000000000000 = +1 * 2**(128-127) * 1.0 = 2
947   0 10000001 10100000000000000000000 = +1 * 2**(129-127) * 1.101 = 6.5
948   1 10000001 10100000000000000000000 = -1 * 2**(129-127) * 1.101 = -6.5
949 
950   0 00000001 00000000000000000000000 = +1 * 2**(1-127) * 1.0 = 2**(-126)
951   0 00000000 10000000000000000000000 = +1 * 2**(-126) * 0.1 = 2**(-127)
952   0 00000000 00000000000000000000001 = +1 * 2**(-126) *
953                                        0.00000000000000000000001 =
954                                        2**(-149)  (Smallest positive value)
955 
956 Double Precision:
957 
958 The IEEE double precision floating point standard representation requires a 64 bit word, which may be represented as numbered from 0 to 63, left to right. The first bit is the sign bit, S, the next eleven bits are the exponent bits, 'E', and the final 52 bits are the fraction 'F':
959 
960   S EEEEEEEEEEE FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
961   0 1        11 12                                                63
962 
963 The value V represented by the word may be determined as follows:
964 
965     * If E=2047 and F is nonzero, then V=NaN ("Not a number")
966     * If E=2047 and F is zero and S is 1, then V=-Infinity
967     * If E=2047 and F is zero and S is 0, then V=Infinity
968     * If 0<E<2047 then V=(-1)**S * 2 ** (E-1023) * (1.F) where "1.F" is intended to represent the binary number created by prefixing F with an implicit leading 1 and a binary point.
969     * If E=0 and F is nonzero, then V=(-1)**S * 2 ** (-1022) * (0.F) These are "unnormalized" values.
970     * If E=0 and F is zero and S is 1, then V=-0
971     * If E=0 and F is zero and S is 0, then V=0
972 
973 */
974 
975 /************************************************************************/
976 /*                       OGRDODSIsFloatInvalid()                        */
977 /*                                                                      */
978 /*      For now we are really just checking if the value is NaN, Inf    */
979 /*      or -Inf.                                                        */
980 /************************************************************************/
981 
982 
OGRDODSIsFloatInvalid(const float * pfValToCheck)983 int OGRDODSIsFloatInvalid( const float * pfValToCheck )
984 
985 {
986     const unsigned char *pabyValToCheck = (unsigned char *) pfValToCheck;
987 
988 #if CPL_IS_LSB == 0
989     if( (pabyValToCheck[0] & 0x7f) == 0x7f
990         && (pabyValToCheck[1] & 0x80) == 0x80 )
991         return TRUE;
992     else
993         return FALSE;
994 #else
995     if( (pabyValToCheck[3] & 0x7f) == 0x7f
996         && (pabyValToCheck[2] & 0x80) == 0x80 )
997         return TRUE;
998     else
999         return FALSE;
1000 #endif
1001 }
1002 
1003 /************************************************************************/
1004 /*                       OGRDODSIsDoubleInvalid()                       */
1005 /*                                                                      */
1006 /*      For now we are really just checking if the value is NaN, Inf    */
1007 /*      or -Inf.                                                        */
1008 /************************************************************************/
1009 
1010 
OGRDODSIsDoubleInvalid(const double * pdfValToCheck)1011 int OGRDODSIsDoubleInvalid( const double * pdfValToCheck )
1012 
1013 {
1014     const unsigned char *pabyValToCheck = (unsigned char *) pdfValToCheck;
1015 
1016 #if CPL_IS_LSB == 0
1017     if( (pabyValToCheck[0] & 0x7f) == 0x7f
1018         && (pabyValToCheck[1] & 0xf0) == 0xf0 )
1019         return TRUE;
1020     else
1021         return FALSE;
1022 #else
1023     if( (pabyValToCheck[7] & 0x7f) == 0x7f
1024         && (pabyValToCheck[6] & 0xf0) == 0xf0 )
1025         return TRUE;
1026     else
1027         return FALSE;
1028 #endif
1029 }
1030