272 lines
6.5 KiB
Go
272 lines
6.5 KiB
Go
package main
|
||
|
||
/*
|
||
#include <stdlib.h>
|
||
*/
|
||
import "C"
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"io"
|
||
"net/http"
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
"unsafe"
|
||
|
||
"gopkg.in/ini.v1"
|
||
"gopkg.in/yaml.v3"
|
||
)
|
||
|
||
// ConfigReader 配置文件读取器接口
|
||
type ConfigReader interface {
|
||
ReadConfig(data []byte) (string, error)
|
||
}
|
||
|
||
// JSONConfigReader JSON配置文件读取器
|
||
type JSONConfigReader struct{}
|
||
|
||
func (r *JSONConfigReader) ReadConfig(data []byte) (string, error) {
|
||
var result map[string]interface{}
|
||
if err := json.Unmarshal(data, &result); err != nil {
|
||
if strings.Contains(err.Error(), "cannot unmarshal array into Go value of type map[string]interface {}") {
|
||
// 尝试解析为数组
|
||
var arrayResult []map[string]interface{}
|
||
if arrayErr := json.Unmarshal(data, &arrayResult); arrayErr != nil {
|
||
return "", fmt.Errorf("JSON解析错误: %v", err)
|
||
}
|
||
arrayResultStr, err := json.Marshal(arrayResult)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(arrayResultStr), nil
|
||
}
|
||
return "", fmt.Errorf("JSON解析错误: %v", err)
|
||
}
|
||
resultStr, err := json.Marshal(result)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(resultStr), nil
|
||
}
|
||
|
||
// YAMLConfigReader YAML配置文件读取器
|
||
type YAMLConfigReader struct{}
|
||
|
||
func (r *YAMLConfigReader) ReadConfig(data []byte) (string, error) {
|
||
var result map[string]interface{}
|
||
if err := yaml.Unmarshal(data, &result); err != nil {
|
||
return "", fmt.Errorf("YAML解析错误: %v", err)
|
||
}
|
||
resultStr, err := json.Marshal(result)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(resultStr), nil
|
||
}
|
||
|
||
// INIConfigReader INI配置文件读取器
|
||
type INIConfigReader struct{}
|
||
|
||
func (r *INIConfigReader) ReadConfig(data []byte) (string, error) {
|
||
cfg, err := ini.Load(data)
|
||
if err != nil {
|
||
return "", fmt.Errorf("INI解析错误: %v", err)
|
||
}
|
||
|
||
result := make(map[string]interface{})
|
||
|
||
// 将INI结构转换为map
|
||
for _, section := range cfg.Sections() {
|
||
sectionName := section.Name()
|
||
if sectionName == "DEFAULT" {
|
||
sectionName = "default"
|
||
}
|
||
|
||
sectionMap := make(map[string]interface{})
|
||
for _, key := range section.Keys() {
|
||
sectionMap[key.Name()] = key.Value()
|
||
}
|
||
|
||
// 如果是默认节,直接合并到顶层
|
||
if sectionName == "default" {
|
||
for k, v := range sectionMap {
|
||
result[k] = v
|
||
}
|
||
} else {
|
||
result[sectionName] = sectionMap
|
||
}
|
||
}
|
||
resultStr, err := json.Marshal(result)
|
||
if err != nil {
|
||
return "", fmt.Errorf("JSON序列化失败: %v", err)
|
||
}
|
||
return string(resultStr), nil
|
||
}
|
||
|
||
// ConfigProcessor 配置处理器
|
||
type ConfigProcessor struct {
|
||
readers map[string]ConfigReader
|
||
}
|
||
|
||
// NewConfigProcessor 创建配置处理器
|
||
func NewConfigProcessor() *ConfigProcessor {
|
||
return &ConfigProcessor{
|
||
readers: map[string]ConfigReader{
|
||
"json": &JSONConfigReader{},
|
||
"yaml": &YAMLConfigReader{},
|
||
"yml": &YAMLConfigReader{},
|
||
"ini": &INIConfigReader{},
|
||
"conf": &INIConfigReader{},
|
||
},
|
||
}
|
||
}
|
||
|
||
// GetFileExtension 获取文件扩展名
|
||
func (p *ConfigProcessor) GetFileExtension(fileName string) string {
|
||
ext := strings.ToLower(filepath.Ext(fileName))
|
||
if ext != "" {
|
||
return ext[1:] // 去掉点号
|
||
}
|
||
return ""
|
||
}
|
||
|
||
// GetReader 根据文件扩展名获取对应的读取器
|
||
func (p *ConfigProcessor) GetReader(fileName string) (ConfigReader, error) {
|
||
ext := p.GetFileExtension(fileName)
|
||
if ext == "" {
|
||
return nil, fmt.Errorf("无法识别文件类型: %s", fileName)
|
||
}
|
||
|
||
reader, exists := p.readers[ext]
|
||
if !exists {
|
||
return nil, fmt.Errorf("不支持的文件类型: %s", ext)
|
||
}
|
||
|
||
return reader, nil
|
||
}
|
||
|
||
// ReadConfigFile 读取配置文件
|
||
// 参数: filePath:文件路径 fileName:文件名
|
||
func (p *ConfigProcessor) readConfigFile(filePath, fileName string) (string, error) {
|
||
// 构建完整文件路径
|
||
fullPath := p.buildFullPath(filePath, fileName)
|
||
// 读取文件内容
|
||
data, err := p.readFileContent(fullPath)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
reader, err := p.GetReader(fileName)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
|
||
return reader.ReadConfig(data)
|
||
}
|
||
|
||
// buildFullPath 构建完整文件路径
|
||
func (p *ConfigProcessor) buildFullPath(filePath, fileName string) string {
|
||
// 如果文件路径为空,使用当前目录
|
||
if filePath == "" {
|
||
return fileName
|
||
}
|
||
|
||
// 检查是否为HTTP/HTTPS URL
|
||
if strings.HasPrefix(filePath, "http://") || strings.HasPrefix(filePath, "https://") {
|
||
// 确保URL以斜杠结尾
|
||
if !strings.HasSuffix(filePath, "/") {
|
||
filePath += "/"
|
||
}
|
||
return filePath + fileName
|
||
}
|
||
|
||
// 本地文件路径
|
||
return filepath.Join(filePath, fileName)
|
||
}
|
||
|
||
// readFileContent 读取文件内容
|
||
func (p *ConfigProcessor) readFileContent(fullPath string) ([]byte, error) {
|
||
// 检查是否为HTTP/HTTPS URL
|
||
if strings.HasPrefix(fullPath, "http://") || strings.HasPrefix(fullPath, "https://") {
|
||
return p.readFromHTTP(fullPath)
|
||
}
|
||
|
||
// 本地文件
|
||
return p.readFromLocal(fullPath)
|
||
}
|
||
|
||
// readFromLocal 从本地文件读取内容
|
||
func (p *ConfigProcessor) readFromLocal(filePath string) ([]byte, error) {
|
||
// 检查文件是否存在
|
||
if _, err := os.Stat(filePath); os.IsNotExist(err) {
|
||
return nil, fmt.Errorf("文件不存在: %s", filePath)
|
||
}
|
||
|
||
return os.ReadFile(filePath)
|
||
}
|
||
|
||
// readFromHTTP 从HTTP URL读取内容
|
||
func (p *ConfigProcessor) readFromHTTP(url string) ([]byte, error) {
|
||
resp, err := http.Get(url)
|
||
if err != nil {
|
||
return nil, fmt.Errorf("HTTP请求失败: %v", err)
|
||
}
|
||
defer resp.Body.Close()
|
||
|
||
if resp.StatusCode != http.StatusOK {
|
||
return nil, fmt.Errorf("HTTP请求失败,状态码: %d", resp.StatusCode)
|
||
}
|
||
|
||
return io.ReadAll(resp.Body)
|
||
}
|
||
|
||
// PrettyPrint 美化打印配置内容
|
||
func PrettyPrint(config map[string]interface{}, indent string) {
|
||
for key, value := range config {
|
||
switch v := value.(type) {
|
||
case map[string]interface{}:
|
||
fmt.Printf("%s%s:\n", indent, key)
|
||
PrettyPrint(v, indent+" ")
|
||
default:
|
||
fmt.Printf("%s%s: %v\n", indent, key, v)
|
||
}
|
||
}
|
||
}
|
||
|
||
// ReadConfigFile 读取配置文件
|
||
//
|
||
//export ReadConfigFile
|
||
func ReadConfigFile(filePath, fileName *C.char) *C.char {
|
||
filePathStr := C.GoString(filePath)
|
||
fileNameStr := C.GoString(fileName)
|
||
info, err := NewConfigProcessor().readConfigFile(filePathStr, fileNameStr)
|
||
if err != nil {
|
||
return C.CString(err.Error())
|
||
}
|
||
return C.CString(info)
|
||
}
|
||
|
||
// FreeCString 释放C字符串内存
|
||
//
|
||
//export FreeCString
|
||
func FreeCString(str *C.char) {
|
||
C.free(unsafe.Pointer(str))
|
||
}
|
||
|
||
// CSV_VERSION 版本号
|
||
const (
|
||
CSV_VERSION = "v1"
|
||
)
|
||
|
||
// 获取版本信息
|
||
//
|
||
//export GetVersion
|
||
func GetVersion() *C.char {
|
||
return C.CString(CSV_VERSION)
|
||
}
|
||
|
||
// 主函数
|
||
func main() {
|
||
}
|