fork download
  1. #include <cstdlib>
  2.  
  3. #include <vector>
  4. #include <unordered_map>
  5. #include <string>
  6. #include <algorithm>
  7. #include <iostream>
  8.  
  9.  
  10. int main (void)
  11. {
  12. /* Even if a std::string was used, a string literal would not work, because
  13. the fake packet contains '\0'. */
  14. //const std::vector<char> msg{"add@/sys/devices\0SUBSYSTEM=block\0DEVTYPE=partition"};
  15. const std::vector<char> msg{
  16. 'a','d','d','@','/','s','y','s','/','d','e','v','i','c','e','s','\0',
  17. 'S','U','B','S','Y','S','T','E','M','=','b','l','o','c','k','\0','D',
  18. 'E','V','T','Y','P','E','=','p','a','r','t','i','t','i','o','n','\0'
  19. };
  20.  
  21. std::unordered_map<std::string , std::string> hotplug_event_variables;
  22.  
  23. auto it1 = std::find( msg.begin() , msg.end() , '@' );
  24. if ( it1 != msg.end() )
  25. {
  26. /* As per the kernel documentation, the piece before the '@' token is
  27. the implicit "ACTION" event variable. */
  28. hotplug_event_variables.emplace( std::piecewise_construct , std::forward_as_tuple("ACTION") , std::forward_as_tuple(msg.begin(),it1) );
  29.  
  30. /* It points to the '@'; increment it. */
  31. ++it1;
  32.  
  33. auto it2 = std::find( it1 , msg.end() , '\0' );
  34. if ( it2 != msg.end() )
  35. {
  36. /* As with the previous event variable, DEVPATH is implicit. */
  37. hotplug_event_variables.emplace( std::piecewise_construct , std::forward_as_tuple("DEVPATH") , std::forward_as_tuple(it1,it2) );
  38.  
  39. /* It points to the '\0'; increment it. */
  40. ++it2;
  41.  
  42. /*
  43. * An example packet:
  44. *
  45. * Pass of the loop
  46. * |$ACTION@$DEVPATH0·····=·····0······=······0|
  47. * ^^ ^^ ^ ^^ ^ ^
  48. * it1 it2 | || | |
  49. * #1 it2 it3 it4 | |
  50. * #2 it2 it3 it4
  51. */
  52. for ( auto it3 = std::find( it2 , msg.end() , '=' ) , it4 = std::find( it3+1 , msg.end() , '\0') ; it2 != msg.end() , it3 != msg.end() , it4 != msg.end() ; it2 = it4+1 , it3 = std::find( it2 , msg.end() , '=' ) , it4 = std::find( it3 , msg.end() , '\0' ) )
  53. {
  54. /* While playing with the fake packet, I found that empty pairs
  55. could made it into the map. */
  56. if ( std::distance(it2,it3) > 0 && std::distance(it3+1,it4) > 0 )
  57. {
  58. hotplug_event_variables.emplace( std::piecewise_construct , std::forward_as_tuple(it2,it3) , std::forward_as_tuple(it3+1,it4) );
  59. }
  60. }
  61.  
  62. /*
  63. * Expected output:
  64. *
  65. * "ACTION" = "add"
  66. * "DEVPATH" = "/sys/devices"
  67. * "SUBSYSTEM" = "block"
  68. * "DEVTYPE" = "partition"
  69. */
  70. for ( const auto & x : hotplug_event_variables )
  71. {
  72. std::cout << '"' << x.first << "\" = \"" << x.second << "\"\n";
  73. }
  74. }
  75. }
  76.  
  77. return EXIT_SUCCESS;
  78. }
Success #stdin #stdout 0.01s 3484KB
stdin
Standard input is empty
stdout
"DEVTYPE" = "partition"
"SUBSYSTEM" = "block"
"DEVPATH" = "/sys/devices"
"ACTION" = "add"