BCBvcl4pyAPI 0.1.6__tar.gz → 0.1.7__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/PKG-INFO +8 -5
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/README.md +7 -4
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/pyproject.toml +1 -1
- bcbvcl4pyapi-0.1.7/src/BCBvcl4pyAPI/TIniFileAPI.py +107 -0
- bcbvcl4pyapi-0.1.7/src/BCBvcl4pyAPI/TMemoryStream.py +149 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI/__init__.py +5 -1
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI.egg-info/PKG-INFO +8 -5
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI.egg-info/SOURCES.txt +2 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/LICENSE +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/setup.cfg +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI/AnsiStringAPI.py +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI/BCBvcl4pyAPI.py +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI/HyperDynamicArrayAPI.py +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI.egg-info/dependency_links.txt +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI.egg-info/requires.txt +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/BCBvcl4pyAPI.egg-info/top_level.txt +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/Example/PyListTest.py +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/Example/PyListTest2.py +0 -0
- {bcbvcl4pyapi-0.1.6 → bcbvcl4pyapi-0.1.7}/src/Example/TestHyperList.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: BCBvcl4pyAPI
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: BCBvcl4pyAPI Python package
|
|
5
5
|
Author-email: James Lin <tylin123@ms27.hinet.net>
|
|
6
6
|
License: Copyright (c) 2025 James Lin
|
|
@@ -33,11 +33,14 @@ Dynamic: license-file
|
|
|
33
33
|
#BCBvcl4pyAPI
|
|
34
34
|
|
|
35
35
|
## History of version
|
|
36
|
-
Version 0.1.
|
|
37
|
-
|
|
36
|
+
Version 0.1.7: 2025/10/09<BR>
|
|
37
|
+
Add the TMemoryStream, TIniFiles class
|
|
38
|
+
|
|
39
|
+
Version 0.1.6: 2025/10/08<BR>
|
|
40
|
+
Add the AnsiString class
|
|
38
41
|
|
|
39
42
|
Version 0.1.5: 2025/09/20<BR>
|
|
40
43
|
Add the HyperDynamicArray class to provide large memory access functionality.<BR>
|
|
41
44
|
|
|
42
|
-
Version 0.1.
|
|
43
|
-
|
|
45
|
+
Version 0.1.3: 2025/09/19<BR>
|
|
46
|
+
Mainly fixed the issue where Packages could not be found after an update.<BR>
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
#BCBvcl4pyAPI
|
|
2
2
|
|
|
3
3
|
## History of version
|
|
4
|
-
Version 0.1.
|
|
5
|
-
|
|
4
|
+
Version 0.1.7: 2025/10/09<BR>
|
|
5
|
+
Add the TMemoryStream, TIniFiles class
|
|
6
|
+
|
|
7
|
+
Version 0.1.6: 2025/10/08<BR>
|
|
8
|
+
Add the AnsiString class
|
|
6
9
|
|
|
7
10
|
Version 0.1.5: 2025/09/20<BR>
|
|
8
11
|
Add the HyperDynamicArray class to provide large memory access functionality.<BR>
|
|
9
12
|
|
|
10
|
-
Version 0.1.
|
|
11
|
-
|
|
13
|
+
Version 0.1.3: 2025/09/19<BR>
|
|
14
|
+
Mainly fixed the issue where Packages could not be found after an update.<BR>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import configparser
|
|
3
|
+
|
|
4
|
+
class TIniFile:
|
|
5
|
+
def __init__(self, FileName: str, Encoding: str = "byte"):
|
|
6
|
+
"""
|
|
7
|
+
Encoding:
|
|
8
|
+
"byte" -> Big5 編碼
|
|
9
|
+
"unicode" -> UTF-8 編碼
|
|
10
|
+
"""
|
|
11
|
+
self.FileName = FileName
|
|
12
|
+
self.Encoding = Encoding.lower()
|
|
13
|
+
self.config = configparser.ConfigParser()
|
|
14
|
+
self.config.optionxform = str # 保留大小寫
|
|
15
|
+
|
|
16
|
+
self._encoding_name = "big5" if self.Encoding == "byte" else "utf-8"
|
|
17
|
+
|
|
18
|
+
if os.path.exists(self.FileName):
|
|
19
|
+
self.config.read(self.FileName, encoding=self._encoding_name)
|
|
20
|
+
|
|
21
|
+
# -----------------------
|
|
22
|
+
# 讀取方法
|
|
23
|
+
# -----------------------
|
|
24
|
+
def ReadString(self, Section: str, Ident: str, Default: str = "") -> str:
|
|
25
|
+
if self.config.has_section(Section) and self.config.has_option(Section, Ident):
|
|
26
|
+
return self.config.get(Section, Ident)
|
|
27
|
+
return Default
|
|
28
|
+
|
|
29
|
+
def ReadInteger(self, Section: str, Ident: str, Default: int = 0) -> int:
|
|
30
|
+
try:
|
|
31
|
+
return int(self.ReadString(Section, Ident, str(Default)))
|
|
32
|
+
except ValueError:
|
|
33
|
+
return Default
|
|
34
|
+
|
|
35
|
+
def ReadFloat(self, Section: str, Ident: str, Default: float = 0.0) -> float:
|
|
36
|
+
try:
|
|
37
|
+
return float(self.ReadString(Section, Ident, str(Default)))
|
|
38
|
+
except ValueError:
|
|
39
|
+
return Default
|
|
40
|
+
|
|
41
|
+
def ReadBool(self, Section: str, Ident: str, Default: bool = False) -> bool:
|
|
42
|
+
val = self.ReadString(Section, Ident, str(Default))
|
|
43
|
+
return val.lower() in ['1', 'true', 'yes']
|
|
44
|
+
|
|
45
|
+
# -----------------------
|
|
46
|
+
# 寫入方法
|
|
47
|
+
# -----------------------
|
|
48
|
+
def WriteString(self, Section: str, Ident: str, Value: str):
|
|
49
|
+
if not self.config.has_section(Section):
|
|
50
|
+
self.config.add_section(Section)
|
|
51
|
+
self.config.set(Section, Ident, Value)
|
|
52
|
+
self._save()
|
|
53
|
+
|
|
54
|
+
def WriteInteger(self, Section: str, Ident: str, Value: int):
|
|
55
|
+
self.WriteString(Section, Ident, str(Value))
|
|
56
|
+
|
|
57
|
+
def WriteFloat(self, Section: str, Ident: str, Value: float):
|
|
58
|
+
self.WriteString(Section, Ident, str(Value))
|
|
59
|
+
|
|
60
|
+
def WriteBool(self, Section: str, Ident: str, Value: bool):
|
|
61
|
+
self.WriteString(Section, Ident, str(int(Value)))
|
|
62
|
+
|
|
63
|
+
# -----------------------
|
|
64
|
+
# 刪除 / 檢查
|
|
65
|
+
# -----------------------
|
|
66
|
+
def DeleteKey(self, Section: str, Ident: str):
|
|
67
|
+
if self.config.has_section(Section):
|
|
68
|
+
self.config.remove_option(Section, Ident)
|
|
69
|
+
self._save()
|
|
70
|
+
|
|
71
|
+
def EraseSection(self, Section: str):
|
|
72
|
+
if self.config.has_section(Section):
|
|
73
|
+
self.config.remove_section(Section)
|
|
74
|
+
self._save()
|
|
75
|
+
|
|
76
|
+
def ValueExists(self, Section: str, Ident: str) -> bool:
|
|
77
|
+
return self.config.has_section(Section) and self.config.has_option(Section, Ident)
|
|
78
|
+
|
|
79
|
+
# -----------------------
|
|
80
|
+
# 內部保存
|
|
81
|
+
# -----------------------
|
|
82
|
+
def _save(self):
|
|
83
|
+
with open(self.FileName, 'w', encoding=self._encoding_name) as f:
|
|
84
|
+
self.config.write(f)
|
|
85
|
+
|
|
86
|
+
# -----------------------
|
|
87
|
+
# 關閉 (可選)
|
|
88
|
+
# -----------------------
|
|
89
|
+
def Close(self):
|
|
90
|
+
self.config = None
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# ================================================================================
|
|
94
|
+
if(__name__=="__main__"):
|
|
95
|
+
# 預設 Big5
|
|
96
|
+
ini = TIniFile("test.ini")
|
|
97
|
+
# 或者使用 Unicode (UTF-8)
|
|
98
|
+
# ini = TIniFile("test.ini", Encoding="unicode")
|
|
99
|
+
|
|
100
|
+
ini.WriteString("User", "Name", "林大明")
|
|
101
|
+
ini.WriteInteger("User", "Age", 36)
|
|
102
|
+
|
|
103
|
+
name = ini.ReadString("User", "Name", "DefaultName")
|
|
104
|
+
age = ini.ReadInteger("User", "Age", 0)
|
|
105
|
+
|
|
106
|
+
print(name, age)
|
|
107
|
+
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import io
|
|
2
|
+
import os
|
|
3
|
+
import pickle
|
|
4
|
+
|
|
5
|
+
class TStream:
|
|
6
|
+
def __init__(self):
|
|
7
|
+
self._stream = io.BytesIO()
|
|
8
|
+
|
|
9
|
+
# ---- 屬性 ----
|
|
10
|
+
@property
|
|
11
|
+
def Position(self) -> int:
|
|
12
|
+
return self._stream.tell()
|
|
13
|
+
|
|
14
|
+
@Position.setter
|
|
15
|
+
def Position(self, value: int):
|
|
16
|
+
self._stream.seek(value, io.SEEK_SET)
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def Size(self) -> int:
|
|
20
|
+
current = self._stream.tell()
|
|
21
|
+
self._stream.seek(0, io.SEEK_END)
|
|
22
|
+
size = self._stream.tell()
|
|
23
|
+
self._stream.seek(current, io.SEEK_SET)
|
|
24
|
+
return size
|
|
25
|
+
|
|
26
|
+
# ---- 基本方法 ----
|
|
27
|
+
def Seek(self, Offset: int, Origin: int = io.SEEK_SET) -> int:
|
|
28
|
+
"""移動資料指標"""
|
|
29
|
+
return self._stream.seek(Offset, Origin)
|
|
30
|
+
|
|
31
|
+
def Read(self, Buffer, Count: int) -> int:
|
|
32
|
+
"""讀取 Count 個位元組到 Buffer"""
|
|
33
|
+
data = self._stream.read(Count)
|
|
34
|
+
if isinstance(Buffer, bytearray):
|
|
35
|
+
Buffer[:len(data)] = data
|
|
36
|
+
return len(data)
|
|
37
|
+
|
|
38
|
+
def Write(self, Buffer, Count: int) -> int:
|
|
39
|
+
"""寫入 Count 個位元組"""
|
|
40
|
+
if isinstance(Buffer, (bytes, bytearray)):
|
|
41
|
+
self._stream.write(Buffer[:Count])
|
|
42
|
+
return Count
|
|
43
|
+
raise TypeError("Buffer must be bytes or bytearray")
|
|
44
|
+
|
|
45
|
+
def ReadBuffer(self, Count: int) -> bytes:
|
|
46
|
+
"""讀取指定長度的 bytes"""
|
|
47
|
+
return self._stream.read(Count)
|
|
48
|
+
|
|
49
|
+
def WriteBuffer(self, Data: bytes):
|
|
50
|
+
"""直接寫入 bytes"""
|
|
51
|
+
self._stream.write(Data)
|
|
52
|
+
|
|
53
|
+
def Clear(self):
|
|
54
|
+
"""清空資料"""
|
|
55
|
+
self._stream = io.BytesIO()
|
|
56
|
+
|
|
57
|
+
def SetSize(self, NewSize: int):
|
|
58
|
+
"""設定串流大小"""
|
|
59
|
+
current = self._stream.tell()
|
|
60
|
+
data = self._stream.getvalue()
|
|
61
|
+
if NewSize < len(data):
|
|
62
|
+
data = data[:NewSize]
|
|
63
|
+
else:
|
|
64
|
+
data += b'\x00' * (NewSize - len(data))
|
|
65
|
+
self._stream = io.BytesIO(data)
|
|
66
|
+
self._stream.seek(min(current, NewSize))
|
|
67
|
+
|
|
68
|
+
def LoadFromFile(self, FileName: str):
|
|
69
|
+
"""從檔案載入"""
|
|
70
|
+
if not os.path.exists(FileName):
|
|
71
|
+
raise FileNotFoundError(FileName)
|
|
72
|
+
with open(FileName, "rb") as f:
|
|
73
|
+
self._stream = io.BytesIO(f.read())
|
|
74
|
+
self._stream.seek(0)
|
|
75
|
+
|
|
76
|
+
def SaveToFile(self, FileName: str):
|
|
77
|
+
"""儲存至檔案"""
|
|
78
|
+
with open(FileName, "wb") as f:
|
|
79
|
+
current = self._stream.tell()
|
|
80
|
+
self._stream.seek(0)
|
|
81
|
+
f.write(self._stream.read())
|
|
82
|
+
self._stream.seek(current)
|
|
83
|
+
|
|
84
|
+
# ---- 擴充:物件序列化 ----
|
|
85
|
+
def WriteObject(self, obj):
|
|
86
|
+
"""序列化並寫入任意 Python 物件(包含 dataclass)"""
|
|
87
|
+
data = pickle.dumps(obj)
|
|
88
|
+
self.Clear()
|
|
89
|
+
self._stream.write(data)
|
|
90
|
+
self._stream.seek(0)
|
|
91
|
+
|
|
92
|
+
def ReadObject(self):
|
|
93
|
+
"""讀取並還原先前 WriteObject() 寫入的 Python 物件"""
|
|
94
|
+
self._stream.seek(0)
|
|
95
|
+
return pickle.loads(self._stream.read())
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class TMemoryStream(TStream):
|
|
99
|
+
"""模擬 BCB5 的 TMemoryStream"""
|
|
100
|
+
def __init__(self):
|
|
101
|
+
super().__init__()
|
|
102
|
+
|
|
103
|
+
# ================================================================================
|
|
104
|
+
# [使用範例]
|
|
105
|
+
if(__name__=="__main__"):
|
|
106
|
+
from dataclasses import dataclass
|
|
107
|
+
|
|
108
|
+
@dataclass
|
|
109
|
+
class STRU_Employee:
|
|
110
|
+
mi_EMPID: int;
|
|
111
|
+
ms_EMPNAME: str;
|
|
112
|
+
ms_BIRTHDAY: str;
|
|
113
|
+
ms_Weight: float;
|
|
114
|
+
|
|
115
|
+
obj_MemStream: TMemoryStream;
|
|
116
|
+
stru_EMP1 : STRU_Employee;
|
|
117
|
+
stru_EMP2 : STRU_Employee;
|
|
118
|
+
stru_EMP3 : STRU_Employee;
|
|
119
|
+
stru_READ : STRU_Employee;
|
|
120
|
+
|
|
121
|
+
obj_MemStream = TMemoryStream();
|
|
122
|
+
stru_EMP1 = STRU_Employee(0, "劉備", "1998/01/02", 54.23);
|
|
123
|
+
stru_EMP2 = STRU_Employee(1, "關羽", "2026/03/26", 74.74);
|
|
124
|
+
stru_EMP3 = STRU_Employee(2, "張飛", "2028/11/18", 94.39);
|
|
125
|
+
stru_READ = STRU_Employee(-1, "", "", 0.0);
|
|
126
|
+
|
|
127
|
+
obj_MemStream.Clear();
|
|
128
|
+
obj_MemStream.WriteObject(stru_EMP1);
|
|
129
|
+
obj_MemStream.Position = 0;
|
|
130
|
+
obj_MemStream.SaveToFile("emp1.bin");
|
|
131
|
+
|
|
132
|
+
obj_MemStream.Clear();
|
|
133
|
+
obj_MemStream.WriteObject(stru_EMP2);
|
|
134
|
+
obj_MemStream.Position = 0;
|
|
135
|
+
obj_MemStream.SaveToFile("emp2.bin");
|
|
136
|
+
|
|
137
|
+
obj_MemStream.Clear();
|
|
138
|
+
obj_MemStream.WriteObject(stru_EMP3);
|
|
139
|
+
obj_MemStream.Position = 0;
|
|
140
|
+
obj_MemStream.SaveToFile("emp3.bin");
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
obj_MemStream.LoadFromFile("emp2.bin");
|
|
144
|
+
stru_READ = obj_MemStream.ReadObject();
|
|
145
|
+
|
|
146
|
+
print(stru_READ.mi_EMPID);
|
|
147
|
+
print(stru_READ.ms_EMPNAME);
|
|
148
|
+
print(stru_READ.ms_BIRTHDAY);
|
|
149
|
+
print(stru_READ.ms_Weight);
|
|
@@ -2,4 +2,8 @@ from .BCBvcl4pyAPI import TStringList, TList, DynamicArray
|
|
|
2
2
|
from .HyperDynamicArrayAPI import HyperDynamicArray
|
|
3
3
|
from .AnsiStringAPI import AnsiString
|
|
4
4
|
|
|
5
|
-
__all__ = ["TStringList", "TList", "DynamicArray",
|
|
5
|
+
__all__ = ["TStringList", "TList", "DynamicArray",
|
|
6
|
+
"HyperDynamicArray",
|
|
7
|
+
"AnsiString",
|
|
8
|
+
"TMemoryStream"
|
|
9
|
+
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: BCBvcl4pyAPI
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: BCBvcl4pyAPI Python package
|
|
5
5
|
Author-email: James Lin <tylin123@ms27.hinet.net>
|
|
6
6
|
License: Copyright (c) 2025 James Lin
|
|
@@ -33,11 +33,14 @@ Dynamic: license-file
|
|
|
33
33
|
#BCBvcl4pyAPI
|
|
34
34
|
|
|
35
35
|
## History of version
|
|
36
|
-
Version 0.1.
|
|
37
|
-
|
|
36
|
+
Version 0.1.7: 2025/10/09<BR>
|
|
37
|
+
Add the TMemoryStream, TIniFiles class
|
|
38
|
+
|
|
39
|
+
Version 0.1.6: 2025/10/08<BR>
|
|
40
|
+
Add the AnsiString class
|
|
38
41
|
|
|
39
42
|
Version 0.1.5: 2025/09/20<BR>
|
|
40
43
|
Add the HyperDynamicArray class to provide large memory access functionality.<BR>
|
|
41
44
|
|
|
42
|
-
Version 0.1.
|
|
43
|
-
|
|
45
|
+
Version 0.1.3: 2025/09/19<BR>
|
|
46
|
+
Mainly fixed the issue where Packages could not be found after an update.<BR>
|
|
@@ -5,6 +5,8 @@ setup.cfg
|
|
|
5
5
|
src/BCBvcl4pyAPI/AnsiStringAPI.py
|
|
6
6
|
src/BCBvcl4pyAPI/BCBvcl4pyAPI.py
|
|
7
7
|
src/BCBvcl4pyAPI/HyperDynamicArrayAPI.py
|
|
8
|
+
src/BCBvcl4pyAPI/TIniFileAPI.py
|
|
9
|
+
src/BCBvcl4pyAPI/TMemoryStream.py
|
|
8
10
|
src/BCBvcl4pyAPI/__init__.py
|
|
9
11
|
src/BCBvcl4pyAPI.egg-info/PKG-INFO
|
|
10
12
|
src/BCBvcl4pyAPI.egg-info/SOURCES.txt
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|