Index: trunk/BNS/RTCM/clock_orbit_rtcm.c
===================================================================
--- trunk/BNS/RTCM/clock_orbit_rtcm.c	(revision 874)
+++ trunk/BNS/RTCM/clock_orbit_rtcm.c	(revision 878)
@@ -3,5 +3,5 @@
         Name:           clock_orbit_rtcm.c
         Project:        RTCM3
-        Version:        $Id: clock_orbit_rtcm.c,v 1.1 2008/05/04 17:38:12 mervart Exp $
+        Version:        $Id$
         Authors:        Dirk Stöcker
         Description:    state space approach for RTCM3
@@ -397,5 +397,5 @@
   while((a) > numbits) \
   { \
-    if(!size--) return -2; \
+    if(!size--) return GCOBR_SHORTBUFFER; \
     bitbuffer = (bitbuffer<<8)|((unsigned char)*(buffer++)); \
     numbits += 8; \
@@ -424,8 +424,11 @@
 
 /* standard values */
-#define G_HEADER                         SKIPBITS(8+6+10)
+#define G_HEADER(a)                      GETBITS(a,8)
+#define G_RESERVEDH(a)                   GETBITS(a,6)
+#define G_SIZE(a)                        GETBITS(a, 10)
 #define G_MESSAGE_NUMBER(a)              GETBITS(a, 12) /* DF002 */
 #define G_RESERVED6                      SKIPBITS(6)    /* DF001 */
-#define G_GPS_SATELLITE_ID(a)            GETBITS(a, 6)  /* DF068 */
+#define G_GPS_SATELLITE_ID(a)            {int temp; GETBITS(temp, 6) \
+ if(a && a != temp) return GCOBR_DATAMISMATCH; a = temp;}  /* DF068 */
 #define G_GPS_IODE(a)                    GETBITS(a, 8)  /* DF071 */
 #define G_GLONASS_IOD(a)                 GETBITS(a, 8)  /* DF237 */
@@ -433,8 +436,12 @@
 /* defined values */
 #define G_MULTIPLE_MESSAGE_INDICATOR(a)  GETBITS(a, 1)
-#define G_GPS_EPOCH_TIME(a)              GETBITS(a, 20)
-#define G_GLONASS_EPOCH_TIME(a)          GETBITS(a, 17)
-#define G_GLONASS_SATELLITE_ID(a)        GETBITS(a, 6)
-#define G_NO_OF_SATELLITES(a)            GETBITS(a, 5)
+#define G_GPS_EPOCH_TIME(a, b)           {int temp; GETBITS(temp, 20) \
+ if(b && a != temp) return GCOBR_TIMEMISMATCH; a = temp;}
+#define G_GLONASS_EPOCH_TIME(a, b)       {int temp; GETBITS(temp, 17) \
+ if(b && a != temp) return GCOBR_TIMEMISMATCH; a = temp;}
+#define G_GLONASS_SATELLITE_ID(a)        {int temp; GETBITS(temp, 6) \
+ if(a && a != temp) return GCOBR_DATAMISMATCH; a = temp;}
+#define G_NO_OF_SATELLITES(a)            {int temp; GETBITS(temp, 5) \
+ if(a && a != temp) return GCOBR_DATAMISMATCH; a = temp;}
 #define G_SATELLITE_REFERENCE_POINT(a)   GETBITS(a, 1)
 #define G_SATELLITE_REFERENCE_DATUM(a)   GETBITS(a, 1)
@@ -458,24 +465,39 @@
 #define G_CODE_BIAS(a)                   GETFLOATSIGN(a, 20, 1/100.0)
 
