/*
 * Copyright (c) 1998-2004 by Wayne C. Gramlich.
 * All rights reserved.
 */

/*
 * This file implements a pretty direct implementation of an fd_set.
 */

#ifndef STHEADERS_H
#include "stheaders.h"
#endif

#ifndef UNIX_ASSERT_H
#include "unix_assert.h"
#endif

#ifndef FILE_SET_H
#include "file_set.h"
#endif

extern module___object file_set__module__object;
extern type___reference unix_system_type_ref;

static File_set_struct file_set_struct;
File_set file_set___initial = &file_set_struct;

static object___object file_set_initial_object = {
    "",					/* Package name */
    "file_set",				/* Type name */
    "??",				/* Object name */
    (type___reference *)0,		/*XXX: Fix me */
    (int *)0,				/* Size of character object */
    0,					/* Static needs count */
    (need___entry *)0,			/*XXX: Fix me Static needs */
    0,					/* Parameter needs count */
    (need___entry *)0,			/* Parameter needs */
    (void **)&file_set___initial,	/* Object pointer */
    (instantiation___object *)0		/* Instantiation list */
};
static object___object *object_list[1] = {
	&file_set_initial_object,
};

void
file_set__external__initialize(void)
{
    extern module___object file_set__module__object;

    file_set__module__object.object_count = 1;
    file_set__module__object.objects = object_list;
}

/*
 * file_set__address_get(file_set)
 *	This procedure will return the address of {file_set}.
 */
unsigned
file_set__address_get(
    File_set file_set)
{
    return (unsigned)file_set;
}

/*
 * file_set__and()
 *	This procedure will store the result of a bitwise AND of
 *	{from_file_set1} and {from_file_set2} into {to_file_set}.
 */
void
file_set__and(
    File_set to_file_set,
    File_set from_file_set1,
    File_set from_file_set2)
{
#ifdef LINUX
    int size;
    char *to_pointer;
    char *from_pointer1;
    char *from_pointer2;

    to_pointer = (char *)to_file_set;
    from_pointer1 = (char *)from_file_set1;
    from_pointer2 = (char *)from_file_set2;
    for (size = sizeof *to_file_set; size > 0; size--) {
	*to_pointer++ = *from_pointer1++ & *from_pointer2++;
    }
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
}

/*
 * file_set__create()
 *	This procedure will create and return a {file_set} object.
 */
File_set
file_set__create(void)
{
    File_set file_set;

#ifdef LINUX
    file_set = (File_set)malloc(sizeof(File_set_struct));
    assert(file_set != (File_set)0);
    FD_ZERO(file_set);
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
    return file_set;
}

/*
 * file_set__clear(file_set)
 *	This procedure will clear the contents of {file_set}.
 */
void
file_set__clear(
    File_set file_set)
{
#ifdef LINUX
    FD_ZERO(file_set);
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
}

/*
 * file_set__contents_copy(to_file_set, from_file_set)
 *	This procedure will copy the contents of {from_file_set}
 *	to {to_file_set}.
 */
void
file_set__contents_copy(
    File_set to_file_set,
    File_set from_file_set)
{
#ifdef LINUX
    *to_file_set = *from_file_set;
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
}

/*
 * file_set__enter(file_set, file_descriptor_number)
 *	This procedure will add {file_descriptor_number} to {file_set}.
 */
void
file_set__enter(
    File_set file_set,
    unsigned file_descriptor_number)
{
#ifdef LINUX
    if (file_descriptor_number < __FD_SETSIZE) {
	FD_SET(file_descriptor_number, file_set);
    }
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
}

/*
 * file_set__is_in(file_set, file_descriptor_number)
 *	This procedure will return 1 if {file_descriptor_number} is in
 *	{file_set} and 0 otherwise.
 */
int
file_set__is_in(
    File_set file_set,
    unsigned file_descriptor_number)
{
#ifdef LINUX
    if (file_descriptor_number < __FD_SETSIZE) {
	if (FD_ISSET(file_descriptor_number, file_set)) {
	    return 1;
	}
    }
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
    return 0;
}

/*
 * file_set__maximum(file_set)
 *	This procedure will return the maximum file descriptor number
 *	in {file_set}.  If no file descriptor numbers are in {file_set},
 *	-1 is returned.
 */
int
file_set__maximum(
    File_set file_set)
{
    int index;

#ifdef LINUX
    /* FIXME: This could be a lot faster!!! */
    for (index = __FD_SETSIZE - 1; index >= 0; index--) {
	if (FD_ISSET(index, file_set)) {
	    return index;
	}
    }
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
    return index;
}

/*
 * file_set__maximum_possible()
 *	This procedure returns the maximum possible number that can be set
 *	in a {file_set} object.
 */
unsigned
file_set__maximum_possible(void)
{
#ifdef WINDOWS
    return __FD_SETSIZE - 1;
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
    return 0;
#endif /* WINDOWS */
}

/*
 * file_set__remove(file_set, file_descriptor_number)
 *	This procedure will remove {file_descriptor_number} from {file_set}.
 */
void
file_set__remove(
    File_set file_set,
    unsigned file_descriptor_number)
{
#ifdef LINUX
    if (file_descriptor_number < __FD_SETSIZE) {
	FD_CLR(file_descriptor_number, file_set);
    }
#endif /* LINUX */
#ifdef WINDOWS
    assert(0);
#endif /* WINDOWS */
}


