11#include  " LocationManager.h" 
22#include  " ../Utils.h" 
3- #include  " Enum.h" 
4- #include  " Struct.h" 
5- #include  < fstream> 
6- #include  < stdexcept> 
3+ #include  < llvm/Support/MemoryBuffer.h> 
4+ #include  < llvm/Support/YAMLTraits.h> 
75
8- LocationManager::LocationManager (std::string mainHeaderPath)
9-     : mainHeaderPath(std::move(mainHeaderPath)) {}
10- 
11- void  LocationManager::loadConfig (const  std::string &path) {
12-     std::string realPath = getRealPath (path.c_str ());
13- 
14-     std::stringstream s;
15-     std::ifstream input (realPath);
16-     for  (std::string line; getline (input, line);) {
17-         s << line;
6+ template  <> struct  llvm ::yaml::MappingTraits<HeaderEntry> {
7+     static  void  mapping (llvm::yaml::IO &io, HeaderEntry &headerEntry) {
8+         io.mapRequired (" path" path );
9+         io.mapRequired (" object" object );
10+         io.mapOptional (" names" names );
1811    }
19-     config = json::parse (s.str ());
20-     validateConfig (config);
21- }
12+ };
2213
23- void  LocationManager::validateConfig (const  json &config) const  {
24-     if  (!config.is_object ()) {
25-         throw  std::invalid_argument (
26-             " Invalid configuration. Configuration should be an object." 
27-     }
28-     for  (auto  it = config.begin (); it != config.end (); ++it) {
29-         std::string headerName = it.key ();
30-         if  (headerName.empty ()) {
31-             throw  std::invalid_argument (" Invalid configuration. Header name " 
32-                                         " should not be an empty string." 
14+ template  <> struct  llvm ::yaml::MappingTraits<HeaderEntryName> {
15+     static  void  mapping (llvm::yaml::IO &io, HeaderEntryName &headerEntryName) {
16+         //  Dynamically look up the available keys when only one key is given.
17+         // 
18+         //  ```yaml
19+         //   - struct point: Point
20+         //  ```
21+         if  (io.keys ().size () == 1 ) {
22+             for  (auto  key : io.keys ()) {
23+                 headerEntryName.original  = key;
24+                 io.mapRequired (headerEntryName.original .c_str (),
25+                                headerEntryName.target );
26+             }
27+         } else  {
28+             io.mapRequired (" original" original );
29+             io.mapRequired (" target" target );
3330        }
34-         json headerEntry = it.value ();
35-         validateHeaderEntry (headerEntry);
3631    }
37- }
32+ }; 
3833
39- void  LocationManager::validateHeaderEntry (const  json &headerEntry) const  {
40-     if  (headerEntry.is_string ()) {
41-         std::string object = headerEntry.get <std::string>();
42-         if  (object.empty ()) {
43-             throw  std::invalid_argument (" Invalid configuration. Each header " 
44-                                         " entry should contain non-empty " 
45-                                         " value." 
46-         }
47-     } else  if  (headerEntry.is_object ()) {
48-         std::unordered_set<std::string> headerKeys = {" object" " names" 
49-         validateKeys (headerEntry, headerKeys);
50-         if  (headerEntry.find (" object" end ()) {
51-             throw  std::invalid_argument (" Invalid configuration. Header entry " 
52-                                         " that is represented as an object " 
53-                                         " should contain 'object' property." 
54-         }
55-         json object = headerEntry[" object" 
56-         if  (!object.is_string () || object.get <std::string>().empty ()) {
57-             throw  std::invalid_argument (" Invalid configuration. 'object' " 
58-                                         " property should be a not empty " 
59-                                         " string." 
60-         }
61-         if  (headerEntry.find (" name" end ()) {
62-             validateNames (headerEntry[" names" 
63-         }
64-     } else  {
65-         throw  std::invalid_argument (" Invalid configuration. Header entry " 
66-                                     " should be a string or an object." 
67-     }
68- }
34+ LLVM_YAML_IS_SEQUENCE_VECTOR (HeaderEntry)
35+ LLVM_YAML_IS_SEQUENCE_VECTOR(HeaderEntryName)
6936
70- void  LocationManager::validateKeys (
71-     const  json &object, const  std::unordered_set<std::string> &keys) const  {
72-     for  (auto  it = object.begin (); it != object.end (); ++it) {
73-         if  (keys.find (it.key ()) == keys.end ()) {
74-             throw  std::invalid_argument (
75-                 " Invalid configuration. Unknown key: '" key () + " '." 
76-         }
77-     }
78- }
37+ LocationManager::LocationManager(std::string mainHeaderPath)
38+     : headerEntries(), mainHeaderPath(std::move(mainHeaderPath)) {}
7939
80- void  LocationManager::validateNames (const  json &names) const  {
81-     if  (!names.is_object ()) {
82-         throw  std::invalid_argument (" Invalid configuration. Library property " 
83-                                     " 'names' should be an object." 
84-     }
85-     for  (auto  it = names.begin (); it != names.end (); ++it) {
86-         if  (!it.value ().is_string ()) {
87-             throw  std::invalid_argument (
88-                 " Invalid configuration. property 'names'" 
89-                 "  should contain only string values." 
90-         }
91-     }
40+ bool  LocationManager::loadConfig (const  std::string &path) {
41+     llvm::SmallString<4096 > realPath;
42+     if  (llvm::sys::fs::real_path (path, realPath))
43+         return  false ;
44+ 
45+     llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> mb =
46+         llvm::MemoryBuffer::getFile (realPath);
47+     if  (!mb)
48+         return  false ;
49+ 
50+     llvm::yaml::Input input (mb->get ()->getBuffer ());
51+     input >> headerEntries;
52+     return  true ;
9253}
9354
9455bool  LocationManager::inMainFile (const  Location &location) const  {
@@ -99,40 +60,36 @@ bool LocationManager::isImported(const Location &location) const {
9960    if  (location.getPath ().empty ()) {
10061        return  false ;
10162    }
102-     json headerEntry = getHeaderEntry (location);
103-     return  !headerEntry.empty ();
63+     return  getHeaderEntryIndex (location) != headerEntries.size ();
10464}
10565
106- json LocationManager::getHeaderEntry (const  Location &location) const  {
107-     for  (auto  it = config.begin (); it != config.end (); ++it) {
108-         std::string pathToHeader = it.key ();
109-         if  (startsWith (pathToHeader, " /" 
110-             /*  full path */ 
111-             if  (location.getPath () == pathToHeader) {
112-                 return  it.value ();
113-             }
114-         } else  if  (endsWith (location.getPath (), " /" 
115-             return  it.value ();
116-         }
117-     }
118-     return  json::object ();
66+ std::vector<HeaderEntry>::size_type
67+ LocationManager::getHeaderEntryIndex (const  Location &location) const  {
68+     auto  isHeader = [&](const  HeaderEntry &headerEntry) {
69+         if  (startsWith (headerEntry.path , " /" 
70+             location.getPath () == headerEntry.path )
71+             return  true ;
72+         return  endsWith (location.getPath (), " /" path );
73+     };
74+     auto  it =
75+         std::find_if (headerEntries.begin (), headerEntries.end (), isHeader);
76+     return  it - headerEntries.begin ();
11977}
12078
12179std::string LocationManager::getImportedType (const  Location &location,
12280                                             const  std::string &name) const  {
123-     json headerEntry = getHeaderEntry (location);
124-     if  (headerEntry.is_string ()) {
125-         return  headerEntry.get <std::string>() + " ." 
126-                handleReservedWords (replaceChar (name, "  " " _" 
127-     }
128-     std::string scalaObject = headerEntry[" object" 
81+     auto  index = getHeaderEntryIndex (location);
82+     if  (index == headerEntries.size ())
83+         return  name;
84+ 
85+     auto  headerEntry = headerEntries[index];
12986
130-     if  (headerEntry.find (" names" end ()) {
131-         /*  name mapping */ 
132-         json names = headerEntry[" names" 
133-         if  (names.find (name) != names.end ()) {
134-             return  scalaObject + " ." get <std::string>();
87+     for  (auto  const  &headerEntryName : headerEntry.names ) {
88+         if  (headerEntryName.original  == name) {
89+             return  headerEntry.object  + " ." target ;
13590        }
13691    }
137-     return  scalaObject + " ." handleReservedWords (replaceChar (name, "  " " _" 
92+ 
93+     return  headerEntry.object  + " ." 
94+            handleReservedWords (replaceChar (name, "  " " _" 
13895}
0 commit comments