Skip to content

Commit 380ed8c

Browse files
authored
feat: add ParseFile wrapping parser.Parse(uri string) (#15)
1 parent a239454 commit 380ed8c

File tree

3 files changed

+91
-16
lines changed

3 files changed

+91
-16
lines changed

go-src/publiccode-parser-wrapper.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,90 @@ func NewParser(disableNetwork C.bool, branch *C.char, baseURL *C.char) C.ParserH
4949
return C.ParserHandle(cgo.NewHandle(p))
5050
}
5151

52+
//export ParseFile
53+
func ParseFile(handle C.ParserHandle, uri *C.char) *C.struct_ParseResult {
54+
result := (*C.struct_ParseResult)(C.calloc(1, C.size_t(C.sizeof_struct_ParseResult)))
55+
result.Data = nil
56+
result.Error = nil
57+
result.ErrorCount = 0
58+
result.Errors = nil
59+
result.WarningCount = 0
60+
result.Warnings = nil
61+
62+
parser, err := toGoParser(handle)
63+
if err != nil {
64+
result.Error = C.CString("Failed create a Parser: " + err.Error())
65+
66+
return result
67+
}
68+
69+
goString := C.GoString(uri)
70+
71+
pc, err := parser.Parse(goString)
72+
73+
if err != nil {
74+
if validationRes, ok := err.(publiccode.ValidationResults); ok {
75+
for _, res := range validationRes {
76+
switch res.(type) {
77+
case publiccode.ValidationError:
78+
result.ErrorCount += 1
79+
case publiccode.ValidationWarning:
80+
result.WarningCount += 1
81+
}
82+
}
83+
84+
var errorsSlice []*C.char
85+
cErrors := unsafe.Pointer(nil)
86+
if result.ErrorCount > 0 {
87+
cErrors = C.malloc(C.size_t(result.ErrorCount) * C.size_t(unsafe.Sizeof(uintptr(0))))
88+
errorsSlice = (*[1 << 28]*C.char)(cErrors)[:result.ErrorCount:result.ErrorCount]
89+
}
90+
91+
var warningsSlice []*C.char
92+
cWarnings := unsafe.Pointer(nil)
93+
if result.WarningCount > 0 {
94+
cWarnings = C.malloc(C.size_t(result.WarningCount) * C.size_t(unsafe.Sizeof(uintptr(0))))
95+
warningsSlice = (*[1 << 28]*C.char)(cWarnings)[:result.WarningCount:result.WarningCount]
96+
}
97+
98+
errIdx := 0
99+
warnIdx := 0
100+
for _, res := range validationRes {
101+
switch res.(type) {
102+
case publiccode.ValidationError:
103+
errorsSlice[errIdx] = C.CString(res.Error())
104+
errIdx += 1
105+
case publiccode.ValidationWarning:
106+
warningsSlice[warnIdx] = C.CString(res.Error())
107+
warnIdx += 1
108+
}
109+
}
110+
111+
result.Errors = (**C.char)(cErrors)
112+
result.Warnings = (**C.char)(cWarnings)
113+
} else {
114+
result.Error = C.CString(err.Error())
115+
116+
return result
117+
}
118+
119+
if result.ErrorCount > 0 {
120+
return result
121+
}
122+
}
123+
124+
jsonData, err := json.Marshal(pc)
125+
if err != nil {
126+
result.Error = C.CString("Failed to marshal result to JSON: " + err.Error())
127+
128+
return result
129+
}
130+
131+
result.Data = C.CString(string(jsonData))
132+
133+
return result
134+
}
135+
52136
//export ParseString
53137
func ParseString(handle C.ParserHandle, content *C.char) *C.struct_ParseResult {
54138
result := (*C.struct_ParseResult)(C.calloc(1, C.size_t(C.sizeof_struct_ParseResult)))

lib/libpubliccode-parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ extern "C" {
9999
#endif
100100

101101
extern ParserHandle NewParser(_Bool disableNetwork, char* branch, char* baseURL);
102+
extern struct ParseResult* ParseFile(ParserHandle handle, char* uri);
102103
extern struct ParseResult* ParseString(ParserHandle handle, char* content);
103104
extern void FreeResult(struct ParseResult* result);
104105
extern void FreeParser(ParserHandle handle);

src/Parser.php

Lines changed: 6 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,25 +70,14 @@ public function parse(string $content): PublicCode
7070
*/
7171
public function parseFile(string $filePath): PublicCode
7272
{
73-
if (!file_exists($filePath)) {
74-
throw new ParserException("File not found: {$filePath}");
75-
}
73+
/** @phpstan-ignore-next-line */
74+
$result = $this->ffi->ParseFile($this->handle, $filePath);
7675

77-
$fp = @fopen($filePath, 'rb');
78-
if ($fp === false) {
79-
throw new ParserException("Cannot open file: {$filePath}");
76+
if ($result === null) {
77+
throw new ParserException("Failed to parse $filePath");
8078
}
8179

82-
try {
83-
$content = stream_get_contents($fp);
84-
if ($content === false) {
85-
throw new ParserException('Failed to read from stream');
86-
}
87-
88-
return $this->parse($content);
89-
} finally {
90-
fclose($fp);
91-
}
80+
return $this->processResult($result);
9281
}
9382

9483
/**
@@ -135,6 +124,7 @@ private function getFFI(): FFI
135124
136125
ParserHandle NewParser(bool disableNetwork, const char* branch, const char* baseURL);
137126
ParseResult* ParseString(ParserHandle handle, const char* content);
127+
ParseResult* ParseFile(ParserHandle handle, const char* uri);
138128
void FreeResult(ParseResult* result);
139129
void FreeParser(ParserHandle handle);
140130
CDEF;

0 commit comments

Comments
 (0)