Skip to content

Commit 7ee7120

Browse files
committed
feat: add Go bindings for CSV file handling and JSON conversion
1 parent 6b7771d commit 7ee7120

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

go_bindings/csv.go

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
package csv
2+
3+
/*
4+
#include <stdlib.h>
5+
*/
6+
import "C"
7+
import (
8+
"encoding/csv"
9+
"encoding/json"
10+
"os"
11+
"strings"
12+
)
13+
14+
// CSVData represents structured CSV output.
15+
type CSVData struct {
16+
Headers []string `json:"headers"`
17+
Rows [][]string `json:"rows"`
18+
}
19+
20+
//export LoadCSV
21+
func (c *CSVData) LoadCSV(filePath *C.char) *C.char {
22+
23+
goFilePath := C.GoString(filePath)
24+
file, err := os.Open(goFilePath)
25+
26+
if err != nil {
27+
return C.CString(`{"error": "CSV File Not Found"}`)
28+
}
29+
defer file.Close()
30+
31+
reader := csv.NewReader(file)
32+
33+
// Read headers
34+
headers, err := reader.Read()
35+
if err != nil {
36+
return C.CString(`{"error": "Failed to read headers"}`)
37+
}
38+
headers = trimSpaces(headers)
39+
40+
// ! STORE THE CSV FILE HEADERS IN MEMORY FOR DOING REDUNDANT FILE-IO
41+
c.Headers = headers
42+
43+
// Read rows
44+
var rows [][]string
45+
records, err := reader.ReadAll()
46+
if err != nil {
47+
return C.CString(`{"error": "Failed to read rows"}`)
48+
}
49+
50+
for _, record := range records {
51+
52+
row := trimSpaces(record)
53+
54+
if allEmpty(row) {
55+
continue
56+
}
57+
58+
// Fill missing values
59+
for len(row) < len(headers) {
60+
row = append(row, "N/A")
61+
}
62+
63+
if len(row) > len(headers) {
64+
row = row[:len(headers)]
65+
}
66+
67+
rows = append(rows, row)
68+
}
69+
70+
// ! STORE THE CSV FILE HEADERS IN MEMORY FOR DOING REDUNDANT FILE-IO
71+
c.Rows = rows
72+
73+
// Convert to JSON
74+
csvData := CSVData{Headers: headers, Rows: rows}
75+
jsonData, _ := json.Marshal(csvData)
76+
77+
// Return JSON as C string
78+
return C.CString(string(jsonData))
79+
}
80+
81+
//export filterRows
82+
func (c *CSVData) filterRows(column *C.char, condition *C.char, writeToFile *C.int, outputFile *C.char) **C.char {
83+
goColumn := C.GoString(column)
84+
goCondition := C.GoString(condition)
85+
goOutputFile := C.GoString(outputFile)
86+
writeToFileFlag := int(writeToFile) != 0
87+
88+
// Find column index
89+
colIdx := -1
90+
for i, h := range c.Headers {
91+
if strings.TrimSpace(h) == goColumn {
92+
colIdx = i
93+
break
94+
}
95+
}
96+
97+
if colIdx == -1 {
98+
return nil // Column not found
99+
}
100+
101+
// Filter rows
102+
filteredRows := [][]string{c.Headers}
103+
for _, row := range c.Rows {
104+
if colIdx < len(row) && row[colIdx] == goCondition {
105+
filteredRows = append(filteredRows, row)
106+
}
107+
}
108+
109+
// Write to file if required
110+
if writeToFileFlag {
111+
outFile, err := os.Create(goOutputFile)
112+
if err == nil {
113+
defer outFile.Close()
114+
writer := csv.NewWriter(outFile)
115+
writer.WriteAll(filteredRows)
116+
writer.Flush()
117+
}
118+
}
119+
120+
// Convert to C-compatible char array
121+
result := make([]*C.char, len(filteredRows))
122+
for i, row := range filteredRows {
123+
result[i] = C.CString(strings.Join(row, ","))
124+
}
125+
126+
return &result[0]
127+
}
128+
129+
func trimSpaces(s []string) []string {
130+
for i, v := range s {
131+
s[i] = strings.TrimSpace(v)
132+
}
133+
return s
134+
}
135+
136+
func allEmpty(row []string) bool {
137+
for _, cell := range row {
138+
if cell != "" {
139+
return false
140+
}
141+
}
142+
return true
143+
}
144+
145+
func main() {}

0 commit comments

Comments
 (0)