/** * This function decodes a message into either the NegotiationData or GuessData structs depending * on what the type of message is. This function receives the message one byte at a time, where the * messages are in the format defined by MESSAGE_TEMPLATE, with payloads of the format defined by * the PAYLOAD_TEMPLATE_* macros. It returns the type of message that was decoded and also places * the decoded data into either the `nData` or `gData` structs depending on what the message held. * The onus is on the calling function to make sure the appropriate structs are available (blame the * lack of function overloading in C for this ugliness). * * PROTOCOL_PARSING_FAILURE is returned if there was an error of any kind (though this excludes * checking for NULL pointers), while * * @param parser The struct holding the data for this instance of the parser. Allows for multiple * protocol decoding streams. * @param in The next character in the NMEA0183 message to be decoded. * @param nData A struct used for storing data if a message is decoded that stores NegotiationData. * @param gData A struct used for storing data if a message is decoded that stores GuessData. * @return A value from the UnpackageDataEnum enum. */ ProtocolParserStatus ProtocolDecode(char in, NegotiationData *nData, GuessData *gData) { static int i; static uint8_t expSum; switch (p.state) { //WATING case case (WAITING) : { //Recycle WAITING if (in != '$') { p.state = WAITING; return PROTOCOL_WAITING; } //Enter RECORDING else if (in == '$') { i = 0; p.state = RECORDING; return PROTOCOL_PARSING_GOOD; } break; } //RECORDING case case (RECORDING) : { //Recycle RECORDING if (in != '*') { sentence[i] = in; i += 1; p.state = RECORDING; return PROTOCOL_PARSING_GOOD; } //Enter FIRSTCHECKSUMHALF else if (in == '*') { p.state = FIRST_CHECKSUM_HALF; return PROTOCOL_PARSING_GOOD; } break; } //FIRSTCHECKSUMHALF case case (FIRST_CHECKSUM_HALF) : { //If given valid Hex Data continue accordingly if (((in >= 'A') && (in <= 'F')) || ((in >= 'a') && (in <= 'f')) || ((in >= '0') && (in <= '9'))) { p.checkSum = (ConvertAscii(in) << 4); p.state = SECOND_CHECKSUM_HALF; return PROTOCOL_PARSING_GOOD; } //Given invalid hex data enter WAITING else { p.state = WAITING; return PROTOCOL_PARSING_FAILURE; } break; } //SECONDCHECKSUM case case (SECOND_CHECKSUM_HALF) : { //Calculate the expected checkSum expSum = CreateCheckSum(i, sentence); //If given VALID hex data and continue if (((in >= 'A') && (in <= 'F')) || ((in >= 'a') && (in <= 'f')) || ((in >= '0') && (in <= '9'))) { //Finish assembling the Checksum thats read p.checkSum |= ConvertAscii(in); printf("Checksum is: %x\nExpChecksum is: %x\n", p.checkSum, expSum); //If the two checkSums ARE equal pass GOOD and enter NEWLINE if (p.checkSum == expSum) { sentence[i] = '\0'; p.state = NEWLINE; return PROTOCOL_PARSING_GOOD; } //If they ARENT equal then pass failure and enter WAITING else { p.state = WAITING; return PROTOCOL_PARSING_FAILURE; } } //Given INVALID hex data return FAILURE and enter WAITING else { p.state = WAITING; return PROTOCOL_PARSING_FAILURE; } break; } //NEWINE case case (NEWLINE) : { //If GIVEN a newline terminated string then evalauate the message //Check what kind of message it is if (in == '\n') { //Check which C message it is if (sentence[0] == 'C') { //return CHA_MESSAGE and enter WAITING if (sentence[1] == 'H') { sscanf(sentence, PAYLOAD_TEMPLATE_CHA, &(nData->encryptedGuess), &(nData->hash)); p.state = WAITING; return PROTOCOL_PARSED_CHA_MESSAGE; } //return COO_MESSAGE and enter WAITING else { sscanf(sentence, PAYLOAD_TEMPLATE_COO, &(gData->row), &(gData->col)); p.state = WAITING; return PROTOCOL_PARSED_COO_MESSAGE; } } //return DET_MESSAGE and enter WAITING else if (sentence[0] == 'D') { sscanf(sentence, PAYLOAD_TEMPLATE_DET, &(nData->guess), &(nData->encryptionKey)); p.state = WAITING; return PROTOCOL_PARSED_DET_MESSAGE; } //return HIT_MESSAGE and enter WAITING else if (sentence[0] == 'H') { sscanf(sentence, PAYLOAD_TEMPLATE_HIT, &(gData->row), &(gData->col), &(gData->hit)); p.state = WAITING; return PROTOCOL_PARSED_HIT_MESSAGE; } } //If NOT GIVEN a newline terminated string then evalauate the message //return FAILURE and enter WAITING else { p.state = WAITING; return PROTOCOL_PARSING_FAILURE; } break; } //Default to waiting just in case of failure default : { p.state = WAITING; return PROTOCOL_PARSING_FAILURE; break; } } //In case it didnt hit anything then indicate a failure return PROTOCOL_PARSING_FAILURE; }
SqlVal GetCsAsciiVal(const SqlVal& val) { return ConvertAscii(GetCsVal(val)); }