5 changed files with 632 additions and 0 deletions
@ -0,0 +1,65 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
#
|
||||
# Makefile
|
||||
#
|
||||
# Copyright (C) 2016 frnmst (Franco Masotti) <franco.masotti@live.com>
|
||||
# <franco.masotti@student.unife.it>
|
||||
#
|
||||
# This file is part of salibc.
|
||||
#
|
||||
# salibc is free software: you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# salibc is distributed in the hope that it will be
|
||||
# useful,but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with salibc. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
|
||||
# Macros.
|
||||
CC = /usr/bin/gcc
|
||||
|
||||
DEPS = salibc.h
|
||||
CFLAGS = -Wall -Wextra -Wpedantic -Werror -march=native -O0
|
||||
LIBS = -lm -lrt
|
||||
CSTANDARD = -std=c99
|
||||
DEFFLAG =
|
||||
|
||||
INDENT_OPTS = -nbad -bap -nbc -bbo -bl -bli2 -bls -ncdb -nce -cp1 -cs -di2 -ndj -nfc1-nfca -hnl -i2 -ip5 -lp -pcs -psl -nsc -nsob
|
||||
SPLINT_OPTS = -usereleased -compdef -preproc
|
||||
|
||||
EXECUTABLES = salibc.out
|
||||
PRG_OBJFILES = salibc.o salibc_test.o
|
||||
|
||||
# Targets
|
||||
default : salibc |
||||
|
||||
all : main |
||||
|
||||
%.o: %.c $(DEPS) |
||||
@$(CC) $(CFLAGS) $(CSTANDARD) $(LIBS) $(DEFFLAG) -c -o $@ $<
|
||||
|
||||
indent: |
||||
@echo "Indenting all files..."
|
||||
@./indent.sh "$(INDENT_OPTS)" "$(SPLINT_OPTS)" "$(PRG_OBJFILES)"
|
||||
@echo "Done."
|
||||
|
||||
clean: |
||||
@echo "Removing object files..."
|
||||
@rm -fv *.o $(EXECUTABLES)
|
||||
@echo "Object files removed."
|
||||
|
||||
target salibc: override DEFFLAG = -DSALIBC_TEST |
||||
salibc: salibc.o salibc_test.o |
||||
@$(CC) -o $@.out $^
|
||||
@echo "$(CC) $(CFLAGS) $(CSTANDARD) $(LIBS) -DFSALIBC_TEST -o $@.out"
|
||||
|
||||
# to protect files with the following names, the .PHONY rule is used
|
||||
.PHONY: default all clean indent $(EXECUTABLES) |
@ -0,0 +1,38 @@
|
||||
#!/bin/bash |
||||
|
||||
# |
||||
# indent.sh |
||||
# |
||||
# Copyright © 2016 Franco Masotti <franco.masotti@student.unife.it> |
||||
# Danny Lessio |
||||
# This work is free. You can redistribute it and/or modify it under the |
||||
# terms of the Do What The Fuck You Want To Public License, Version 2, |
||||
# as published by Sam Hocevar. See the LICENSE file for more details. |
||||
# |
||||
|
||||
|
||||
indentOptions="$1" |
||||
splintOptions="$2" |
||||
paths="$3" |
||||
|
||||
# Set indent backup suffix. |
||||
export SIMPLE_BACKUP_SUFFIX=".indent.bak" |
||||
|
||||
# Check if indent and splint executable exists. |
||||
which indent splint 1>/dev/null 2>/dev/null |
||||
|
||||
if [ $? -eq 0 ]; then |
||||
for file in $paths; do |
||||
file="${file:0:(-2)}.c" |
||||
splint $splintOptions "$file" |
||||
indent $indentOptions "$file" |
||||
# Remove indent backup files. |
||||
rm "${file}${SIMPLE_BACKUP_SUFFIX}" |
||||
|
||||
# Get header path (.h files). |
||||
file="${file:0:(-2)}.h" |
||||
[ -f "$file" ] \ |
||||
&& { indent $indentOptions "$file"; rm "${file}${SIMPLE_BACKUP_SUFFIX}"; } |
||||
done; |
||||
fi |
||||
|
@ -0,0 +1,421 @@
|
||||
/*
|
||||
* salibc.c |
||||
* |
||||
* Copyright (C) 2016 frnmst (Franco Masotti) <franco.masotti@live.com> |
||||
* <franco.masotti@student.unife.it> |
||||
* |
||||
* This file is part of salibc. |
||||
* |
||||
* salibc is free software: you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* salibc is distributed in the hope that it will be |
||||
* useful,but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with salibc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
/* Simple C Array Library */ |
||||
|
||||
/* Use:
|
||||
* const MYVARIABLE = value |
||||
* instead of: |
||||
* value |
||||
* or |
||||
* #define MYVAR value |
||||
* in your code. |
||||
*/ |
||||
#include "salibc.h" |
||||
|
||||
static bool element_null (void *element); |
||||
static bool memory_overlaps (void *chunk1, void *chunk2, size_t fullsize); |
||||
static void realarray_delete (Array a); |
||||
static char *array_indexpointer (Array a, int index); |
||||
static bool array_indexoutofbounds (Array a, int index); |
||||
static bool array_memcopy (Array a, int index, void *element); |
||||
/*
|
||||
*************************** |
||||
*General purpose methods. * |
||||
*************************** |
||||
*/ |
||||
static bool |
||||
element_null (void *element) |
||||
{ |
||||
return (element == NULL); |
||||
} |
||||
|
||||
static bool |
||||
memory_overlaps (void *chunk1, void *chunk2, size_t fullsize) |
||||
{ |
||||
char *c1 = chunk1, *c2 = chunk2; |
||||
|
||||
if (element_null (chunk1) || element_null (chunk2)) |
||||
return false; |
||||
|
||||
/* |-----------|
|
||||
* | |-----|-------| |
||||
* c1 c2 c1+fullsize c2+smt |
||||
* c2 c1 c2+fullsize c1+smt |
||||
* |
||||
*/ |
||||
return ((c1 <= c2) && (c1 + fullsize >= c2)) || ((c2 <= c1) |
||||
&& (c2 + fullsize >= c1)); |
||||
} |
||||
|
||||
/*
|
||||
****************** |
||||
* Mixed methods. * |
||||
****************** |
||||
*/ |
||||
/* Delete the non-ADT part of the array (as well as some fields of the ADT). */ |
||||
static void |
||||
realarray_delete (Array a) |
||||
{ |
||||
if (array_null (a)) |
||||
return; |
||||
|
||||
/* Free the real array. */ |
||||
free (array_pointer (a)); |
||||
a->ptr = NULL; |
||||
a->nmemb = 0; |
||||
} |
||||
|
||||
/*
|
||||
*************************** |
||||
* Array specific methods. * |
||||
*************************** |
||||
*/ |
||||
static bool |
||||
array_indexoutofbounds (Array a, int index) |
||||
{ |
||||
return ((index < 0) || (index > array_length (a) - 1)); |
||||
} |
||||
|
||||
static char * |
||||
array_indexpointer (Array a, int index) |
||||
{ |
||||
if (array_null (a)) |
||||
return NULL; |
||||
|
||||
/* Array bound check. */ |
||||
if (array_indexoutofbounds (a, index)) |
||||
return NULL; |
||||
|
||||
return (array_pointer (a) + (((size_t) index) * array_size (a))); |
||||
} |
||||
|
||||
/* It is assumed that element has the same size of a->ptr. */ |
||||
static bool |
||||
array_memcopy (Array a, int index, void *element) |
||||
{ |
||||
if (array_null (a)) |
||||
return false; |
||||
|
||||
/* Even though the array_indexoutofbounds function is called inside the
|
||||
array_indexpointer function, this returns NULL, so memcpy would be done on a
|
||||
dest of NULL. */ |
||||
if (!element_null (element) |
||||
&& !memory_overlaps (a, element, array_fullsize (a)) |
||||
&& !array_indexoutofbounds (a, index)) |
||||
{ |
||||
memcpy (array_indexpointer (a, index), element, array_size (a)); |
||||
return true; |
||||
} |
||||
else |
||||
return false; |
||||
} |
||||
|
||||
|
||||
bool |
||||
array_null (Array a) |
||||
{ |
||||
return (element_null (a)); |
||||
} |
||||
|
||||
bool |
||||
array_empty (Array a) |
||||
{ |
||||
assert (!array_null (a)); |
||||
return (array_length (a) == 0); |
||||
} |
||||
|
||||
size_t |
||||
array_size (Array a) |
||||
{ |
||||
assert (!array_null (a)); |
||||
return (a->size); |
||||
} |
||||
|
||||
int |
||||
array_length (Array a) |
||||
{ |
||||
assert (!array_null (a)); |
||||
return (a->nmemb); |
||||
} |
||||
|
||||
/* This shouldn't go out of bounds. */ |
||||
size_t |
||||
array_fullsize (Array a) |
||||
{ |
||||
assert (!array_null (a)); |
||||
return (((size_t) array_length (a)) * array_size (a)); |
||||
} |
||||
|
||||
char * |
||||
array_pointer (Array a) |
||||
{ |
||||
if (array_null (a)) |
||||
return NULL; |
||||
|
||||
return (a->ptr); |
||||
} |
||||
|
||||
/* memcmp works well in checking equality even for floating point numbers. */ |
||||
bool |
||||
array_equal (Array a1, Array a2) |
||||
{ |
||||
if (array_null (a1) || array_null (a2)) |
||||
return false; |
||||
|
||||
if ((array_length (a1) == array_length (a2)) |
||||
&& (array_fullsize (a1) == array_fullsize (a2)) |
||||
&& (memcmp (array_pointer (a1), array_pointer (a2), array_fullsize (a1)) |
||||
== 0)) |
||||
return true; |
||||
|
||||
return false; |
||||
} |
||||
|
||||
/* Array constructor. */ |
||||
Array |
||||
array_new (int nmemb, size_t size) |
||||
{ |
||||
Array new_array = NULL; |
||||
|
||||
if (nmemb >= 0 && size > 0) |
||||
{ |
||||
new_array = malloc (sizeof (struct Array)); |
||||
if (element_null (new_array)) |
||||
return NULL; |
||||
|
||||
new_array->size = size; |
||||
new_array->nmemb = nmemb; |
||||
new_array->ptr = calloc (nmemb, size); |
||||
if (element_null (array_pointer (new_array))) |
||||
array_delete (&new_array); |
||||
} |
||||
|
||||
/* This may be NULL. */ |
||||
return new_array; |
||||
} |
||||
|
||||
void |
||||
array_delete (Array * a_ref) |
||||
{ |
||||
if (!element_null (a_ref) && !array_null (*a_ref)) |
||||
{ |
||||
/* Free the real array. */ |
||||
realarray_delete (*a_ref); |
||||
/* Free the ADT. */ |
||||
(*a_ref)->size = 0; |
||||
free (*a_ref); |
||||
*a_ref = NULL; |
||||
} |
||||
} |
||||
|
||||
/* true = success
|
||||
* false = failure |
||||
*/ |
||||
bool |
||||
array_put (Array a, int index, void *element) |
||||
{ |
||||
return (array_memcopy (a, index, element)); |
||||
} |
||||
|
||||
|
||||
/* Set the every index of array with the same value. */ |
||||
bool |
||||
array_set (Array a, void *element) |
||||
{ |
||||
int i; |
||||
|
||||
for (i = 0; i < array_length (a); i++) |
||||
{ |
||||
if (!array_memcopy (a, i, element)) |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/* Get pointer to index. If you cast to the correct pointer type, then
|
||||
* reference it you get the stored value in the index. |
||||
* This is an interface to array_indexpointer. |
||||
*/ |
||||
char * |
||||
array_get (Array a, int index) |
||||
{ |
||||
return (array_indexpointer (a, index)); |
||||
} |
||||
|
||||
/* BUGGY PART--------------------------------------------- */ |
||||
void |
||||
array_printelement (Array a, int index, const char *format) |
||||
{ |
||||
char buf[128]; |
||||
|
||||
sprintf (buf, format, *(array_indexpointer (a, index))); |
||||
printf ("%s", buf); |
||||
/* printf (format, * (array_indexpointer (a, index) ) );*/ |
||||
} |
||||
|
||||
void |
||||
array_print (Array a, const char *format) |
||||
{ |
||||
int i; |
||||
assert (!array_empty (a)); |
||||
|
||||
for (i = 0; i < array_length (a); i++) |
||||
array_printelement (a, i, format); |
||||
} |
||||
|
||||
bool |
||||
array_orderedasc (Array a) |
||||
{ |
||||
int i; |
||||
|
||||
/* With 1 or 0 elements the array is surely ordered. */ |
||||
if (array_length (a) <= 1) |
||||
return true; |
||||
|
||||
for (i = 0; i < array_length (a) - 1; i++) |
||||
{ |
||||
if (*((double *) array_indexpointer (a, i)) < * |
||||
((double *) array_indexpointer (a, i + 1))) |
||||
printf ("in--OK\n"); |
||||
|
||||
if (memcmp (array_indexpointer (a, i + i), array_indexpointer (a, i), |
||||
array_size (a)) < 0) |
||||
return false; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
/* END OF BUGGY PART------------------------------------------ */ |
||||
|
||||
Array |
||||
array_copy (Array a1) |
||||
{ |
||||
int i; |
||||
Array a2; |
||||
|
||||
if (array_null (a1)) |
||||
return NULL; |
||||
|
||||
/* Allocate a new array with the same ADT characteristics. */ |
||||
a2 = array_new (array_length (a1), array_size (a1)); |
||||
if (array_null (a2)) |
||||
return NULL; |
||||
|
||||
/* Copy the real array using the previously defined functions. */ |
||||
for (i = 0; i < array_length (a1); i++) |
||||
if (!array_memcopy (a2, i, array_indexpointer (a1, i))) |
||||
return NULL; |
||||
|
||||
return a2; |
||||
} |
||||
|
||||
bool |
||||
array_resize (Array a, int new_length) |
||||
{ |
||||
char *tmp; |
||||
int memdiff; |
||||
|
||||
if (array_null (a)) |
||||
return NULL; |
||||
|
||||
/* Invalid new length. */ |
||||
if (new_length < 0) |
||||
return false; |
||||
/* new_length is set to 0 -> leave ADT, but delete internal array. */ |
||||
else if (new_length == 0) |
||||
{ |
||||
realarray_delete (a); |
||||
return true; |
||||
} |
||||
/* Same size -> do nothing. */ |
||||
else if (array_length (a) == new_length) |
||||
return true; |
||||
/* Array's length != new_length, so realloc can now be used directly. */ |
||||
else |
||||
{ |
||||
/* Safe realloc (to avoid losing the stored array if realloc fails). */ |
||||
tmp = |
||||
realloc (array_pointer (a), |
||||
array_fullsize (a) + |
||||
(array_size (a) * ((size_t) new_length))); |
||||
if (!element_null (tmp)) |
||||
a->ptr = tmp; |
||||
else |
||||
return false; |
||||
|
||||
/* memset to 0 new part of the array.
|
||||
* To do this we must go to the first byte of the new array and put 0
|
||||
* until we get to (memdiff * a->size) bytes. |
||||
*/ |
||||
memdiff = new_length - array_length (a); |
||||
if (memdiff > 0) |
||||
memset (array_pointer (a) + array_fullsize (a) + array_size (a), 0, |
||||
((size_t) memdiff) * array_size (a)); |
||||
|
||||
/* Set the new array length. */ |
||||
a->nmemb = new_length; |
||||
} |
||||
|
||||
return true; |
||||
} |
||||
|
||||
bool |
||||
array_append (Array a, void *element) |
||||
{ |
||||
int initial_length = array_length (a); |
||||
|
||||
if (array_resize (a, initial_length + 1) |
||||
&& array_memcopy (a, initial_length, element)) |
||||
return true; |
||||
else |
||||
return false; |
||||
} |
||||
|
||||
char * |
||||
array_trim (Array a) |
||||
{ |
||||
int initial_length = array_length (a); |
||||
char *element, *element_copy; |
||||
|
||||
element = array_indexpointer (a, initial_length - 1); |
||||
/* Copy *element int *element_copy. */ |
||||
element_copy = malloc (array_size (a)); |
||||
memcpy (element_copy, element, array_size (a)); |
||||
|
||||
if (!element_null (element_copy) && array_resize (a, initial_length - 1)) |
||||
return element_copy; |
||||
else |
||||
return NULL; |
||||
} |
||||
|
||||
/* Array array_merge (Array a1, Array a2) */ |
||||
/* Array array_sum (Array a ) */ |
||||
/* Array array_merge (Array a1, Array a2) */ |
||||
/* The following two return the pointer to the elements. If referenced they
|
||||
* return the value. */ |
||||
/* char *array_maxelement (Array a ) */ |
||||
/* char *array_minelement (Array a ) */ |
||||
/* ? array_ascorder (Array a) */ |
||||
/* ? array_dscorder (Array a) */ |
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* salibc.h |
||||
* |
||||
* Copyright (C) 2016 frnmst (Franco Masotti) <franco.masotti@live.com> |
||||
* <franco.masotti@student.unife.it> |
||||
* |
||||
* This file is part of salibc. |
||||
* |
||||
* salibc is free software: you can redistribute it and/or |
||||
* modify it under the terms of the GNU General Public License as published by |
||||
* the Free Software Foundation, either version 3 of the License, or |
||||
* (at your option) any later version. |
||||
* |
||||
* salibc is distributed in the hope that it will be |
||||
* useful,but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
* GNU General Public License for more details. |
||||
* |
||||
* You should have received a copy of the GNU General Public License |
||||
* along with salibc. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#ifndef SALIBC |
||||
#define SALIBC |
||||
|
||||
#include <assert.h> |
||||
#include <stdbool.h> |
||||
#include <stddef.h> |
||||
#include <stdio.h> |
||||
#include <stdlib.h> |
||||
#include <string.h> |
||||
|
||||
struct Array |
||||
{ |
||||
size_t size; |
||||
int nmemb; |
||||
/* Pointer aritmetic can be doin on char star (unlike void star) . */ |
||||
char *ptr; |
||||
}; |
||||
|
||||
typedef struct Array *Array; |
||||
|
||||
extern bool array_null (Array a); |
||||
extern bool array_empty (Array a); |
||||
extern size_t array_size (Array a); |
||||
extern int array_length (Array a); |
||||
extern size_t array_fullsize (Array a); |
||||
extern char *array_pointer (Array a); |
||||
extern bool array_equal (Array a1, Array a2); |
||||
extern void array_delete (Array * a_ref); |
||||
extern Array array_new (int nmemb, size_t size); |
||||
extern bool array_put (Array a, int index, void *element); |
||||
extern bool array_set (Array a, void *element); |
||||
extern char *array_get (Array a, int index); |
||||
extern Array array_copy (Array a1); |
||||
extern bool array_resize (Array a, int new_length); |
||||
extern bool array_append (Array a, void *element); |
||||
extern char *array_trim (Array a); |
||||
|
||||
#endif |
@ -0,0 +1,48 @@
|
||||
#include "salibc.h" |
||||
|
||||
#ifdef SALIBC_TEST |
||||
|
||||
int main (void ) |
||||
{ |
||||
|
||||
Array arr0, arr1, arr2, arr3; |
||||
char a = 'f'; |
||||
int b = 421; |
||||
double c = 3223.554; |
||||
long double d=123423509.99999999; |
||||
|
||||
arr0 = array_new ( 50, sizeof ( char ) ); |
||||
arr1 = array_new ( 50, sizeof ( int ) ); |
||||
arr2 = array_new ( 50, sizeof ( double ) ); |
||||
arr3 = array_new ( 50, sizeof ( long double ) ); |
||||
|
||||
array_put ( arr0, 20, &a ); |
||||
array_put ( arr1, 21, &b ); |
||||
array_put ( arr2, 22, &c ); |
||||
array_put ( arr3, 23, &d ); |
||||
|
||||
printf ( "%c\n", * ((char *) array_get ( arr0, 20 ) ) ); |
||||
printf ( "%d\n", * ((int *) array_get ( arr1, 21 ) ) ); |
||||
printf ( "%f\n", * ((double *) array_get ( arr2, 22 ) ) ); |
||||
printf ( "%.9Lf\n", * ((long double *) array_get ( arr3, 23 ) ) ); |
||||
|
||||
array_append ( arr0, &a ); |
||||
array_append ( arr0, &a ); |
||||
array_append ( arr0, &a ); |
||||
printf ( "%c\n", * ((char *) array_get ( arr0, 50 ) ) ); |
||||
printf ( "%c\n", * ((char *) array_get ( arr0, 51 ) ) ); |
||||
printf ( "%c\n", * ((char *) array_get ( arr0, 52 ) ) ); |
||||
|
||||
printf ( "%c\n", * ((char *) array_trim ( arr0 ) ) ); |
||||
printf ( "%c\n", * ((char *) array_trim ( arr0 ) ) ); |
||||
printf ( "%c\n", * ((char *) array_trim ( arr0 ) ) ); |
||||
printf ( "null char: %c\n", * ((char *) array_trim ( arr0 ) ) ); |
||||
|
||||
array_resize ( arr2, 0 ); |
||||
if ( array_empty ( arr2 ) ) |
||||
printf ("arr2's length is now equal to zero\n"); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
#endif |
Reference in new issue