ref: cea5b851fc55e241c24792c50157adc2cb2cc240
parent: 9eddf61979d8dbc0029c85b400f2488bdcabf25c
author: Mahdi <mahdi.hoseini1381@yahoo.com>
date: Fri Dec 1 14:15:43 EST 2023
rewritten itoa.c and scanf.c, added adler32.c hash algorithm,
--- a/include/libc.h
+++ b/include/libc.h
@@ -25,4 +25,6 @@
int printf(const char* restrict format, ...);
int scanf (char * str, ...);
-char* itoa(int value, int base);
+char* itoa(int num, char* str, int base);
+
+long adler32(char *data);
--- /dev/null
+++ b/libc/adler32.c
@@ -1,0 +1,16 @@
+long
+adler32(char *data)
+{
+ const int prime = 65521;
+ int i = 0;
+ int a = 0, b = 1;
+ while (i < strlen(data))
+ {
+ b += data[i];
+ a += b;
+ i++;
+ }
+ b = b % prime;
+ a = a % prime;
+ return(b << 16 | a);
+}
\ No newline at end of file
--- a/libc/itoa.c
+++ b/libc/itoa.c
@@ -1,39 +1,59 @@
+// A utility function to reverse a string
+void
+reverse(char str[], int length)
+{
+ int start = 0;
+ int end = length - 1;
+ while (start < end)
+ {
+ char temp = str[start];
+ str[start] = str[end];
+ str[end] = temp;
+ end--;
+ start++;
+ }
+}
+
char*
-itoa(int value, int base )
+itoa(int num, char* str, int base)
{
- char *rc;
- char *ptr;
- char *low;
- char *str;
- // Check for supported base.
- if ( base < 2 || base > 36 )
+ int i = 0;
+ int isNegative = 0;
+
+ // Handle 0 explicitly
+ if (num == 0)
{
- *str = '\0';
+ str[i++] = '0';
+ str[i] = '\0';
return str;
}
- rc = ptr = str;
- // Set '-' for negative decimals.
- if ( value < 0 && base == 10 )
+
+ /* In standard itoa(), negative numbers are handled
+ only with base 10. Otherwise numbers are
+ considered unsigned. */
+ if (num < 0 && base == 10)
{
- *ptr++ = '-';
+ isNegative = 1;
+ num = -num;
}
- // Remember where the numbers start.
- low = ptr;
- // The actual conversion.
- do
+
+ // Process individual digits
+ while (num != 0)
{
- // Modulo is negative for negative value. This trick makes abs() unnecessary.
- *ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"[35 + value % base];
- value /= base;
- } while ( value );
- // Terminating the string.
- *ptr-- = '\0';
- // Invert the numbers.
- while ( low < ptr )
- {
- char tmp = *low;
- *low++ = *ptr;
- *ptr-- = tmp;
+ int rem = num % base;
+ str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
+ num = num / base;
}
- return rc;
-}
+
+ // If number is negative, append '-'
+ if (isNegative)
+ str[i++] = '-';
+
+ // Reverse the string
+ reverse(str, i);
+
+ // Append string terminator
+ str[i] = '\0';
+
+ return str;
+}
\ No newline at end of file
--- a/libc/scanf.c
+++ b/libc/scanf.c
@@ -3,62 +3,67 @@
#include <vga.h>
#include <ps2.h>
+#include <mem.h>
-int scanf(char *str, ...)
+char*
+get_char()
{
- va_list vl;
- int i = 0, j=0, ret = 0;
- char buff[100] = {0}, tmp[20], c;
- char *out_loc;
-
-
- while(c != '\r')
- {
+ int i = 0;
+ char *buff = malloc(10), c;
+ while (1 == 1)
+ {
c = ps2_getc();
vga_putc(c);
- buff[i] = c;
- i++;
- }
-
- va_start( vl, str );
- i = 0;
- while (str && str[i])
- {
- if(str[i] == '%')
- {
- i++;
- switch (str[i])
- {
- case 'c':
- {
- *(char*)va_arg(vl, char*) = buff[j];
- j++;
- ret++;
- break;
- }
- case 'd':
- {
- *(int*)va_arg( vl, int* ) = strtol(&buff[j], &out_loc, 10);
- j+=out_loc -&buff[j];
- ret++;
- break;
- }
- case 'x':
- {
- *(int *)va_arg( vl, int* ) = strtol(&buff[j], &out_loc, 16);
- j += out_loc -&buff[j];
- ret++;
- break;
- }
- }
- }
- else
- {
- buff[j] =str[i];
- j++;
- }
- i++;
- }
- va_end(vl);
- return ret;
+ if (c != '\r')
+ {
+ buff[i] = c;
+ i++;
+ }
+ else break;
+ }
+ return buff;
}
+
+int
+scanf(char *str, ...)
+{
+ va_list ap;
+ va_start(ap, str);
+
+ int count = 0;
+ char *buffer, *temp;
+
+ while (*str != '\0')
+ {
+ if (*str == '%')
+ {
+ buffer = get_char();
+ str++;
+ switch(*str)
+ {
+ case 'c':
+ *va_arg(ap, char*) = buffer[0];
+ count++;
+ break;
+ case 's':
+ *va_arg(ap, char**) = buffer;
+ count++;
+ break;
+ case 'd':
+ *va_arg(ap, int*) = strtol(buffer, &temp, 10);
+ count++;
+ break;
+ case 'x':
+ *va_arg(ap, int*) = strtol(buffer, &temp, 16);
+ count++;
+ break;
+ default:
+ break;
+ }
+ }
+ str++;
+ }
+ va_end(ap);
+ return count;
+}
+