void mgh::write(string fname, const raw & data){ FILE * src = fopen(fname.c_str(), "wb"); if(src == NULL)throw "Failed to open file"; int bytes_written = fwrite(data.c_str(), 1, data.size(), src); fclose(src); if(bytes_written != data.size())throw "Could not write all the data"; };
void message_10::read_data(const raw & bits) { bits.get(repeat_indicator, 6, 2); bits.get(mmsi, 8, 30); // spare 38 - 39 bits.get(dest_mmsi, 40, 30); // spare 70 - 71 }
message_21::message_21(const raw & bits) : message(ID) , name("@@@@@@@@@@@@@@@@@@@@") { if ((bits.size() < SIZE_BITS_MIN) || (bits.size() > SIZE_BITS_MAX)) throw std::invalid_argument{"invalid number of bits in message_21"}; read_data(bits); }
message_03::message_03(const raw & bits) : message_01(ID) { if (bits.size() != SIZE_BITS) throw std::invalid_argument{"invalid number of bits in ais/message_03"}; read_data(bits); }
std::unique_ptr<message> make_message(const raw & data) throw(std::invalid_argument) { if (data.size() < 1) throw std::invalid_argument{"raw data of insufficient size"}; message_id type = static_cast<message_id>(data[0]); return instantiate_message(type)(data); }
void message_21::read_data(const raw & bits) { get(bits, repeat_indicator); get(bits, mmsi); get(bits, aid_type); get(bits, name); get(bits, position_accuracy); get(bits, longitude_minutes); get(bits, latitude_minutes); get(bits, to_bow); get(bits, to_stern); get(bits, to_port); get(bits, to_starboard); get(bits, epfd_fix); get(bits, utc_second); get(bits, off_position); get(bits, regional); get(bits, raim); get(bits, virtual_aid_flag); get(bits, assigned); auto rest = bits.size() - SIZE_BITS_MIN; if (rest > 0) { rest = std::min(rest, SIZE_BITS_MAX - SIZE_BITS_MIN); name_extension = read_string(bits, 272, rest / 6); } }
message_18::message_18(const raw & bits) : message_18(ID) { if (bits.size() != SIZE_BITS) throw std::invalid_argument{"invalid number of bits in message_18"}; read_data(bits); }
/// Checks the specified sizes for the raw data. In case of error, an /// exception is thrown (std::invalid_argument). /// /// This check must be done for every message. void message::check_size(const raw & data, size_t size) { assert(size > 2); if (data.size() != size) throw std::invalid_argument{"invalid number of bytes in message"}; if ((data[1] & 0x0f) != static_cast<uint8_t>(size - 3)) throw std::invalid_argument{"invalid size specified in message"}; }
void message_23::read_data(const raw & bits) { bits.get(repeat_indicator, 6, 2); bits.get(mmsi, 8, 30); // spare: 38 - 39 bits.get(ne_lon, 40, 18); bits.get(ne_lat, 58, 17); bits.get(sw_lon, 75, 18); bits.get(sw_lat, 93, 17); bits.get(station_type, 110, 4); bits.get(shiptype, 114, 8); // spare: 122 - 143 bits.get(txrx_mode, 144, 2); bits.get(interval, 146, 4); bits.get(quiet_time, 150, 4); // spare: 154 - 159 }
std::unique_ptr<message> message_10::parse(const raw & bits) { if (bits.size() != SIZE_BITS) throw std::invalid_argument{"invalid number of bits in message_10::parse"}; std::unique_ptr<message> result = utils::make_unique<message_10>(); message_10 & msg = static_cast<message_10 &>(*result); msg.read_data(bits); return result; }
/// Writes the specified string into the AIS message. If the string does not fill /// the entire space within the message, fill characters `@` will be written /// until the specified number of sixbits is reached. /// /// @param[out] bits The AIS message. /// @param[in] ofs The offset at which the string is being written within the message. /// @param[in] count_sixbits Number of sixbits to write into the message. /// @param[in] s The string to be written. /// void binary_data::write_string( raw & bits, raw::size_type ofs, raw::size_type count_sixbits, const std::string & s) { for (raw::size_type i = 0; i < count_sixbits; ++i) { uint8_t value; if (i < s.size()) { value = encode_sixbit_ascii(s[i]); } else { value = encode_sixbit_ascii('@'); } bits.set(value, ofs + i * 6, 6); } }
/// Reads a string from the AIS message at the specified offset. /// The string is decoded and returned. /// /// @param[in] bits The AIS message. /// @param[in] ofs The offset at which the string is being read. /// @param[in] count_sixbits Number of sixbits to be read. /// @return The decoded string. /// /// @todo consider to hide characters after '@' std::string binary_data::read_string( const raw & bits, raw::size_type ofs, raw::size_type count_sixbits) { std::string s; s.reserve(count_sixbits); for (raw::size_type i = 0; i < count_sixbits; ++i) { uint8_t sixbit = 0; bits.get(sixbit, ofs + i * 6, 6); s += decode_sixbit_ascii(sixbit); } return s; }
//writing the results back void memcpy_reverse_w(raw & data, const char * input, int size, int &pos){ if(data.size() < pos+size)throw "Not enough bytes to write;"; for(int i = 0; i < size; i++){data[pos+i] = input[size-i-1];}; pos+=size; };
//raw memory copy from a string void memcpy_reverse(const raw & data, char * output, int size, int &pos){ if(data.size() < pos+size)throw "Not enough bytes to read;"; for(int i = 0; i < size; i++){output[size-i-1]=data[pos+i];}; pos+=size; };
void message_01::read_data(const raw & bits) { bits.get(repeat_indicator, 6, 2); bits.get(mmsi, 8, 30); bits.get(nav_status, 38, 4); bits.get(rot, 42, 8); bits.get(sog, 50, 10); bits.get(position_accuracy, 60, 1); bits.get(longitude_minutes, 61, 28); bits.get(latitude_minutes, 89, 27); bits.get(cog, 116, 12); bits.get(hdg, 128, 9); bits.get(timestamp, 136, 6); bits.get(maneuver_indicator, 143, 2); // spare: 145 - 147 bits.get(raim, 148, 1); bits.get(radio_status, 149, 19); }