AbstractEncodedMessage.java

  1. /* Copyright 2002-2025 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.gnss.metric.parser;

  18. import org.hipparchus.util.FastMath;
  19. import org.orekit.errors.OrekitException;
  20. import org.orekit.errors.OrekitMessages;

  21. /** Encoded messages as a sequence of bytes.
  22.  * <p>
  23.  * Note that only full bytes are supported. This means that for example
  24.  * the 300 bits message from GPS sub-frames must be completed with 4 zero
  25.  * bits to reach 304 bits = 38 bytes, even if only the first 300 bits
  26.  * will be decoded and the 4 extra bits in the last byte will be ignored.
  27.  * </p>
  28.  * @author Luc Maisonobe
  29.  * @since 11.0
  30.  */
  31. public abstract class AbstractEncodedMessage implements EncodedMessage {

  32.     /** Current byte (as an int). */
  33.     private int current;

  34.     /** Remaining bits in current byte. */
  35.     private int remaining;

  36.     /** Empty constructor.
  37.      * <p>
  38.      * This constructor is not strictly necessary, but it prevents spurious
  39.      * javadoc warnings with JDK 18 and later.
  40.      * </p>
  41.      * @since 12.0
  42.      */
  43.     public AbstractEncodedMessage() {
  44.         // nothing to do
  45.     }

  46.     /** {@inheritDoc} */
  47.     @Override
  48.     public void start() {
  49.         this.remaining  = 0;
  50.     }

  51.     /** Fetch the next byte from the message.
  52.      * @return next byte from the message, as a primitive integer,
  53.      * or -1 if end of data has been reached
  54.      */
  55.     protected abstract int fetchByte();

  56.     /** {@inheritDoc} */
  57.     @Override
  58.     public long extractBits(final int n) {

  59.         // safety check
  60.         if (n > 63) {
  61.             throw new OrekitException(OrekitMessages.TOO_LARGE_DATA_TYPE, n);
  62.         }

  63.         // initialization
  64.         long value = 0l;

  65.         // bits gathering loop
  66.         int needed = n;
  67.         while (needed > 0) {

  68.             if (remaining == 0) {
  69.                 // we need to fetch one more byte
  70.                 final int read = fetchByte();
  71.                 if (read == -1) {
  72.                     // end was unexpected
  73.                     throw new OrekitException(OrekitMessages.END_OF_ENCODED_MESSAGE);
  74.                 }
  75.                 current   = read & 0xFF;
  76.                 remaining = 8;
  77.             }

  78.             final int nbBits = FastMath.min(remaining, needed);
  79.             value      = (value << nbBits) | (current >>> (8 - nbBits));
  80.             current    = (current << nbBits) & 0xFF;
  81.             remaining -= nbBits;
  82.             needed    -= nbBits;

  83.         }

  84.         return value;

  85.     }

  86. }