@@ -4714,7 +4714,111 @@ namespace SpecUtils
47144714
47154715 return new_data_end;
47164716 }// convert_n42_utf16_xml_to_utf8
4717-
4717+
4718+
4719+ bool rsi_portal_xml_to_n42_hack ( char * &data, char * &data_end )
4720+ {
4721+ assert ( data <= data_end );
4722+ if ( data_end < data )
4723+ throw logic_error ( " Invalid start-end of data" ); // shouldnt ever happen
4724+
4725+ const size_t orig_len = (data_end - data);
4726+ if ( orig_len < 1024 )
4727+ return false ;
4728+
4729+ // If '<MessageEnvelope' is not found within the first 512 characters, then return false
4730+ // if '<n42:RadInstrumentData>' is not found within the first 8192 characters, return false.
4731+ // Go through and replace all instances of "<n42:" with " <"
4732+ // Go through and replace all instances of "</n42:" with " </"
4733+ // Make `data` point at the first instance of "<RadInstrumentData>"
4734+ // Make `data_end` point one position past the first following "</RadInstrumentData>"
4735+
4736+ // Define string literals
4737+ const char message_envelope[] = " <MessageEnvelope" ;
4738+ const size_t message_envelope_len = (sizeof (message_envelope) / sizeof (message_envelope[0 ])) - 1 ;
4739+
4740+ const char rad_instrument_data[] = " <n42:RadInstrumentData>" ;
4741+ const size_t rad_instrument_data_len = (sizeof (rad_instrument_data) / sizeof (rad_instrument_data[0 ])) - 1 ;
4742+
4743+ const char rad_instrument_data_start[] = " <RadInstrumentData>" ;
4744+ const size_t rad_instrument_data_start_len = (sizeof (rad_instrument_data_start) / sizeof (rad_instrument_data_start[0 ])) - 1 ;
4745+
4746+ const char rad_instrument_data_end[] = " </RadInstrumentData>" ;
4747+ const size_t rad_instrument_data_end_len = (sizeof (rad_instrument_data_end) / sizeof (rad_instrument_data_end[0 ])) - 1 ;
4748+
4749+ const char n42_open[] = " <n42:" ;
4750+ const size_t n42_open_len = (sizeof (n42_open) / sizeof (n42_open[0 ])) - 1 ;
4751+ const char n42_close[] = " </n42:" ;
4752+ const size_t n42_close_len = (sizeof (n42_close) / sizeof (n42_close[0 ])) - 1 ;
4753+ const char replacement_open[] = " <" ;
4754+ const size_t replacement_open_len = (sizeof (replacement_open) / sizeof (replacement_open[0 ])) - 1 ;
4755+ const char replacement_close[] = " </" ;
4756+ const size_t replacement_close_len = (sizeof (replacement_close) / sizeof (replacement_close[0 ])) - 1 ;
4757+
4758+ static_assert ( sizeof (n42_open) == sizeof (replacement_open), " Mismatch on n42 open str len" );
4759+ static_assert ( sizeof (n42_close) == sizeof (replacement_close), " Mismatch on n42 open str len" );
4760+
4761+ // Check for '<MessageEnvelope' within the first 512 characters
4762+ const size_t envelope_search_len = std::min (size_t (512 ), orig_len);
4763+ char * const message_envelope_pos = std::search ( data, data + envelope_search_len,
4764+ message_envelope, message_envelope + message_envelope_len);
4765+ if ( message_envelope_pos == (data + envelope_search_len) )
4766+ return false ;
4767+
4768+ // Check for '<n42:RadInstrumentData>' within the first 8192 characters
4769+ const size_t rad_instrument_search_len = std::min (size_t (8192 ), orig_len);
4770+ char *rad_instrument_pos = std::search (data, data + rad_instrument_search_len,
4771+ rad_instrument_data, rad_instrument_data + rad_instrument_data_len);
4772+ if ( rad_instrument_pos == (data + rad_instrument_search_len) )
4773+ return false ;
4774+
4775+ // If we are here, we are probably in the target rsi portal file
4776+
4777+ // Replace all instances of "<n42:" with " <"
4778+ char *pos = data;
4779+ while ( pos < (data_end - n42_open_len) )
4780+ {
4781+ pos = std::search (pos, data_end, n42_open, n42_open + n42_open_len);
4782+ if ( pos == data_end )
4783+ break ; // No more occurrences
4784+ std::memcpy (pos, replacement_open, replacement_open_len);
4785+ pos += n42_open_len; // Move past the replaced substring
4786+ }
4787+
4788+
4789+ // Replace all instances of "</n42:" with " <"
4790+ pos = data;
4791+ while ( pos < (data_end - n42_close_len) )
4792+ {
4793+ pos = std::search (pos, data_end, n42_close, n42_close + n42_close_len);
4794+ if ( pos == data_end )
4795+ break ; // No more occurrences
4796+ std::memcpy (pos, replacement_close, replacement_close_len);
4797+ pos += n42_close_len; // Move past the replaced substring
4798+ }
4799+
4800+ // Make `data` point at the first instance of "<RadInstrumentData>"
4801+ char *rad_data_start = std::search (data, data_end,
4802+ rad_instrument_data_start, rad_instrument_data_start + rad_instrument_data_start_len);
4803+ assert ( rad_data_start < data_end );
4804+
4805+ if ( rad_data_start == data_end )
4806+ return false ; // "<RadInstrumentData>" not found
4807+
4808+ data = rad_data_start;
4809+
4810+ // Make `data_end` point one position past the first following "</RadInstrumentData>"
4811+ char *rad_data_end = std::search (rad_data_start, data_end,
4812+ rad_instrument_data_end, rad_instrument_data_end + rad_instrument_data_end_len);
4813+ if ( rad_data_end == data_end )
4814+ return false ; // "</RadInstrumentData>" not found
4815+
4816+ data_end = rad_data_end + rad_instrument_data_end_len;
4817+
4818+ return true ;
4819+ }// bool rsi_portal_xml_to_n42_hack( char* &data, char* &data_end )
4820+
4821+
47184822 bool SpecFile::load_from_N42 ( std::istream &input )
47194823 {
47204824 std::unique_lock<std::recursive_mutex> scoped_lock ( mutex_ );
@@ -8867,10 +8971,11 @@ namespace SpecUtils
88678971 reset ();
88688972
88698973 data_end = convert_n42_utf16_xml_to_utf8 ( data, data_end );
8974+ rsi_portal_xml_to_n42_hack ( data, data_end );
88708975
88718976 // Some times a bunch of null characters can get appended to the end
88728977 // of the file - lets remove them, or rapidxml::parse will fail.
8873- // TODO: bet yet, we should look for the last '>' character, or even better, the last valid closing tag
8978+ // TODO: better yet, we should look for the last '>' character, or even better, the last valid closing tag
88748979 while ( ((data_end - data) > 2 ) && ((*(data_end - 1 )) == ' \0 ' ) )
88758980 --data_end;
88768981
0 commit comments