From 80d80ad8aa1d954d1cf81a0ef1fd20f54086bbe0 Mon Sep 17 00:00:00 2001 From: xushiwei Date: Sat, 13 Jul 2024 17:51:06 +0800 Subject: [PATCH] library: cpp/std; cpp/inih demo: inihreader --- _demo/hello/hello.go | 2 +- c/socket/socket.go | 16 +++ cpp/inih/READEME.md | 15 ++- cpp/inih/_demo/inihdemo/ReaderDemo.go | 61 ------------ cpp/inih/_demo/inihdemo/inihdemo.go | 2 +- cpp/inih/_demo/inihreader/config.ini | 10 ++ cpp/inih/_demo/inihreader/reader_demo.go | 31 ++++++ cpp/inih/inih.go | 18 +++- cpp/inih/inihReader.go | 64 ------------ cpp/inih/reader.go | 73 ++++++++++++++ cpp/std/_cppstd/string.cpp | 43 ++++++++ cpp/std/_demo/cpphello/cppstr.go | 12 +++ cpp/std/std.go | 24 +++++ cpp/std/string.go | 121 +++++++++++++++++++++++ 14 files changed, 363 insertions(+), 129 deletions(-) delete mode 100644 cpp/inih/_demo/inihdemo/ReaderDemo.go create mode 100644 cpp/inih/_demo/inihreader/config.ini create mode 100644 cpp/inih/_demo/inihreader/reader_demo.go delete mode 100644 cpp/inih/inihReader.go create mode 100644 cpp/inih/reader.go create mode 100644 cpp/std/_cppstd/string.cpp create mode 100644 cpp/std/_demo/cpphello/cppstr.go create mode 100644 cpp/std/std.go create mode 100644 cpp/std/string.go diff --git a/_demo/hello/hello.go b/_demo/hello/hello.go index 7437c3e8..5d2cdd76 100644 --- a/_demo/hello/hello.go +++ b/_demo/hello/hello.go @@ -9,5 +9,5 @@ func main() { } /* Expected output: -Hello World +Hello world */ diff --git a/c/socket/socket.go b/c/socket/socket.go index c4e24da6..d019cf62 100644 --- a/c/socket/socket.go +++ b/c/socket/socket.go @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package socket import ( diff --git a/cpp/inih/READEME.md b/cpp/inih/READEME.md index f679f1da..93ef8a45 100644 --- a/cpp/inih/READEME.md +++ b/cpp/inih/READEME.md @@ -1 +1,14 @@ -brew install inih \ No newline at end of file +LLGo wrapper of benhoyt/inih +===== + +## How to install + +### on macOS (Homebrew) + +```sh +brew install inih +``` + +### on Linux (Debian/Ubuntu) + +TODO diff --git a/cpp/inih/_demo/inihdemo/ReaderDemo.go b/cpp/inih/_demo/inihdemo/ReaderDemo.go deleted file mode 100644 index 6ada6523..00000000 --- a/cpp/inih/_demo/inihdemo/ReaderDemo.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "github.com/goplus/llgo/c" - "github.com/goplus/llgo/cpp/inih" -) - -/* -expected output: - section: owner name: name value: John Doe - section: owner name: organization value: Acme Widgets Inc. - section: database name: server value: 192.0.2.62 - section: database name: port value: 143 - section: database name: file value: "payroll.dat" - section: database name: enabled value: true - section: owner name: name value: John Doe - section: owner name: organization value: Acme Widgets Inc. - section: database name: server value: 192.0.2.62 - section: database name: port value: 143 - section: database name: file value: "payroll.dat" - section: database name: enabled value: true - section: settings name: username value: lee - section: settings name: timeout value: 20 - Config file parsed successfully - s : 192.0.2.62 - isDatabaseEnabled: true port: 143 - 0x109f54da0 - 0 - value: 100 -*/ - -func main() { - demo1() - reader := inih.NewReaderFile(inih.Str("config.ini")) - if reader.ParseError() != 0 { - println("Error parsing config file") - return - } - isDatabaseEnabled := reader.GetBoolean(inih.Str("database"), inih.Str("enabled"), false) - port := reader.GetInteger(inih.Str("database"), inih.Str("port"), 0) - s := reader.GetString(inih.Str("database"), inih.Str("server"), inih.Str("unknown")) - println("s :", s.String()) - println("isDatabaseEnabled:", isDatabaseEnabled, "port:", port) - demo2() - -} - -func demo2() { - buf := `[settings] -username=admin -timeout=100 -` - reader := inih.NewReader(c.Str(buf), c.Ulong(len(buf))) - - println(&reader) - println(reader.ParseError()) - sec := inih.Str("settings") - name := inih.Str("timeout") - value := reader.GetInteger(sec, name, 0) - println("value:", value) -} diff --git a/cpp/inih/_demo/inihdemo/inihdemo.go b/cpp/inih/_demo/inihdemo/inihdemo.go index 156cfff3..1de2af69 100644 --- a/cpp/inih/_demo/inihdemo/inihdemo.go +++ b/cpp/inih/_demo/inihdemo/inihdemo.go @@ -5,7 +5,7 @@ import ( "github.com/goplus/llgo/cpp/inih" ) -func demo1() { +func main() { filename := c.Str("config.ini") if inih.Parse(filename, func(user c.Pointer, section *c.Char, name *c.Char, value *c.Char) c.Int { diff --git a/cpp/inih/_demo/inihreader/config.ini b/cpp/inih/_demo/inihreader/config.ini new file mode 100644 index 00000000..62e16fc7 --- /dev/null +++ b/cpp/inih/_demo/inihreader/config.ini @@ -0,0 +1,10 @@ +; example.ini +[owner] +name = John Doe +organization = Acme Widgets Inc. + +[database] +server = 192.0.2.62 +port = 143 +file = "payroll.dat" +enabled = true diff --git a/cpp/inih/_demo/inihreader/reader_demo.go b/cpp/inih/_demo/inihreader/reader_demo.go new file mode 100644 index 00000000..13fbbcf6 --- /dev/null +++ b/cpp/inih/_demo/inihreader/reader_demo.go @@ -0,0 +1,31 @@ +package main + +import ( + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/cpp/inih" + "github.com/goplus/llgo/cpp/std" +) + +func main() { + buf := `[settings] +username=admin +timeout=100 +` + reader := inih.NewReader(c.Str(buf), uintptr(len(buf))) + println(reader.ParseError()) + sec := std.Str("settings") + name := std.Str("timeout") + value := reader.GetInteger(sec, name, 0) + println("value:", value) + + reader = inih.NewReaderFile(std.Str("config.ini")) + if ret := reader.ParseError(); ret != 0 { + println("Error parsing config file:", ret) + return + } + isDatabaseEnabled := reader.GetBoolean(std.Str("database"), std.Str("enabled"), false) + port := reader.GetInteger(std.NewString("database"), std.Str("port"), 0) + s := reader.GetString(std.Str("database"), std.Str("server"), std.Str("unknown")) + println("s:", s.Str()) + println("isDatabaseEnabled:", isDatabaseEnabled, "port:", port) +} diff --git a/cpp/inih/inih.go b/cpp/inih/inih.go index 05f5c384..08f96fd9 100644 --- a/cpp/inih/inih.go +++ b/cpp/inih/inih.go @@ -1,3 +1,19 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package inih import ( @@ -7,7 +23,7 @@ import ( ) const ( - LLGoPackage = "link: $(pkg-config --libs inih INIReader) -lc++; -linih -lINIReader" + LLGoPackage = "link: $(pkg-config --libs inih INIReader); -linih -lINIReader" ) //go:linkname Parse C.ini_parse diff --git a/cpp/inih/inihReader.go b/cpp/inih/inihReader.go deleted file mode 100644 index b1b682d1..00000000 --- a/cpp/inih/inihReader.go +++ /dev/null @@ -1,64 +0,0 @@ -package inih - -import ( - "unsafe" - - "github.com/goplus/llgo/c" -) - -// llgo:type C -type Reader struct { - Unused [24]byte -} - -type StdString struct { - buf [24]byte -} - -type __long struct { - __cap_ int - __size_ int - __data_ unsafe.Pointer -} - -func Str(s string) *StdString { - var r StdString - r.init(c.GoStringData(s), c.Int(len(s))) - return &r -} - -func (r *StdString) String() string { - if r.buf[0]&1 == 0 { - return c.GoString((*c.Char)(unsafe.Pointer(&r.buf[1]))) - } else { - v := *(*__long)(unsafe.Pointer(&r.buf[0])) - return unsafe.String((*byte)(v.__data_), v.__size_) - } -} - -// llgo:link (*StdString).init C._ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEPKcm -func (*StdString) init(s *c.Char, size c.Int) {} - -//go:linkname NewReader C._ZN9INIReaderC1EPKcm -func NewReader(fileName *c.Char, size c.Ulong) Reader - -//go:linkname NewReaderFile C._ZN9INIReaderC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE -func NewReaderFile(fileName *StdString) Reader - -// llgo:link (*Reader).ParseError C._ZNK9INIReader10ParseErrorEv -func (*Reader) ParseError() c.Int { return 0 } - -// llgo:link (*Reader).GetInteger C._ZNK9INIReader10GetIntegerERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_l -func (*Reader) GetInteger(section *StdString, name *StdString, defaultValue c.Long) c.Long { - return 0 -} - -// llgo:link (*Reader).GetBoolean C._ZNK9INIReader10GetBooleanERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_b -func (*Reader) GetBoolean(section *StdString, name *StdString, defaultValue bool) bool { - return false -} - -// llgo:link (*Reader).GetString C._ZNK9INIReader9GetStringERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_S8_ -func (*Reader) GetString(section *StdString, name *StdString, defaultValue *StdString) StdString { - return StdString{} -} diff --git a/cpp/inih/reader.go b/cpp/inih/reader.go new file mode 100644 index 00000000..89456ec0 --- /dev/null +++ b/cpp/inih/reader.go @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package inih + +import ( + _ "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/cpp/std" +) + +// ----------------------------------------------------------------------------- + +// llgo:type C +type Reader struct { + Unused [24]byte +} + +// llgo:link (*Reader).InitFromBuffer C._ZN9INIReaderC1EPKcm +func (r *Reader) InitFromBuffer(buffer *c.Char, bufferSize uintptr) {} + +// llgo:link (*Reader).InitFromFile C._ZN9INIReaderC1ERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE +func (r *Reader) InitFromFile(buffer *c.Char, bufferSize uintptr) {} + +// ----------------------------------------------------------------------------- + +func NewReader(buffer *c.Char, bufferSize uintptr) (ret Reader) { + ret.InitFromBuffer(buffer, bufferSize) + return +} + +func NewReaderFile(fileName *std.String) (ret Reader) { + ret.InitFromFile(fileName.CStr(), fileName.Size()) + return +} + +// ----------------------------------------------------------------------------- + +// llgo:link (*Reader).ParseError C._ZNK9INIReader10ParseErrorEv +func (*Reader) ParseError() c.Int { return 0 } + +// ----------------------------------------------------------------------------- + +// llgo:link (*Reader).GetInteger C._ZNK9INIReader10GetIntegerERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_l +func (*Reader) GetInteger(section *std.String, name *std.String, defaultValue c.Long) c.Long { + return 0 +} + +// llgo:link (*Reader).GetBoolean C._ZNK9INIReader10GetBooleanERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_b +func (*Reader) GetBoolean(section *std.String, name *std.String, defaultValue bool) bool { + return false +} + +// llgo:link (*Reader).GetString C._ZNK9INIReader9GetStringERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_S8_ +func (*Reader) GetString(section *std.String, name *std.String, defaultValue *std.String) (ret std.String) { + return +} + +// ----------------------------------------------------------------------------- diff --git a/cpp/std/_cppstd/string.cpp b/cpp/std/_cppstd/string.cpp new file mode 100644 index 00000000..f48415e7 --- /dev/null +++ b/cpp/std/_cppstd/string.cpp @@ -0,0 +1,43 @@ +#include + +extern "C" { + +// ----------------------------------------------------------------------------- + +void stdStringInitEmpty(std::string* s) { + new(s) std::string(); +} + +void stdStringInitFrom(std::string* s, std::string* v) { + new(s) std::string(*v); +} + +void stdStringInitFromCStr(std::string* s, const char* cstr) { + new(s) std::string(cstr); +} + +void stdStringInitFromCStrLen(std::string* s, const char* cstr, size_t len) { + new(s) std::string(cstr, len); +} + +void stdStringDispose(const std::string* s) { + s->~basic_string(); +} + +// ----------------------------------------------------------------------------- + +const char* stdStringCStr(const std::string* s) { + return s->c_str(); +} + +const char* stdStringData(const std::string* s) { + return s->data(); +} + +size_t stdStringSize(const std::string* s) { + return s->size(); +} + +// ----------------------------------------------------------------------------- + +} // extern "C" diff --git a/cpp/std/_demo/cpphello/cppstr.go b/cpp/std/_demo/cpphello/cppstr.go new file mode 100644 index 00000000..55ed56a1 --- /dev/null +++ b/cpp/std/_demo/cpphello/cppstr.go @@ -0,0 +1,12 @@ +package main + +import ( + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/cpp/std" +) + +func main() { + s := std.Str("Hello world\n") + c.Printf(s.CStr()) + print(s.Str(), s.Size(), "\n") +} diff --git a/cpp/std/std.go b/cpp/std/std.go new file mode 100644 index 00000000..89d6b720 --- /dev/null +++ b/cpp/std/std.go @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package std + +const ( + LLGoFiles = "_cppstd/string.cpp" + LLGoPackage = "link: c++" +) + +// ----------------------------------------------------------------------------- diff --git a/cpp/std/string.go b/cpp/std/string.go new file mode 100644 index 00000000..fbc24bd9 --- /dev/null +++ b/cpp/std/string.go @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package std + +import ( + "unsafe" + + "github.com/goplus/llgo/c" + "github.com/goplus/llgo/c/bdwgc" +) + +// ----------------------------------------------------------------------------- + +// String represents a C++ std::string object. +type String struct { + Unused [24]byte +} + +// llgo:link (*String).InitEmpty C.stdStringInitEmpty +func (s *String) InitEmpty() {} + +// llgo:link (*String).InitFrom C.stdStringInitFrom +func (s *String) InitFrom(v *String) {} + +// llgo:link (*String).InitFromCStr C.stdStringInitFromCStr +func (s *String) InitFromCStr(cstr *c.Char) {} + +// llgo:link (*String).InitFromCStrLen C.stdStringInitFromCStrLen +func (s *String) InitFromCStrLen(cstr *c.Char, n uintptr) {} + +// llgo:link (*String).Dispose C.stdStringDispose +func (s *String) Dispose() {} + +// ----------------------------------------------------------------------------- + +func allocString() *String { + ptr := bdwgc.Malloc(unsafe.Sizeof(String{})) + bdwgc.RegisterFinalizer(ptr, func(obj, data c.Pointer) { + (*String)(obj).Dispose() + }, nil, nil, nil) + return (*String)(ptr) +} + +// NewString creates a C++ std::string object. +func NewString(v string) *String { + ret := allocString() + ret.InitFromCStrLen(c.GoStringData(v), uintptr(len(v))) + return ret +} + +// NewStringEmpty creates an empty std::string object. +func NewStringEmpty() *String { + ret := allocString() + ret.InitEmpty() + return ret +} + +// NewStringFrom creates a copy of a C++ std::string object. +func NewStringFrom(v *String) *String { + ret := allocString() + ret.InitFrom(v) + return ret +} + +// NewStringFromCStr creates a C++ std::string object. +func NewStringFromCStr(cstr *c.Char) *String { + ret := allocString() + ret.InitFromCStr(cstr) + return ret +} + +// NewStringFromCStrLen creates a C++ std::string object. +func NewStringFromCStrLen(cstr *c.Char, n uintptr) *String { + ret := allocString() + ret.InitFromCStrLen(cstr, n) + return ret +} + +// ----------------------------------------------------------------------------- + +// Str returns a Go string (it doesn't clone data of the C++ std::string object). +func (s *String) Str() string { + return unsafe.String((*byte)(unsafe.Pointer(s.Data())), s.Size()) +} + +// llgo:link (*String).CStr C.stdStringCStr +func (s *String) CStr() *c.Char { return nil } + +// llgo:link (*String).Data C.stdStringData +func (s *String) Data() *c.Char { return nil } + +// llgo:link (*String).Size C.stdStringSize +func (s *String) Size() uintptr { return 0 } + +// ----------------------------------------------------------------------------- + +// GoString converts a C++ std::string object to a Go string. +func GoString(v *String) string { + return c.GoString(v.Data(), v.Size()) +} + +// Str creates a constant C++ std::string object. +func Str(v string) *String { + return NewString(v) // TODO(xsw): optimize it +} + +// -----------------------------------------------------------------------------