Coder Social home page Coder Social logo

sisoputnfrba / so-commons-library Goto Github PK

View Code? Open in Web Editor NEW
106.0 48.0 175.0 603 KB

TADs de uso comun en aplicaciones desarrolladas en C

Home Page: http://sisoputnfrba.github.io/so-commons-library/

License: GNU General Public License v3.0

Makefile 1.64% C 98.24% Dockerfile 0.12%

so-commons-library's Introduction

Commons Library For C

Build Status

Biblioteca con TADs útiles para el desarrollo de aplicaciones hechas con el lenguaje C

Provee los siguientes TADs:

  • Logging (commons/log.h)
  • Manipulación de Strings (commons/string.h)
  • Manipulación de archivos de configuración (commons/config.h)
  • Colecciones de elementos
    • List (commons/collections/list.h)
    • Dictionary (commons/collections/dictionary.h)
    • Queue (commons/collections/queue.h)
  • Manejo de array de bits (commons/bitarray.h)
  • Manejo de fechas y timestamps (commons/temporal.h)
  • Información de procesos (commons/process.h)
  • Impresión de dumps de memoria (commons/memory.h)
  • Impresión de errores (commons/error.h)
  • Manejo simple de archivos de texto (commons/txt.h)

Notas

Algunas de las consideraciones a tener a la hora de su uso:

  • Ninguna de las implementaciones utiliza semáforos, por lo que el uso concurrente debe ser implementado por el usuario de estas.
  • Ninguna de las funciones implementadas posee validaciones para manejo de errores.

Guía de Instalación

Esta biblioteca utiliza CSpec para testear todas las funcionalidades, más información en: https://github.com/mumuki/cspec

Instrucciones de instalación:

  • Clonar el repositorio desde git (no usar el link de Download ZIP que provee GitHub).

  • make install -> instala la biblioteca en el sistema

  • make uninstall -> desinstala la biblioteca

Guía para el uso

  1. Linkear con -lcommons

  2. Para usarla en un .c/.h deberá incluirse de la siguiente forma: commons/<Nombre_TAD>

Por ejemplo:

#include <commons/log.h>
#include <commons/collections/list.h>

Desde Eclipse

  1. Ir a las Properties del proyecto (en el Project Explorer - la columna de la izquierda - la opción aparece dándole click derecho al proyecto), y dentro de la categoría C/C++ Build entrar a Settings, y ahí a Tool Settings.
  2. Buscar GCC Linker > Libraries > Libraries. Notar que entre paréntesis dice -l, el parámetro de gcc que estamos buscando.
  3. Darle click en el botón de +, y poner el nombre de la biblioteca sin el -l (en este caso, commons).
  4. Aceptar y buildear el proyecto.

so-commons-library's People

Contributors

afska avatar dkazarian avatar fedebonisconti avatar fedescarpa avatar fernandovelcic avatar gastoncastineira avatar gastonprieto avatar jarlakxen avatar jazcarate avatar julian-salinas avatar juliancolaiacovo avatar matiasgarciaisaia avatar maximilianofelice avatar mesaglio avatar mgarciaisaia avatar nicozare avatar raniagus avatar sciciliani avatar shiroaka avatar tferraro avatar tomasanchez avatar tomasferraro avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

so-commons-library's Issues

Documentación en los headers (en vez de en los .c)

Si en la documentación de las funciones quiero contar lo que al usuario de las mismas le interesa, ¿por qué esa documentación está en los archivos de la implementación en lugar de en los de la interfaz?

¿Hay algún motivo/convención por el que están en los .c los comentarios? ¿Estaría bien moverlos a los .h?

Puedo hacerlo, es pasar un ratín moviendo líneas, nomás.

Segmentation fault al correr los tests en MacOS X

Super baja prioridad, pero estaba probando a pedido de @gastonprieto cómo anda lo de cspecs en Mac, y me están dando un segfault los tests :(

Estoy probando en 0955634 con estos cambiecitos para que compile y corra valgrind:

diff --git a/tests/unit-tests/makefile b/tests/unit-tests/makefile
index bfe086d..94aa943 100644
--- a/tests/unit-tests/makefile
+++ b/tests/unit-tests/makefile
@@ -25,7 +25,7 @@ clean:
        $(RM) build

 test: all
-       LD_LIBRARY_PATH="../../src/build/:$(C_SPEC_BIN)" build/commons-unit-test
+       LD_LIBRARY_PATH="../../src/build/:$(C_SPEC_BIN)" DYLD_LIBRARY_PATH="../../src/build/:$(C_SPEC_BIN)" valgrind build/commons-unit-test

 dependents:
        -cd ../../ && git submodule init && git submodule update
make test
cd src && /Applications/Xcode.app/Contents/Developer/usr/bin/make all
mkdir -p build/commons/collections
gcc -shared -o "build/libcommons.so" build/commons/bitarray.o build/commons/collections/dictionary.o build/commons/collections/list.o build/commons/collections/queue.o build/commons/config.o build/commons/error.o build/commons/log.o build/commons/process.o build/commons/string.o build/commons/temporal.o build/commons/txt.o
cd tests/unit-tests && /Applications/Xcode.app/Contents/Developer/usr/bin/make all
cd ../../ && git submodule init && git submodule update
cd ../../cspec && /Applications/Xcode.app/Contents/Developer/usr/bin/make all
mkdir -p release/cspecs/
gcc -shared -o "release/libcspecs.so" release/cspecs/cspec.o
cd ../../src/ && /Applications/Xcode.app/Contents/Developer/usr/bin/make all
mkdir -p build/commons/collections
gcc -shared -o "build/libcommons.so" build/commons/bitarray.o build/commons/collections/dictionary.o build/commons/collections/list.o build/commons/collections/queue.o build/commons/config.o build/commons/error.o build/commons/log.o build/commons/process.o build/commons/string.o build/commons/temporal.o build/commons/txt.o
mkdir -p build
gcc -L"../../src/build" -L"../../cspec/release" -o "build/commons-unit-test" build/test_bitarray.o build/test_config.o build/test_dictionary.o build/test_list.o build/test_queue.o build/test_string.o -lcommons -lcspecs
cd tests/unit-tests && /Applications/Xcode.app/Contents/Developer/usr/bin/make test
cd ../../ && git submodule init && git submodule update
cd ../../cspec && /Applications/Xcode.app/Contents/Developer/usr/bin/make all
mkdir -p release/cspecs/
gcc -shared -o "release/libcspecs.so" release/cspecs/cspec.o
cd ../../src/ && /Applications/Xcode.app/Contents/Developer/usr/bin/make all
mkdir -p build/commons/collections
gcc -shared -o "build/libcommons.so" build/commons/bitarray.o build/commons/collections/dictionary.o build/commons/collections/list.o build/commons/collections/queue.o build/commons/config.o build/commons/error.o build/commons/log.o build/commons/process.o build/commons/string.o build/commons/temporal.o build/commons/txt.o
mkdir -p build
gcc -L"../../src/build" -L"../../cspec/release" -o "build/commons-unit-test" build/test_bitarray.o build/test_config.o build/test_dictionary.o build/test_list.o build/test_queue.o build/test_string.o -lcommons -lcspecs
LD_LIBRARY_PATH="../../src/build/:../../cspec/release" DYLD_LIBRARY_PATH="../../src/build/:../../cspec/release" valgrind build/commons-unit-test
==39273== Memcheck, a memory error detector
==39273== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==39273== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==39273== Command: build/commons-unit-test
==39273== 
==39273== WARNING: Support on MacOS 10.8/10.9 is experimental and mostly broken.
==39273== WARNING: Expect incorrect results, assertions and crashes.
==39273== WARNING: In particular, Memcheck on 32-bit programs will fail to
==39273== WARNING: detect any errors associated with heap-allocated data.
==39273== 
--39273-- build/commons-unit-test:
--39273-- dSYM directory is missing; consider using --dsymutil=yes
--39273-- /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so:
--39273-- dSYM directory is missing; consider using --dsymutil=yes
--39273-- /Users/mgarcia/Documents/workspace/so-commons-library/cspec/release/libcspecs.so:
--39273-- dSYM directory is missing; consider using --dsymutil=yes
==39273== Conditional jump or move depends on uninitialised value(s)
==39273==    at 0x39FBFB: _libxpc_initializer (in /usr/lib/system/libxpc.dylib)
==39273==    by 0x1CAA7: libSystem_initializer (in /usr/lib/libSystem.B.dylib)
==39273==    by 0x7FFF5FC11C2D: ImageLoaderMachO::doModInitFunctions(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC11DB9: ImageLoaderMachO::doInitialization(ImageLoader::LinkContext const&) (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC0EA61: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC0E9EA: ImageLoader::recursiveInitialization(ImageLoader::LinkContext const&, unsigned int, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC0E8F5: ImageLoader::runInitializers(ImageLoader::LinkContext const&, ImageLoader::InitializerTimingList&) (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC021B6: dyld::initializeMainExecutable() (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC0555F: dyld::_main(macho_header const*, unsigned long, int, char const**, char const**, char const**, unsigned long*) (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC0127A: dyldbootstrap::start(macho_header const*, int, char const**, long, macho_header const*, unsigned long*) (in /usr/lib/dyld)
==39273==    by 0x7FFF5FC0105D: _dyld_start (in /usr/lib/dyld)
==39273== 

  Bitarray
    ✔ should get the bit value at position
    ✔ should clean the bit value at position
    ✔ should set the bit value at position
    ✔ should get the bits count

  Config
==39273== Invalid read of size 1
==39273==    at 0xF6F4: _is_last_token.3409 (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xFBE4: _string_split (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xF727: string_split (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xE650: add_cofiguration.3420 (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xF96C: string_iterate_lines (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xE7DB: config_create (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0x10000121E: __$__.3037 (in build/commons-unit-test)
==39273==    by 0x18571: __before_execute (in /Users/mgarcia/Documents/workspace/so-commons-library/cspec/release/libcspecs.so)
==39273==    by 0x17356: __it (in /Users/mgarcia/Documents/workspace/so-commons-library/cspec/release/libcspecs.so)
==39273==    by 0x1000013D5: __$__.3034 (in build/commons-unit-test)
==39273==    by 0x1725B: __describe (in /Users/mgarcia/Documents/workspace/so-commons-library/cspec/release/libcspecs.so)
==39273==    by 0x100001204: cspec_context_test_config (in build/commons-unit-test)
==39273==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==39273== 
==39273== 
==39273== Process terminating with default action of signal 11 (SIGSEGV)
==39273==  Access not within mapped region at address 0x0
==39273==    at 0xF6F4: _is_last_token.3409 (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xFBE4: _string_split (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xF727: string_split (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xE650: add_cofiguration.3420 (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xF96C: string_iterate_lines (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0xE7DB: config_create (in /Users/mgarcia/Documents/workspace/so-commons-library/src/build/libcommons.so)
==39273==    by 0x10000121E: __$__.3037 (in build/commons-unit-test)
==39273==    by 0x18571: __before_execute (in /Users/mgarcia/Documents/workspace/so-commons-library/cspec/release/libcspecs.so)
==39273==    by 0x17356: __it (in /Users/mgarcia/Documents/workspace/so-commons-library/cspec/release/libcspecs.so)
==39273==    by 0x1000013D5: __$__.3034 (in build/commons-unit-test)
==39273==    by 0x1725B: __describe (in /Users/mgarcia/Documents/workspace/so-commons-library/cspec/release/libcspecs.so)
==39273==    by 0x100001204: cspec_context_test_config (in build/commons-unit-test)
==39273==  If you believe this happened as a result of a stack
==39273==  overflow in your program's main thread (unlikely but
==39273==  possible), you can try to increase the size of the
==39273==  main thread stack using the --main-stacksize= flag.
==39273==  The main thread stack size used in this run was 67104768.
==39273== 
==39273== HEAP SUMMARY:
==39273==     in use at exit: 36,188 bytes in 398 blocks
==39273==   total heap usage: 501 allocs, 103 frees, 42,853 bytes allocated
==39273== 
==39273== LEAK SUMMARY:
==39273==    definitely lost: 4,096 bytes in 1 blocks
==39273==    indirectly lost: 0 bytes in 0 blocks
==39273==      possibly lost: 0 bytes in 0 blocks
==39273==    still reachable: 6,910 bytes in 25 blocks
==39273==         suppressed: 25,182 bytes in 372 blocks
==39273== Rerun with --leak-check=full to see details of leaked memory
==39273== 
==39273== For counts of detected and suppressed errors, rerun with: -v
==39273== Use --track-origins=yes to see where uninitialised values come from
==39273== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 146 from 37)
make[1]: *** [test] Segmentation fault: 11
make: [test] Error 2 (ignored)

CC: @gastonprieto @fedescarpa

Feature request: hexdump

Se me ocurre que sería útil una función que devuelva/imprima un hexdump de una porción de memoria. No se me ocurre en cuál de los TADs actuales entraría (hacer string_hexdump() ayudaría a confundir strings con streams y memoria en general, se me ocurre), pero la firma sería algo como char *XXXX_hexstring(void *source, size_t length) para devolver el hexdump, o void XXXX_hexdump(void *source, size_t length) para imprimirlo por pantalla.

El dump sería similar a lo que muestran bless, hexdump y otros:

00000000  cf fa ed fe 07 00 00 01  03 00 00 80 02 00 00 00  |................|
00000010  10 00 00 00 a0 06 00 00  85 00 20 00 00 00 00 00  |.......... .....|
00000020  19 00 00 00 48 00 00 00  5f 5f 50 41 47 45 5a 45  |....H...__PAGEZE|
00000030  52 4f 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |RO..............|
00000040  00 00 00 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000060  00 00 00 00 00 00 00 00  19 00 00 00 28 02 00 00  |............(...|

Como referencia, Crystal lo hace.

dictionary_put no reemplaza el elemento

El dictionary_put no reemplaza el elemento. Si no se hace un remove antes y después se hace el put, queda duplicado.

Cuando se haga el get va a devolver siempre el mismo valor (el que encuentre primero)

Implementar Asserts

Implementar un mecanismo de assertions y utilizarlo para validar las precondiciones en las operaciones de los TADs

Log erróneo si algún parámetro string incluye %

Javier Casaubon reporta problemas cuando quiere loggear un string que incluya el caracter %. Supongo que el problema está en que lo que son parámetros de las funciones de log se lo pasamos a printf dentro del formato, con el string ya formado.

No lo probé ni tengo casos puntuales de prueba, por ahora, así que habría que validarlo, pero me parece que tiene que estar pasando algo de esto.

Agregar un parámetro data a algunas funciones de list.c y .h

Para poder agregar información ajena al elemento a la condición.

Ejemplo del TP actual:

Tengo una lista de estructuras consola que contienen el pid y el socket de la consola que representan. Teniendo un pid necesito obtener el socket correspondiente.

_Bool compararPid(t_consola* consola, int* pid){
    return consola->pid == *pid;
}

int unPid = 3;
t_consola* consola = list_find(consolas, compararPid, &unPid);
consola->socket;

Una posible forma para find y remove_and_destroy_by_condition: http://pastebin.com/45gHSqBi

Desde ya gracias

Constructor para el dictionary

Elimnar el constructor que recibe por parametro el destroyer de elementos, para mantener ser homogeneo con el resto de las colecciones de elementos.

Soportar/detectar saltos de línea de Windows en t_config

El TAD de config tiene problemas con los saltos de línea Windows-like, pero es un error relativamente común en el código de los TPs.

Técnicamente hablando quizá no sea lo más correcto, pero, dado el objetivo principal de la biblioteca, estaría bueno detectar esos casos y mostrar un warning al usuario, o bien soportar indistintamente ambos saltos de línea.

Podemos asumir que la biblioteca es nativa de Linux (y buscar los de Windows específicamente), o buscar hacer que detecte saltos "foráneos" (es decir, distintos al de la plataforma actual) dinámicamente.

Numeración de bits en el bitmap

Los bits de los bytes se deben numerar para el otro lado:

cambiar

define BIT_IN_CHAR(bit) (0x01 << (CHAR_BIT - 1 - ((bit) % CHAR_BIT)))

Por

define BIT_IN_CHAR(bit) (0x80 >> (CHAR_BIT - 1 - ((bit) % CHAR_BIT)))

Problemas creando nuestra propia library

Hola SO:

Estoy intentando hacer nuestra propia library para evitar código repetido entre procesos del TP.

Ya ví el video de como agregar una library que explica como usar las commos y el como crear una library(https://youtu.be/s5ac8CPDkMg). Las commons las puedo usar sin problemas haciendo #include <commons/asd.h>

Tengo esto:
En eclipse tengo un proyecto para cada proceso (planif, cpu, mem, swap) y un quinto proyecto libraryTP que lo creé siguiendo el vídeo ese que explica como agregar las commons al eclipse. libraryTP tiene el -fPIC.

En cada proyecto ya fui a c/c++ general> paths and symbols > library paths > add > /libraryTP (que está dentro del mismo workspace, que es mi root de github.

Cuando abro memoria.c (ó el .c de cualquier proceso) e intento hacer #include <libraryTP/sockets.h> me dice que no puede resolver la inclusión.

Dentro de libraryTP en sockets.h tengo:

#ifndef SOCKETS_H_
#define SOCKETS_H_

int escuchar(int puerto);
int conectarse(char* ip, int puerto);

#endif /* SOCKETS_H_ */

Que me falta? Gracias!

salloc()/string_allocate()

Espero que me convenzan de que estaría mal crear una función salloc() o string_allocate() que reciba la cantidad de caracteres a guardar y se encargue de reservar el lugar para eso + el \0, además de poner un \0 al final.

El rationale es que usar un caracter terminador es una especie de detalle de implementación: cuanto más pueda desentenderme de que existe el \0, me parece que es mejor.

Guardado de Keys

Haciendo: dictionary_put("unaClave", "515165161616516156"); y luego: dictionary_remove("unaClave"),
se rompe dado que intenta hacer free del element->key.
Obviamente, es un tema de uso. Se soluciona pasándole a put un elemento dinámico en la clave, pero resulta un poco tedioso para usos simples del diccionario.
No seria bueno que la key guardada sea independiente del origen de la cadena que pasa el usuario? porque justamente es en la key donde imagino menos necesidad de que lo que estés guardando sea si o si de origen dinámico.
Y es más, si yo con la key que le pase (imaginando que es dinámica) quiero seguir trabajando y eventualmente hago un free, estoy al horno, porque en el diccionario guarda el puntero que yo le paso.

El bitmap llena el array por posición de menor peso del byte

Al settear el primer bit de un bitarray vacío , la operación no settea el primer bit respecto a la posición de memoria, sino el bit que corresponde al peso más chico del primer byte del mismo.

Supongamos que tenemos un bitmap:
char *bitmap = malloc(2);

Nuestra memoria, en bits (8 bits por byte):
00000000 00000000

Si setteamos el primer bit obtenemos que la memoria queda con:
00000001 00000000

Cuando en realidad, esperaría obtener:
10000000 00000000

Esto, además, rompe con la interoperabilidad a otras implementaciones de bitmap.

Existe algún motivo por el que se desarrolló de esta forma, o es un bug?

string_nsplit()

El nombre propuesto es horrible, pero la idea no tanto: hacer una versión de string_split() a la que le pueda pasar la cantidad máxima de tokens en que separar. Separa los primeros n tokens, y en el último mete toooodo el resto del string.

string_nsplit("hola como estas", " ", 2) devuelve un array con "hola" y "como estas".

Basado en este post de @SofiAudisio:

Hola , estaba programando la consola especialmente cuando se pide almacenar bytes mediante la misma.

Se ingresa todo en una línea separados por espacios usando la función de las commons string_split:

almacenarBytes base offset tamaño idPrograma buffer

El problema surge al momento de ingresar un buffer con espacios ya que la función string_split me va a cortar el mismo.

Quería saber si se va a probar con un buffer con espacios ya que esto me traería un problema .

Una solución seria ingresar en una línea pero separadas por comas

almacenarBytes,base,offset,tamaño,idPrograma,buffer

pero no se si esto sería correcto

Gracias

Saludos!

list_remove_and_destroy_by_condition borra un único elemento

Hola! Haciendo el TP vi que si usaba el list_remove_and_destroy_by_condition solo me borraba el primer elemento que cumple con la condición (y como uno de los ayudantes me hizo saber después, es coherente, ya que llama al list_find_element que devuelve el primero que la cumple) pero la descripción del list_remove_and_destroy_by_condition aún dice que saca todos los que cumplen la condición.
Me recomendaron que lo suba a issues para que lo tengan en cuenta!
Saludos

Reemplazar mallocs por memoria statica

En todas las funciones que internamente hagan mallocs y free, habria que reemplazarlo por memoria statica como puede ser un stack alloc o vectores dinamicos.

Un caso son las bibliotecas de Log

Segfault en config_create cuando el archivo termina con dos \n

Si el archivo de configuración a cargar con config_create() termina con dos newlines (\n\n), la función da segfault tratando de hacer un string_split().

Eso no ocurre cuando el archivo tiene un doble newline en el medio.

Podría ocurrir que también rompa si no hay newlines al final. Lo vi recién con los chicos de @sisoputnfrba/plikiti-plikiti por su TP, estaría genial que nos aporten los archivos con los que están probando :)

config_get_as_array(...)

Implementar como obtener un array de elementos desde el config, creo que un formato valido podría ser:

listaElementos = [elemento1, elemento2, elemento3]

Soportar la instalación desde el zip

Actualmente el make rompe si el proyecto se bajó usando Download as zip porque no tiene información del submódulo git de las cspec.

Deberíamos solucionar ese problema no-se-cómo :)

Spec mostrando cómo usar list_find con una inner function con parámetros externos

El spec actual de list_find busca un valor hardcodeado:

            it(" should find the first value that satisfies a condition") {
                int _is_ezequiel(t_person *p) {
                    return string_equals_ignore_case(p->name, "Ezequiel");
                }

                assert_person(list_find(list, (void*) _is_ezequiel), "Ezequiel", 25);

                int _is_chuck_norris(t_person *p) {
                    return string_equals_ignore_case(p->name, "Chuck Norris");
                }

                should_ptr(list_find(list, (void*) _is_chuck_norris)) be null;
                should_int(list_size(list)) be equal to(5);
            } end

Deberíamos modificarlo o hacer otro en el que "Ezequiel" no esté hardcodeado en la función interna, si no que refiera a una variable del contexto que contiene a la función. Por ejemplo, este mínimo cambio:

            it(" should find the first value that satisfies a condition") {
                char *person_name = "Ezequiel";
                int _is_this_person(t_person *p) {
                    return string_equals_ignore_case(p->name, person_name);
                }

                assert_person(list_find(list, (void*) _is_this_person), "Ezequiel", 25);

                int _is_chuck_norris(t_person *p) {
                    return string_equals_ignore_case(p->name, "Chuck Norris");
                }

                should_ptr(list_find(list, (void*) _is_chuck_norris)) be null;
                should_int(list_size(list)) be equal to(5);
            } end

Desacoplar la definición del TAD de la implementación

Encapsular la estructura que almacena los datos del dato, para que pueda variar la implementación.

Esto debería sacarse de la definición del Header y debería estar definido en la implementación.

typedef struct {
    FILE* file;
    bool is_active_console;
    t_log_level detail;
    char *program_name;
    pid_t pid;
}t_log;

dictionary_iterate() itera infinitamente con claves sobrecargadas

Cuando se inserta más de un valor para la misma clave del t_dictionary, dictionary_iterate queda en un loop infinito sobre la primer entrada de esa clave sobrecargada.

$ cat test.c 
#include <stdio.h>
#include <stdlib.h>
#include "commons/collections/dictionary.h"
#include "commons/collections/node.h"

void imprimirNumeros(char *clave, void *entrada) {
    printf("%s=%d\n", clave, (int)((t_hash_element *)entrada)->data);
}

int main(void) {
  t_dictionary *diccionario = dictionary_create(NULL);

  dictionary_put(diccionario, "hola", 4);
//  dictionary_put(diccionario, "hola", 10);
  dictionary_put(diccionario, "chau", 20);

  dictionary_iterator(diccionario, imprimirNumeros);

  exit(0);
}
$ make && build/test 
cd ../commons/Debug && make all
make[1]: Entering directory `/home/mati/workspaces/operativos/workspace-dictionary/commons/Debug'
Building target: libcommons-library.so
Invoking: GCC C Linker
gcc -shared -o "libcommons.so"  ./src/commons/collections/dictionary.o ./src/commons/collections/list.o ./src/commons/collections/queue.o  ./src/commons/bitarray.o ./src/commons/config.o ./src/commons/error.o ./src/commons/log.o ./src/commons/string.o ./src/commons/temporal.o   
Finished building target: libcommons-library.so

make[1]: Leaving directory `/home/mati/workspaces/operativos/workspace-dictionary/commons/Debug'
mkdir -p build
gcc -I"../commons/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"build/test.d" -MT"build/test.d" -o "build/test.o" "build/../test.c"
build/../test.c: In function ‘imprimirNumeros’:
build/../test.c:7:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
build/../test.c: In function ‘main’:
build/../test.c:13:2: warning: passing argument 3 of ‘dictionary_put’ makes pointer from integer without a cast [enabled by default]
In file included from build/../test.c:3:0:
../commons/src/commons/collections/dictionary.h:34:11: note: expected ‘void *’ but argument is of type ‘int’
build/../test.c:15:2: warning: passing argument 3 of ‘dictionary_put’ makes pointer from integer without a cast [enabled by default]
In file included from build/../test.c:3:0:
../commons/src/commons/collections/dictionary.h:34:11: note: expected ‘void *’ but argument is of type ‘int’
gcc -L"../commons/src" -L"../commons/Debug" -o "build/test" ./build/test.o -lcommons
chau=20
hola=4
$ vi test.c 
$ cat test.c 
#include <stdio.h>
#include <stdlib.h>
#include "commons/collections/dictionary.h"
#include "commons/collections/node.h"

void imprimirNumeros(char *clave, void *entrada) {
    printf("%s=%d\n", clave, (int)((t_hash_element *)entrada)->data);
}

int main(void) {
  t_dictionary *diccionario = dictionary_create(NULL);

  dictionary_put(diccionario, "hola", 4);
  dictionary_put(diccionario, "hola", 10);
  dictionary_put(diccionario, "chau", 20);

  dictionary_iterator(diccionario, imprimirNumeros);

  exit(0);
}

$ make && build/test 
cd ../commons/Debug && make all
make[1]: Entering directory `/home/mati/workspaces/operativos/workspace-dictionary/commons/Debug'
Building target: libcommons-library.so
Invoking: GCC C Linker
gcc -shared -o "libcommons.so"  ./src/commons/collections/dictionary.o ./src/commons/collections/list.o ./src/commons/collections/queue.o  ./src/commons/bitarray.o ./src/commons/config.o ./src/commons/error.o ./src/commons/log.o ./src/commons/string.o ./src/commons/temporal.o   
Finished building target: libcommons-library.so

make[1]: Leaving directory `/home/mati/workspaces/operativos/workspace-dictionary/commons/Debug'
mkdir -p build
gcc -I"../commons/src" -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"build/test.d" -MT"build/test.d" -o "build/test.o" "build/../test.c"
build/../test.c: In function ‘imprimirNumeros’:
build/../test.c:7:30: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
build/../test.c: In function ‘main’:
build/../test.c:13:2: warning: passing argument 3 of ‘dictionary_put’ makes pointer from integer without a cast [enabled by default]
In file included from build/../test.c:3:0:
../commons/src/commons/collections/dictionary.h:34:11: note: expected ‘void *’ but argument is of type ‘int’
build/../test.c:14:2: warning: passing argument 3 of ‘dictionary_put’ makes pointer from integer without a cast [enabled by default]
In file included from build/../test.c:3:0:
../commons/src/commons/collections/dictionary.h:34:11: note: expected ‘void *’ but argument is of type ‘int’
build/../test.c:15:2: warning: passing argument 3 of ‘dictionary_put’ makes pointer from integer without a cast [enabled by default]
In file included from build/../test.c:3:0:
../commons/src/commons/collections/dictionary.h:34:11: note: expected ‘void *’ but argument is of type ‘int’
gcc -L"../commons/src" -L"../commons/Debug" -o "build/test" ./build/test.o -lcommons
chau=20
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
hola=4
[...]

Path absoluto en el test de config

El test de config (test_config.c) tiene hardcodeado un path en la home de Gastón :P

Yo cambié mi Makefile para que copie el archivo de configuración a la carpeta de build, y la ruta la hice relativa (que levante del propio directorio). Pero no se cómo se lleva eso con el CUnit desde eclipse o como sea que lo estén corriendo.

Tampoco se cómo hacerlo feliz, porque lo mío queda dependiendo del directorio desde el que corrés los tests (tenés que meterte a la carpeta build para que funcione, sino también pincha por SegFault).

¿Cómo deberíamos hacer esto? ¿Hay alguna manera "correcta"?

Info de debug?

Podría ser útil tener opciones para entender mejor el funcionamiento de la biblioteca.

Para las colecciones, por ejemplo, funciones del estilo list_inspect para mostrar el estado interno de la lista (mostrar algo como [0xb0cacaca, 0xcafebabe, 0x51f42152], que represente la lista de punteros), y alguna opción global de la biblioteca para habilitar un modo DEBUG en el que se impriman por stderr mensajes como "Adding element 0x135262f1 to list 0xab225252" en cada operación "relevante".

Es muy experimental todo, y medio bizarro, pero podría ayudar a entender algunos errores frecuentes en el uso de la biblioteca.

Viene de acá

CC: @gastonprieto

Devolver tamaño vector de string_split

Hola.
No hay forma de obtener el tamaño del vector dinámico que devuelve string_split, sobre todo cuando se usa con algo que introduzca el usuario o leamos desde archivo. Si hago un string_length me da la longitud del primer substring. No del vector en si.

#include <stdio.h>
#include <stdlib.h>
#include <commons/string.h>

int main() {
    char** split;
    int i, j;
    split = string_split("probando uno dos tres", " ");
    j = string_length(*split);
    printf("%d 'partes'\n", j);
    for (i=0; i<j; i++)
        printf("Parte %d, size %d - |%s|\n", i, string_length(split[i]), split[i]);

    for (i=0; i<j; i++){
        free(split[i]);
        printf("Libero parte %d\n", i);
    }

    free(split);
    printf("Liberro array de parametros");
    return 0;
}

Estaría bueno que lo devuelvan la cantidad en algún parámetro o en la posición 0. En las pruebas unitarias esto no "salta" porque esta hardcodeado. Prueban separar "Hola planeta tierra" y no controlan que salgan 3 partes, porque ya saben de antemano que va a a salir un vector de 3 elementos

PD: publico esto porque pienso que quisieron que funcione string_length al poner el ultimo elemento en 0. No me parece muy lindo tener que recorrer todo el vector en busca de algún NULL para obtener su tamaño

Manipulación de arrays

Analizar la implementación de un wrapper para los arrays, o de realizar un helper con funciones como: search(..), map(..), filter(..), etc.

list_add_in_index() falla con index = elements_count

Si index es igual a elements_count, list_add_index() no agrega el elemento al comienzo de la lista, como es esperado.

int main(void) {

    void mostrar(void *elemento) {
        printf("%s\n", (char *)elemento);
    }

    t_list *lista = list_create();
    list_add_in_index(lista, 0, strdup("mensaje"));
    list_add(lista, strdup("mensaje2"));
    list_add_in_index(lista, 0, strdup("mensaje3"));
    list_add_in_index(lista, 0, strdup("mensaje4"));

    list_iterate(lista, mostrar);

    exit(0);
}

Muestra:

mensaje4
mensaje3
mensaje2

string_replacing

Implementar una función string_replacing que reemplace todas las ocurrencias de un substring en una cadena por otro. La llamaría string_replace pero no debería mutar el original (o podríamos ofrecer las dos alternativas).

// returns a copy of source with all occurrences of pattern replaced by replacement
char *string_replacing(char *source, char *pattern, char *replacement);

string_replacing("hello", "ello", "ola") // devuelve "hola"
string_replacing("hello", "l", "") // devuelve "heo"
string_replacing("hello", "o", "o world!") // devuelve "hello world!"
string_replacing("hello", "not a substring", "yay!") // devuelve "hello"
string_replacing("hello", "", "x") // no tengo idea qué debería devolver - "hello"? "xhxexlxlxox"? NULL?
string_replacing("hello", NULL, "x") // error?
string_replacing(NULL, "a", "x") // devuelve NULL

No se si alguien lo va a usar en el TP, pero yo lo voy a usar como una alternativa a sed/awk/tr en la consola - armando un comandito que aplique este reemplazo al stdin y lo escupa por stdout.

¿Opiniones, @gastonprieto?

Agregar list_sort(...)

Firma posible

void list_sort(t_list_, comparator_);

Creo que conviene que tenga efecto colateral sobre la lista, y no que devuelva una nueva.. dejarlo libre para que podamos implementar distintos algoritmos de ordenamiento

Segmentation fault en "config_get_string_value"

Cuando quiero correr el programa por consola me tira el segmentation fault, dejo acá lo que me dice Valgrind, que por lo que entiendo es en el uso de la función "config_get_string_value" de las commons.

Por si es necesario, la linea de codigo es esta:

configuracion.puertoCpu = strdup(config_get_string_value(config, "PUERTO_CPU"));

==4139== Memcheck, a memory error detector
==4139== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4139== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==4139== Command: ./kernel
==4139== 
==4139== Invalid read of size 4
==4139==    at 0x4054F3F: config_get_string_value (in /usr/lib/libcommons.so)
==4139==    by 0x8048A56: cargarConfiguracion (kernel.c:115)
==4139==    by 0x8048D5A: main (kernel.c:158)
==4139==  Address 0x4 is not stack'd, malloc'd or (recently) free'd
==4139== 
==4139== 
==4139== Process terminating with default action of signal 11 (SIGSEGV)
==4139==  Access not within mapped region at address 0x4
==4139==    at 0x4054F3F: config_get_string_value (in /usr/lib/libcommons.so)
==4139==    by 0x8048A56: cargarConfiguracion (kernel.c:115)
==4139==    by 0x8048D5A: main (kernel.c:158)
==4139==  If you believe this happened as a result of a stack
==4139==  overflow in your program's main thread (unlikely but
==4139==  possible), you can try to increase the size of the
==4139==  main thread stack using the --main-stacksize= flag.
==4139==  The main thread stack size used in this run was 8388608.
==4139== 
==4139== HEAP SUMMARY:
==4139==     in use at exit: 0 bytes in 0 blocks
==4139==   total heap usage: 1 allocs, 1 frees, 352 bytes allocated
==4139== 
==4139== All heap blocks were freed -- no leaks are possible
==4139== 
==4139== For counts of detected and suppressed errors, rerun with: -v
==4139== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Violación de segmento (`core' generado)

Que estoy haciendo mal o cual sería el problema?

Muchas gracias!

list_find_element_and_index()

Propusieron implementar esta función:

void* list_find_element_and_index(t_list *self, bool(*condition)(void*), int* index) {
    t_link_element *element = self->head;
    int position = 0;

    while (element != NULL && !condition(element->data)) {
        element = element->next;
        position++;
    }

    if (index != NULL) {
        *index = position;
    }

    return element != NULL ? element->data : NULL;
}

La idea es que busque un elemento que cumpla la condición y devuelva el índice en que se encuentra.

Temporal no es thread-safe

La función temporal_get_string_time utiliza la función localtime que no es thread-safe​. Esto afecta por ejemplo a todas las funciones de log cuando la usan.

Implementar string_reverse

Subo una forma horrible de implementarlo

char* string_reverse(char* palabra) {
    char* resultado = malloc(string_length(palabra) + 1);

    int i = string_length(palabra) - 1, j = 0;
    while (i >= 0){
        resultado[j] = palabra[i];
        i--;
        j++;
    }
    resultado[j] = '\0';

    return resultado;
}

Feature Request: List sorting

Podríamos tener un list_t * list_sort(t_list*, int (*sorter)(void*)), que nos devuelva la lista ordenada según un criterio, como lo ven?

Explicar en README como Linkear una libreria desde Eclipse

Para linkear una librería desde Eclipse:
1.En el Project Explorer (La columna de la izquierda), click derecho en tu proyecto que queres agregar la biblioteca > Properties > C/C++ Build > Settings > Tool Settings.
2.Hay vas a ver GCC Linker > Libraries > Libraries (notar como dice -l, que es lo que estamos buscando).
3.Click en el botón de + y pones el nombre de la biblioteca, en este caso "commons" (sin el -l).

Conflicto con nombre de TAD strings

Parece que a mas de uno les estuvo causando problemas el hecho de que el header del TAD de strings se llame igual que el de la librería estándar.

En este post del foro se menciona esto...

Estaría bien renombrarlo un poco?

Para usar el estándar aparentemente están teniendo que hacer:

#include </usr/include/string.h>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.