adding atoi_superscript and isdigit_superscript

This commit is contained in:
hugogogo
2026-05-06 20:02:44 +02:00
parent b64ede50af
commit f93c635234
10 changed files with 269 additions and 82 deletions

View File

@@ -14,27 +14,13 @@
int ft_atoi(const char *str)
{
long nbr;
int i;
int negatif;
long long result = ft_atoll(str);
i = 0;
negatif = 1;
nbr = 0;
// clamp to int range
if (result > INT_MAX)
return INT_MAX;
if (result < INT_MIN)
return INT_MIN;
// Skip leading whitespace
while ((str[i] == ' ') || (str[i] > 8 && str[i] < 14))
i++;
// Handle optional sign
if (str[i] == '-')
negatif = -1;
if (str[i] == '+' || str[i] == '-')
i++;
// parse integer
while (str[i] >= '0' && str[i] <= '9')
nbr = nbr * 10 + (str[i++] - '0');
return (nbr * negatif);
return (int)result;
}

View File

@@ -0,0 +1,16 @@
#include "libft.h"
/**
* Parses a string of superscript digits into an int.
* Returns the integer value, or INT_MAX/INT_MIN on overflow.
*/
int ft_atoi_superscript(const char *str)
{
long long result = ft_atoll_superscript(str);
if (result > INT_MAX)
return INT_MAX;
if (result < INT_MIN)
return INT_MIN;
return (int)result;
}

View File

@@ -3,27 +3,13 @@
long ft_atol(const char *str)
{
long long nbr;
int i;
int negatif;
long long result = ft_atoll(str);
i = 0;
negatif = 1;
nbr = 0;
// clamp to long range
if (result > LONG_MAX)
return LONG_MAX;
if (result < LONG_MIN)
return LONG_MIN;
// Skip leading whitespace
while ((str[i] == ' ') || (str[i] > 8 && str[i] < 14))
i++;
// Handle optional sign
if (str[i] == '-')
negatif = -1;
if (str[i] == '+' || str[i] == '-')
i++;
// parse integer
while (str[i] >= '0' && str[i] <= '9')
nbr = nbr * 10 + (str[i++] - '0');
return (nbr * negatif);
return (long)result;
}

View File

@@ -0,0 +1,16 @@
#include "libft.h"
/**
* Parses a string of superscript digits into a long.
* Returns the integer value, or LONG_MAX/LONG_MIN on overflow.
*/
long ft_atol_superscript(const char *str)
{
long long result = ft_atoll_superscript(str);
if (result > LONG_MAX)
return LONG_MAX;
if (result < LONG_MIN)
return LONG_MIN;
return (long)result;
}

39
srcs/ft_atoll.c Normal file
View File

@@ -0,0 +1,39 @@
#include "libft.h"
long long ft_atoll(const char *str)
{
long long nbr;
int i;
int sign;
i = 0;
sign = 1;
nbr = 0;
// skip leading whitespace
while (ft_isspace(str[i]))
i++;
// handle optional sign
if (str[i] == '-')
sign = -1;
if (str[i] == '+' || str[i] == '-')
i++;
// parse digits with overflow check for `long long`
while (str[i] >= '0' && str[i] <= '9')
{
// check if multiplying by 10 would overflow
if (nbr > LLONG_MAX / 10)
return (sign > 0) ? LLONG_MAX : LLONG_MIN;
// check if adding the next digit would overflow
if (nbr == LLONG_MAX / 10 && (str[i] - '0') > LLONG_MAX % 10)
return (sign > 0) ? LLONG_MAX : LLONG_MIN;
nbr = nbr * 10 + (str[i] - '0');
i++;
}
return (nbr * sign);
}

View File

