Thanks to visit codestin.com
Credit goes to github.com

Skip to content

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