-/* FIXME: Joining data does no care for satellite numbers, dates and so on.
-It will only work with data, which is stored and the same order and number as
-the previos blocks! */
-
-int GetClockOrbitBias(struct ClockOrbit *co, struct Bias *b,
-const char *buffer, size_t size)
+enum GCOB_RETURN GetClockOrbitBias(struct ClockOrbit *co, struct Bias *b,
+const char *buffer, size_t size, int *bytesused)
 {
-  int type, mmi=0, i, j;
+  int type, mmi=0, i, j, h, rs, sizeofrtcmblock;
+  const char *blockstart = buffer;
   DECODESTART
 
-  G_HEADER
+  if(size < 7)
+    return GCOBR_SHORTBUFFER;
+
+  G_HEADER(h)
+  G_RESERVEDH(rs)
+  G_SIZE(sizeofrtcmblock);
+
+  if((unsigned char)h != 0xD3 || rs)
+    return GCOBR_UNKNOWNDATA;
+  if(size < sizeofrtcmblock + 3) /* 3 header bytes already removed */
+    return GCOBR_MESSAGEEXCEEDSBUFFER;
+  if(CRC24(sizeofrtcmblock+3, (const unsigned char *) blockstart) !=
+  ((((unsigned char)buffer[sizeofrtcmblock])<<16)|
+   (((unsigned char)buffer[sizeofrtcmblock+1])<<8)|
+   (((unsigned char)buffer[sizeofrtcmblock+2]))))
+    return GCOBR_CRCMISMATCH;
+
   G_MESSAGE_NUMBER(type)
   switch(type)
   {
   case COTYPE_GPSORBIT:
-    if(!co) return -5;
-    G_GPS_EPOCH_TIME(co->GPSEpochTime)
+    if(!co) return GCOBR_NOCLOCKORBITPARAMETER;
+    G_GPS_EPOCH_TIME(co->GPSEpochTime, co->NumberOfGPSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
     G_NO_OF_SATELLITES(co->NumberOfGPSSat)
+    if(co->OrbitDataSupplied)
+      return GCOBR_DATAMISMATCH;
     co->OrbitDataSupplied = 1;
     for(i = 0; i < co->NumberOfGPSSat; ++i)
@@ -497,9 +519,11 @@
     break;
   case COTYPE_GPSCLOCK:
-    if(!co) return -5;
-    G_GPS_EPOCH_TIME(co->GPSEpochTime)
+    if(!co) return GCOBR_NOCLOCKORBITPARAMETER;
+    G_GPS_EPOCH_TIME(co->GPSEpochTime, co->NumberOfGPSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
     G_NO_OF_SATELLITES(co->NumberOfGPSSat)
+    if(co->ClockDataSupplied)
+      return GCOBR_DATAMISMATCH;
     co->ClockDataSupplied = 1;
     for(i = 0; i < co->NumberOfGPSSat; ++i)
@@ -514,8 +538,10 @@
   case COTYPE_GPSCOMBINED:
     if(!co) return -5;
-    G_GPS_EPOCH_TIME(co->GPSEpochTime)
+    G_GPS_EPOCH_TIME(co->GPSEpochTime, co->NumberOfGPSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
     G_NO_OF_SATELLITES(co->NumberOfGPSSat)
+    if(co->ClockDataSupplied || co->OrbitDataSupplied)
+      return GCOBR_DATAMISMATCH;
     co->OrbitDataSupplied = 1;
     co->ClockDataSupplied = 1;
@@ -541,9 +567,11 @@
     break;
   case COTYPE_GLONASSORBIT:
-    if(!co) return -5;
-    G_GLONASS_EPOCH_TIME(co->GLONASSEpochTime)
+    if(!co) return GCOBR_NOCLOCKORBITPARAMETER;
+    G_GLONASS_EPOCH_TIME(co->GLONASSEpochTime, co->NumberOfGLONASSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
     G_NO_OF_SATELLITES(co->NumberOfGLONASSSat)
+    if(co->OrbitDataSupplied)
+      return GCOBR_DATAMISMATCH;
     co->OrbitDataSupplied = 1;
     for(i = CLOCKORBIT_NUMGPS;
@@ -566,9 +594,11 @@
     break;
   case COTYPE_GLONASSCLOCK:
-    if(!co) return -5;
-    G_GLONASS_EPOCH_TIME(co->GLONASSEpochTime)
+    if(!co) return GCOBR_NOCLOCKORBITPARAMETER;
+    G_GLONASS_EPOCH_TIME(co->GLONASSEpochTime, co->NumberOfGLONASSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
     G_NO_OF_SATELLITES(co->NumberOfGLONASSSat)
+    if(co->ClockDataSupplied)
+      return GCOBR_DATAMISMATCH;
     co->ClockDataSupplied = 1;
     for(i = CLOCKORBIT_NUMGPS;
@@ -583,9 +613,11 @@
     break;
   case COTYPE_GLONASSCOMBINED:
-    if(!co) return -5;
-    G_GLONASS_EPOCH_TIME(co->GLONASSEpochTime)
+    if(!co) return GCOBR_NOCLOCKORBITPARAMETER;
+    G_GLONASS_EPOCH_TIME(co->GLONASSEpochTime, co->NumberOfGLONASSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
     G_NO_OF_SATELLITES(co->NumberOfGLONASSSat)
+    if(co->ClockDataSupplied || co->OrbitDataSupplied)
+      return GCOBR_DATAMISMATCH;
     co->OrbitDataSupplied = 1;
     co->ClockDataSupplied = 1;
@@ -612,6 +644,6 @@
     break;
   case BTYPE_GPS:
-    if(!b) return -4;
-    G_GPS_EPOCH_TIME(b->GPSEpochTime)
+    if(!b) return GCOBR_NOBIASPARAMETER;
+    G_GPS_EPOCH_TIME(b->GPSEpochTime, co->NumberOfGPSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
@@ -629,6 +661,6 @@
     break;
   case BTYPE_GLONASS:
-    if(!b) return -4;
-    G_GPS_EPOCH_TIME(b->GLONASSEpochTime)
+    if(!b) return GCOBR_NOBIASPARAMETER;
+    G_GPS_EPOCH_TIME(b->GLONASSEpochTime, co->NumberOfGLONASSSat)
     G_MULTIPLE_MESSAGE_INDICATOR(mmi)
     G_RESERVED6
@@ -647,7 +679,9 @@
     break;
   default:
-    return -3;
-  }
-  return mmi ? 1 : 0;
+    return GCOBR_UNKNOWNTYPE;
+  }
+  if(bytesused)
+    *bytesused = sizeofrtcmblock+6;
+  return mmi ? GCOBR_MESSAGEFOLLOWS : GCOBR_OK;
 }
 #endif /* NODECODE */
Index: trunk/BNS/RTCM/clock_orbit_rtcm.h
===================================================================
--- trunk/BNS/RTCM/clock_orbit_rtcm.h	(revision 874)
+++ trunk/BNS/RTCM/clock_orbit_rtcm.h	(revision 878)
@@ -102,15 +102,30 @@
        int moremessagesfollow, char *buffer, size_t size);
 
-/* returns 0 if all ok and < 0 in case of an error, a value of 1 means
-   multiple data flags was found and there probably is at least one more block
-   for same epoch */
-/* buffer should point to a RTCM3 block. The functions does not check if the
-   block is valid, but assumes it has already been checked.
-   As a result either co or b are filled with data.
-   NOTE: data is not overwritten, but appended. You get an error if the dataset
-   do not match (i.e. mismatch in time).
-*/
-int GetClockOrbitBias(struct ClockOrbit *co, struct Bias *b,
-       const char *buffer, size_t size);
+enum GCOB_RETURN {
+  /* all well */
+  GCOBR_MESSAGEFOLLOWS = 1,
+  GCOBR_OK = 0,
+  /* unknown data, a warning */
+  GCOBR_UNKNOWNTYPE = -1,
+  GCOBR_UNKNOWNDATA = -2,
+  GCOBR_CRCMISMATCH = -3,
+  /* failed to do the work */
+  GCOBR_NOCLOCKORBITPARAMETER = -10,
+  GCOBR_NOBIASPARAMETER = -11,
+  /* data mismatch - data in storage does not match new data */
+  GCOBR_TIMEMISMATCH = -20,
+  GCOBR_DATAMISMATCH = -21,
+  /* not enough data - can decode the block completely */
+  GCOBR_SHORTBUFFER = -30,
+  GCOBR_MISSINGBITS = -31,
+  GCOBR_MESSAGEEXCEEDSBUFFER = -32
+};
+
+/* NOTE: When an error message has been emitted, the output structures may have been modified. Make a copy of the previous variant before calling the
+function to have a clean state. */
+
+/* buffer should point to a RTCM3 block */
+enum GCOB_RETURN GetClockOrbitBias(struct ClockOrbit *co, struct Bias *b,
+       const char *buffer, size_t size, int *bytesused);
 
 #endif /* RTCM3_CLOCK_ORBIT_RTCM_H */