@@ -0,0 +1,65 @@
#include "libft.h"
/**
* Parses a string of superscript digits (e.g., "²³⁴") into a long long.
* Returns the integer value, or LLONG_MAX/LLONG_MIN on overflow.
*/
long long ft_atoll_superscript(const char *str)
{
long long nbr = 0;
int i = 0;
int negatif = 1;
int superscript_size;
// Skip leading whitespace
while (ft_isspace(str[i]))
i++;
// Handle optional sign
if (str[i] == '-')
negatif = -1;
if (str[i] == '+' || str[i] == '-')
i++;
// Parse superscript digits
while (1)
{
if (!ft_isdigit_superscript(&str[i], &superscript_size))
break; // Not a superscript digit
// Extract the digit value (0-9) from the superscript character
int digit;
if (superscript_size == 2)
{
// ² (U+00B2) or ³ (U+00B3)
if ((uint8_t)str[i + 1] == 0xB2)
digit = 2;
else if ((uint8_t)str[i + 1] == 0xB3)
digit = 3;
else
break; // Invalid, should not happen
}
else if (superscript_size == 3)
{
// ⁰ (U+2070) to ⁹ (U+2079)
digit = (uint8_t)str[i + 2] - 0xB0; // 0xB0 → 0, 0xB1 → 1, ..., 0xB9 → 9
}
else
{
break; // Invalid, should not happen
}
// Check for overflow
if (nbr > LLONG_MAX / 10 ||
(nbr == LLONG_MAX / 10 && digit > LLONG_MAX % 10))
{
return (negatif > 0) ? LLONG_MAX : LLONG_MIN;
}
nbr = nbr * 10 + digit;
i += superscript_size; // Skip the entire UTF-8 character
}
return (nbr * negatif);
}

View File

@@ -0,0 +1,55 @@
#include "libft.h"
/**
* Checks if the UTF-8 character at `input` is a superscript digit (², ³, ⁰-⁹).
* If it is, sets `*size` to the number of bytes in the character (2 or 3).
* Returns 1 if true, 0 otherwise.
*/
int ft_isdigit_superscript(const char *input, int *size)
{
if (size != NULL)
{
*size = 0; // Default to 0 if not a superscript digit
}
// 2-byte UTF-8 superscript digits: ² (U+00B2) and ³ (U+00B3) ---
// In UTF-8, 2-byte characters start with a byte in the range 0xC0-0xDF.
// For superscript ² and ³:
// - First byte: 0xC2 (binary: 11000010)
// - Second byte: 0xB2 (²) or 0xB3 (³) (binary: 10110010 or 10110011)
if ((uint8_t)*input == 0xC2) // Check if first byte is 0xC2 (start of 2-byte UTF-8)
{
// Check if the second byte matches ² (0xB2) or ³ (0xB3)
if ((uint8_t)*(input + 1) == 0xB2 || (uint8_t)*(input + 1) == 0xB3)
{
if (size != NULL)
{
*size = 2; // 2-byte character
}
return 1; // Valid superscript digit (² or ³)
}
}
// 3-byte UTF-8 superscript digits: ⁰ (U+2070) to ⁹ (U+2079) ---
// In UTF-8, 3-byte characters start with a byte in the range 0xE0-0xEF.
// For superscript ⁰-⁹:
// - First byte: 0xE2 (binary: 11100010)
// - Second byte: 0x81 (binary: 10000001)
// - Third byte: 0xB0 (⁰) to 0xB9 (⁹) (binary: 10110000 to 10111001)
else if ((uint8_t)*input == 0xE2) // Check if first byte is 0xE2 (start of 3-byte UTF-8)
{
// Check if the second byte is 0x81 (part of the 3-byte sequence for ⁰-⁹)
if ((uint8_t)*(input + 1) == 0x81)
{
// Check if the third byte is in the range 0xB0-0xB9 (⁰ to ⁹)
if ((uint8_t)*(input + 2) >= 0xB0 && (uint8_t)*(input + 2) <= 0xB9)
{
if (size != NULL)
{
*size = 3; // 3-byte character
}
return 1; // Valid superscript digit (⁰-⁹)
}
}
}
return 0;
}