user_file.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. // Copyright (C) 2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #ifndef _USER_FILE_H
  15. #define _USER_FILE_H
  16. /// @file user_file.h Defines the class, UserFile, which implements the UserDataSource interface for text files.
  17. #include <user_data_source.h>
  18. #include <user.h>
  19. #include <boost/shared_ptr.hpp>
  20. #include <fstream>
  21. #include <string>
  22. namespace user_chk {
  23. /// @brief Thrown a UserFile encounters an error.
  24. /// Note that it derives from UserDataSourceError to comply with the interface.
  25. class UserFileError : public UserDataSourceError {
  26. public:
  27. UserFileError(const char* file, size_t line, const char* what) :
  28. UserDataSourceError(file, line, what)
  29. {}
  30. };
  31. /// @brief Provides a UserDataSource implementation for JSON text files.
  32. /// This class allows a text file of JSON entries to be treated as a source of
  33. /// User entries. The format of the file is one user entry per line, where
  34. /// each line contains a JSON string as follows:
  35. ///
  36. /// { "type" : "<user type>", "id" : "<user_id>" (options) }
  37. ///
  38. /// where:
  39. ///
  40. /// &lt;user_type&gt; text label of the id type: "HW_ADDR" or "DUID"
  41. /// &lt;user_id&gt; the user's id as a string of hex digits with or without
  42. /// colons (':') as a delimiter
  43. /// (options) zero or more string elements as name-value pairs, separated by
  44. /// commas: "opt1" : "val1", "other_opt", "77" ...
  45. ///
  46. /// Each entry must have a valid entry for "type" and a valid entry or "id".
  47. ///
  48. /// If an entry contains duplicate option names, that option will be assigend
  49. /// the last value found. This is typical JSON behavior.
  50. /// Currently, only string option values (i.e. enclosed in quotes) are
  51. /// supported.
  52. ///
  53. /// Example file entries might look like this:
  54. /// @code
  55. ///
  56. /// { "type" : "HW_ADDR", "id" : "01AC00F03344", "opt1" : "true" }
  57. /// { "type" : "DUID", "id" : "225060de0a0b", "opt1" : "false" }
  58. ///
  59. /// @endcode
  60. class UserFile : public UserDataSource {
  61. public:
  62. /// @brief Maximum length of a single user entry.
  63. /// This value is somewhat arbitrary. 4K seems reasonably large. If it
  64. /// goes beyond this, then a flat file is not likely the way to go.
  65. static const size_t USER_ENTRY_MAX_LEN = 4096;
  66. /// @brief Constructor
  67. ///
  68. /// Create a UserFile for the given file name without opening the file.
  69. /// @param fname pathname to the input file.
  70. ///
  71. /// @throw UserFileError if given file name is empty.
  72. UserFile(const std::string& fname);
  73. /// @brief Destructor.
  74. ////
  75. /// The destructor does call the close method.
  76. virtual ~UserFile();
  77. /// @brief Opens the input file for reading.
  78. ///
  79. /// Upon successful completion, the file is opened and positioned to start
  80. /// reading from the beginning of the file.
  81. ///
  82. /// @throw UserFileError if the file cannot be opened.
  83. virtual void open();
  84. /// @brief Fetches the next user from the file.
  85. ///
  86. /// Reads the next user entry from the file and attempts to create a
  87. /// new User from the text therein. If there is no more data to be read
  88. /// it returns an empty UserPtr.
  89. ///
  90. /// @return A UserPtr pointing to the new User or an empty pointer on EOF.
  91. ///
  92. /// @throw UserFileError if an error occurs while reading.
  93. virtual UserPtr readNextUser();
  94. /// @brief Closes the underlying file.
  95. ///
  96. /// Method is exception safe.
  97. virtual void close();
  98. /// @brief Returns true if the file is open.
  99. ///
  100. /// @return True if the underlying file is open, false otherwise.
  101. virtual bool isOpen() const;
  102. /// @brief Creates a new User instance from JSON text.
  103. ///
  104. /// @param user_string string the JSON text for a user entry.
  105. ///
  106. /// @return A pointer to the newly created User instance.
  107. ///
  108. /// @throw UserFileError if the entry is invalid.
  109. UserPtr makeUser(const std::string& user_string);
  110. private:
  111. /// @brief Pathname of the input text file.
  112. std::string fname_;
  113. /// @brief Input file stream.
  114. std::ifstream file_;
  115. };
  116. /// @brief Defines a smart pointer to a UserFile.
  117. typedef boost::shared_ptr<UserFile> UserFilePtr;
  118. } // namespace user_chk
  119. #endif