Skip to content

Commit 11fcf04

Browse files
committed
Support multiple headers for one scala object
1 parent a60fbeb commit 11fcf04

File tree

8 files changed

+84
-33
lines changed

8 files changed

+84
-33
lines changed

bindgen/ir/Location.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class Location {
1212
int getLineNumber() const;
1313

1414
private:
15-
std::string path;
15+
std::string path; // may be empty
1616
int lineNumber;
1717
};
1818

bindgen/ir/LocationManager.cpp

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,13 @@ bool LocationManager::inMainFile(const Location &location) const {
2424
}
2525

2626
bool LocationManager::isImported(const Location &location) const {
27+
if (location.getPath().empty()) {
28+
return false;
29+
}
2730
for (auto it = config.begin(); it != config.end(); ++it) {
28-
json libObject = it.value();
29-
for (const auto &header : libObject["headers"]) {
30-
if (equal(header, location)) {
31+
json lib = it.value();
32+
for (const auto &object : lib["objects"]) {
33+
if (equal(object, location)) {
3134
return true;
3235
}
3336
}
@@ -36,41 +39,63 @@ bool LocationManager::isImported(const Location &location) const {
3639
}
3740

3841
bool LocationManager::equal(json header, const Location &location) const {
39-
std::string headerName = getHeaderName(header);
40-
return endsWith(location.getPath(), headerName);
42+
for (const std::string &headerName : getHeaderNames(header)) {
43+
if (endsWith(location.getPath(), "/" + headerName)) {
44+
return true;
45+
}
46+
}
47+
return false;
4148
}
4249

43-
std::string
44-
LocationManager::getContainingObject(const Location &location) const {
50+
std::string LocationManager::getImportedType(const Location &location,
51+
const std::string &name) const {
4552
for (auto it = config.begin(); it != config.end(); ++it) {
46-
json libObject = it.value();
47-
for (const json &header : libObject["headers"]) {
48-
if (equal(header, location)) {
49-
return getContainingObject(libObject, header);
53+
json lib = it.value();
54+
for (const json &object : lib["objects"]) {
55+
if (equal(object, location)) {
56+
std::string scalaObject = getContainingObject(lib, object);
57+
if (lib.find("names") != lib.end()) {
58+
/* name mapping */
59+
json names = lib["names"];
60+
if (names.find(name) != names.end()) {
61+
return scalaObject + "." +
62+
names[name].get<std::string>();
63+
}
64+
}
65+
return scalaObject + "." + handleReservedWords(name);
5066
}
5167
}
5268
}
5369
throw std::logic_error("Location: " + location.getPath() +
5470
" does not belong to any known library");
5571
}
5672

57-
std::string LocationManager::getHeaderName(const json &header) const {
73+
std::vector<std::string>
74+
LocationManager::getHeaderNames(const json &header) const {
75+
std::vector<std::string> headerNames;
5876
if (header.is_string()) {
59-
return header.get<std::string>();
60-
} else {
61-
return header["header"].get<std::string>();
77+
headerNames.push_back(header.get<std::string>());
78+
} else if (header.is_object()) {
79+
if (header.find("header") != header.end()) {
80+
headerNames.push_back(header["header"].get<std::string>());
81+
} else {
82+
for (const json &h : header["headers"]) {
83+
headerNames.push_back(h.get<std::string>());
84+
}
85+
}
6286
}
87+
return headerNames;
6388
}
6489

65-
std::string LocationManager::getContainingObject(const json &libObject,
90+
std::string LocationManager::getContainingObject(const json &lib,
6691
const json &header) const {
6792
std::string package;
6893
std::string name;
69-
if (libObject.find("package") != libObject.end()) {
70-
package = libObject["package"].get<std::string>();
94+
if (lib.find("package") != lib.end()) {
95+
package = lib["package"].get<std::string>();
7196
}
72-
if (libObject.find("name") != libObject.end()) {
73-
package = libObject["name"].get<std::string>();
97+
if (lib.find("name") != lib.end()) {
98+
package = lib["name"].get<std::string>();
7499
}
75100
if (header.is_object()) {
76101
/* override default values */
@@ -83,7 +108,9 @@ std::string LocationManager::getContainingObject(const json &libObject,
83108
}
84109
if (name.empty()) {
85110
/* extract object name from header name */
86-
name = getHeaderName(header);
111+
std::vector<std::string> names = getHeaderNames(header);
112+
assert(names.size() == 1);
113+
name = names[0];
87114
auto slashPos = name.find_last_of('/');
88115
if (slashPos != std::string::npos) {
89116
name = name.substr(slashPos + 1, name.length());

bindgen/ir/LocationManager.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,18 @@ class LocationManager {
2121
*/
2222
bool isImported(const Location &location) const;
2323

24-
std::string getContainingObject(const Location &location) const;
24+
std::string getImportedType(const Location &location,
25+
const std::string &name) const;
2526

2627
private:
2728
std::string mainHeaderPath;
2829
json config;
2930

3031
bool equal(json header, const Location &location) const;
3132

32-
std::string getHeaderName(const json &header) const;
33+
std::vector<std::string> getHeaderNames(const json &header) const;
3334

34-
std::string getContainingObject(const json &libObject,
35-
const json &header) const;
35+
std::string getContainingObject(const json &lib, const json &header) const;
3636
};
3737

3838
#endif // SCALA_NATIVE_BINDGEN_LOCATIONMANAGER_H

bindgen/ir/TypeDef.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,7 @@ std::string TypeDef::str(const LocationManager &locationManager) const {
4646
if (hasLocation()) {
4747
std::shared_ptr<const Location> location = getLocation();
4848
if (locationManager.isImported(*location)) {
49-
std::string containingObject =
50-
locationManager.getContainingObject(*location);
51-
return containingObject + "." + handleReservedWords(name);
49+
return locationManager.getImportedType(*location, name);
5250
}
5351
}
5452
return handleReservedWords(name);

tests/samples/ReuseBindings.json

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
{
22
"samples": {
33
"package": "org.scalanative.bindgen.samples",
4-
"headers": [
5-
{
6-
"header": "Struct.h"
7-
}
4+
"objects": [
5+
"Struct.h"
86
]
97
}
108
}

tests/samples/ReuseStdio.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#include <stdio.h>
2+
3+
extern FILE myFile;

tests/samples/ReuseStdio.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"libc": {
3+
"package": "scala.scalanative.native",
4+
"objects": [
5+
{
6+
"headers": [
7+
"_stdio.h",
8+
"FILE.h"
9+
],
10+
"name": "stdio"
11+
}
12+
]
13+
}
14+
}
15+

tests/samples/ReuseStdio.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package org.scalanative.bindgen.samples
2+
3+
import scala.scalanative._
4+
import scala.scalanative.native._
5+
6+
@native.link("bindgentests")
7+
@native.extern
8+
object ReuseStdio {
9+
val myFile: scala.scalanative.native.stdio.FILE = native.extern
10+
}

0 commit comments

Comments
 (0)