Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix incorrectly parsed value of gid with horizontal flip flag on #84

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

IoriBranford
Copy link

No description provided.

@baylej
Copy link
Owner

baylej commented Dec 17, 2024

Hi, thank you for this,

What is the issue? I can't infer what it is from the contributed code.

Thanks!

@IoriBranford
Copy link
Author

IoriBranford commented Dec 17, 2024

Gids in TMX files are unsigned int numbers, but atoi is only designed to read numbers in signed int range.
Ints nowadays have pretty much standardized to 32 bits, so a gid with the h-flip flag (the 32nd bit) is outside of signed int range. atoi doesn't handle this well and returns some incorrect value.

@baylej
Copy link
Owner

baylej commented Jan 18, 2025

Thanks again, would using function atol() then downcasting to a uint32_t be a simpler alternative, wdyt?

@IoriBranford
Copy link
Author

IoriBranford commented Jan 18, 2025

I decided on strtoull

  • Returns 0 on non-number value, fortunately 0 is never a valid gid for a tile object.
  • long long is almost always 64 bits while long may be 32 or 64. Thus we can tell if the value is beyond 32-bit range, whereas strtoul and atol would just return the max 32-bit value, which is still a valid gid (but the wrong one).

And also made content.gid unsigned, to be consistent with tmx format which stores gids as unsigned (e.g. gid 1 with h-flip is 2,147,483,649 instead of -2,147,483,647). It shouldn't break anything unless a user is silly and checks for h-flip with gid < 0.

@baylej
Copy link
Owner

baylej commented Jan 24, 2025

Thanks for doing the change.

I don't understand why strtoul() wont work here, as an unsigned int certainly fits in an unsigned long 🤔
And in Tiled, tile ids are stored in 32 bits unsigned integers anyway

could you please detail your reasoning here?
Thanks

@IoriBranford
Copy link
Author

strtoul can work, but does add an extra step when checking for out of gid range.

unsigned long gid = strtoul(value, NULL, 0);
if (gid > UINT_MAX || gid == ULONG_MAX && errno == ERANGE)
// Some systems have int and long as the same size.
// In that case you can't tell out-of-range from the value alone, and need to check errno.

vs

unsigned long long gid = strtoull(value, NULL, 0);
if (gid > UINT_MAX)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants