#include "filasm.h"

struct FilaMStr
{
    size_t tamanho, base, topo;
    void **m;
};


FilaM *FMcria(size_t tamanho)

{
    FilaM *f;
    
    if((f = malloc(sizeof(*f))) == 0)
	return 0;
    if(tamanho == 0)
	f->tamanho = FMTAMANHO + 1;
    else
	f->tamanho = tamanho + 1;
    if((f->m = calloc(f->tamanho, sizeof(void *))) == 0)
    {
	free(f);
	return 0;
    }
    f->topo = f->base = 0;
    return f;
}


void FMdestroi(FilaM *f)

{
    if(f == 0)
	return;
    free(f->m);
    free(f);
}


FilaM *FMesvazia(FilaM *f)

{
    if(f != 0)
	f->topo = f->base;
    return f;
}


size_t FMquantos(FilaM *f)

{
    if(f == 0)
	return 0;
    return f->topo >= f->base ? f->topo - f->base : f->topo - f->base +
	f->tamanho;
}


int FMcheia(FilaM *f)

{
    if(f == 0)
	return 0;
    return FMquantos(f) == f->tamanho - 1;
}


FilaM *FMpoe(FilaM *f, void *d)

{
    if(f == 0 || FMcheia(f))
	return 0;
    f->m[f->topo++] = d;
    if(f->topo == f->tamanho)
	f->topo = 0;
    return f;
}


void *FMtira(FilaM *f)

{
    void *d;
    
    if(f == 0 || f->topo == f->base)
	return 0;
    d = f->m[f->base++];
    if(f->base == f->tamanho)
	f->base = 0;
    return d;
}


#ifdef TESTE

#include <stdio.h>

int main(void)

{
    FilaM *f;
    int val, *pval;
    
    f = FMcria(7);
    
    do
    {
	printf("Valor a inserir (0 para sair, negativo para retirar): ");
	if(scanf("%d", &val) != 1)
	    return EXIT_FAILURE;
	if(val < 0)
	{
	    printf("Retirando: ");
	    if((pval = FMtira(f)) == 0)
		puts("fila vazia!");
	    else
	    {
		printf("Retirei %d.\n", *pval);
		free(pval);
	    }
	}
	else if(val > 0)
	{
	    printf("Inserindo: ");
	    if((pval = malloc(sizeof(int))) == 0)
		return EXIT_FAILURE;
	    *pval = val;
	    if(FMpoe(f, pval) == 0)
		puts("pilha cheia!");
	    else
		printf("Inseri %d.\n", val);
	}
    }
    while(val != 0);

    if(FMcheia(f))
	puts("Esta' cheia!");
    
    if(FMquantos(f) != 0)
    {
	printf("Retirando:");
	while((pval = FMtira(f)) != 0)
	{
	    printf(" %d", *pval);
	    free(pval);
	}
	putchar('\n');
    }
    
    FMdestroi(f);

    return EXIT_SUCCESS;
}

#endif