Refactor core APIs, fix bugs, and improve safety

- Make image result/info structs readonly; improve error handling and memory safety in image library
- Introduce IJobScheduler interface; move job scheduling docs to interface
- Remove "index 0 invalid" convention from slot/sparse maps; fix Count logic
- Add Owner<T> for disposable value types in low-level utilities
- Improve ObjectPool<T> thread safety and logic
- Change List<T>.RemoveAndSwapBack to return bool
- Remove unsafe methods from generated math types; add debug range checks
- Update benchmarks and enable collection checks in tests
- Improve documentation, comments, and error messages
- Bump assembly versions across all projects
This commit is contained in:
2025-12-21 16:08:10 +09:00
parent a1ad0bd2da
commit 1fee890329
38 changed files with 1967 additions and 350 deletions

View File

@@ -34,13 +34,22 @@ namespace Misaki.HighPerformance.Image
var info = new stbi__bmp_data();
info.all_a = 255;
if (stbi__bmp_parse_header(s, &info) == null)
{
return null;
}
flip_vertically = (int)s.img_y > 0 ? 1 : 0;
s.img_y = (uint)CRuntime.abs((int)s.img_y);
if (s.img_y > 1 << 24)
{
return (byte*)(ulong)(stbi__err("too large") != 0 ? 0 : 0);
}
if (s.img_x > 1 << 24)
{
return (byte*)(ulong)(stbi__err("too large") != 0 ? 0 : 0);
}
mr = info.mr;
mg = info.mg;
mb = info.mb;
@@ -49,12 +58,16 @@ namespace Misaki.HighPerformance.Image
if (info.hsz == 12)
{
if (info.bpp < 24)
{
psize = (info.offset - info.extra_read - 24) / 3;
}
}
else
{
if (info.bpp < 16)
{
psize = (info.offset - info.extra_read - info.hsz) >> 2;
}
}
if (psize == 0)
@@ -63,26 +76,47 @@ namespace Misaki.HighPerformance.Image
var header_limit = 1024;
var extra_data_limit = 256 * 4;
if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit)
{
return (byte*)(ulong)(stbi__err("bad header") != 0 ? 0 : 0);
}
if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit)
{
return (byte*)(ulong)(stbi__err("bad offset") != 0 ? 0 : 0);
}
stbi__skip(s, info.offset - bytes_read_so_far);
}
if (info.bpp == 24 && ma == 0xff000000)
{
s.img_n = 3;
}
else
{
s.img_n = ma != 0 ? 4 : 3;
}
if (req_comp != 0 && req_comp >= 3)
{
target = req_comp;
}
else
{
target = s.img_n;
}
if (stbi__mad3sizes_valid(target, (int)s.img_x, (int)s.img_y, 0) == 0)
{
return (byte*)(ulong)(stbi__err("too large") != 0 ? 0 : 0);
}
_out_ = (byte*)stbi__malloc_mad3(target, (int)s.img_x, (int)s.img_y, 0);
if (_out_ == null)
{
return (byte*)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0);
}
if (info.bpp < 16)
{
var z = 0;
@@ -98,7 +132,10 @@ namespace Misaki.HighPerformance.Image
pal[i][1] = stbi__get8(s);
pal[i][0] = stbi__get8(s);
if (info.hsz != 12)
{
stbi__get8(s);
}
pal[i][3] = 255;
}
@@ -123,6 +160,7 @@ namespace Misaki.HighPerformance.Image
pad = -width & 3;
if (info.bpp == 1)
{
for (j = 0; j < (int)s.img_y; ++j)
{
var bit_offset = 7;
@@ -134,9 +172,15 @@ namespace Misaki.HighPerformance.Image
_out_[z++] = pal[color][1];
_out_[z++] = pal[color][2];
if (target == 4)
{
_out_[z++] = 255;
}
if (i + 1 == (int)s.img_x)
{
break;
}
if (--bit_offset < 0)
{
bit_offset = 7;
@@ -146,7 +190,9 @@ namespace Misaki.HighPerformance.Image
stbi__skip(s, pad);
}
}
else
{
for (j = 0; j < (int)s.img_y; ++j)
{
for (i = 0; i < (int)s.img_x; i += 2)
@@ -163,19 +209,28 @@ namespace Misaki.HighPerformance.Image
_out_[z++] = pal[v][1];
_out_[z++] = pal[v][2];
if (target == 4)
{
_out_[z++] = 255;
}
if (i + 1 == (int)s.img_x)
{
break;
}
v = info.bpp == 8 ? stbi__get8(s) : v2;
_out_[z++] = pal[v][0];
_out_[z++] = pal[v][1];
_out_[z++] = pal[v][2];
if (target == 4)
{
_out_[z++] = 255;
}
}
stbi__skip(s, pad);
}
}
}
else
{
@@ -191,17 +246,30 @@ namespace Misaki.HighPerformance.Image
var easy = 0;
stbi__skip(s, info.offset - info.extra_read - info.hsz);
if (info.bpp == 24)
{
width = (int)(3 * s.img_x);
}
else if (info.bpp == 16)
{
width = (int)(2 * s.img_x);
}
else
{
width = 0;
}
pad = -width & 3;
if (info.bpp == 24)
{
easy = 1;
}
else if (info.bpp == 32)
{
if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000)
{
easy = 2;
}
}
if (easy == 0)
{
@@ -240,7 +308,9 @@ namespace Misaki.HighPerformance.Image
a = (byte)(easy == 2 ? stbi__get8(s) : 255);
all_a |= a;
if (target == 4)
{
_out_[z++] = a;
}
}
}
else
@@ -256,7 +326,9 @@ namespace Misaki.HighPerformance.Image
a = (uint)(ma != 0 ? stbi__shiftsigned(v & ma, ashift, acount) : 255);
all_a |= a;
if (target == 4)
{
_out_[z++] = (byte)(a & 255);
}
}
}
@@ -265,8 +337,12 @@ namespace Misaki.HighPerformance.Image
}
if (target == 4 && all_a == 0)
{
for (i = (int)(4 * s.img_x * s.img_y - 1); i >= 0; i -= 4)
{
_out_[i] = 255;
}
}
if (flip_vertically != 0)
{
@@ -288,13 +364,18 @@ namespace Misaki.HighPerformance.Image
{
_out_ = stbi__convert_format(_out_, target, req_comp, s.img_x, s.img_y);
if (_out_ == null)
{
return _out_;
}
}
*x = (int)s.img_x;
*y = (int)s.img_y;
if (comp != null)
{
*comp = s.img_n;
}
return _out_;
}
@@ -311,15 +392,25 @@ namespace Misaki.HighPerformance.Image
}
if (x != null)
{
*x = (int)s.img_x;
}
if (y != null)
{
*y = (int)s.img_y;
}
if (comp != null)
{
if (info.bpp == 24 && info.ma == 0xff000000)
{
*comp = 3;
}
else
{
*comp = info.ma != 0 ? 4 : 3;
}
}
return 1;
@@ -330,9 +421,15 @@ namespace Misaki.HighPerformance.Image
var r = 0;
var sz = 0;
if (stbi__get8(s) != 66)
{
return 0;
}
if (stbi__get8(s) != 77)
{
return 0;
}
stbi__get32le(s);
stbi__get16le(s);
stbi__get16le(s);
@@ -345,7 +442,10 @@ namespace Misaki.HighPerformance.Image
public static int stbi__bmp_set_mask_defaults(stbi__bmp_data* info, int compress)
{
if (compress == 3)
{
return 1;
}
if (compress == 0)
{
if (info->bpp == 16)
@@ -377,7 +477,10 @@ namespace Misaki.HighPerformance.Image
{
var hsz = 0;
if (stbi__get8(s) != 66 || stbi__get8(s) != 77)
{
return (byte*)(ulong)(stbi__err("not BMP") != 0 ? 0 : 0);
}
stbi__get32le(s);
stbi__get16le(s);
stbi__get16le(s);
@@ -386,9 +489,15 @@ namespace Misaki.HighPerformance.Image
info->mr = info->mg = info->mb = info->ma = 0;
info->extra_read = 14;
if (info->offset < 0)
{
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
}
if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124)
{
return (byte*)(ulong)(stbi__err("unknown BMP") != 0 ? 0 : 0);
}
if (hsz == 12)
{
s.img_x = (uint)stbi__get16le(s);
@@ -401,17 +510,29 @@ namespace Misaki.HighPerformance.Image
}
if (stbi__get16le(s) != 1)
{
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
}
info->bpp = stbi__get16le(s);
if (hsz != 12)
{
var compress = (int)stbi__get32le(s);
if (compress == 1 || compress == 2)
{
return (byte*)(ulong)(stbi__err("BMP RLE") != 0 ? 0 : 0);
}
if (compress >= 4)
{
return (byte*)(ulong)(stbi__err("BMP JPEG/PNG") != 0 ? 0 : 0);
}
if (compress == 3 && info->bpp != 16 && info->bpp != 32)
{
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
}
stbi__get32le(s);
stbi__get32le(s);
stbi__get32le(s);
@@ -440,7 +561,9 @@ namespace Misaki.HighPerformance.Image
info->mb = stbi__get32le(s);
info->extra_read += 12;
if (info->mr == info->mg && info->mg == info->mb)
{
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
}
}
else
{
@@ -452,16 +575,24 @@ namespace Misaki.HighPerformance.Image
{
var i = 0;
if (hsz != 108 && hsz != 124)
{
return (byte*)(ulong)(stbi__err("bad BMP") != 0 ? 0 : 0);
}
info->mr = stbi__get32le(s);
info->mg = stbi__get32le(s);
info->mb = stbi__get32le(s);
info->ma = stbi__get32le(s);
if (compress != 3)
{
stbi__bmp_set_mask_defaults(info, compress);
}
stbi__get32le(s);
for (i = 0; i < 12; ++i)
{
stbi__get32le(s);
}
if (hsz == 124)
{