# HG changeset patch # User Eris Caffee # Date 1293610475 21600 # Node ID 5db060528d2b3931bc17e7ee24e348f3b0fc87fe Initial import diff -r 000000000000 -r 5db060528d2b CMakeLists.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMakeLists.txt Wed Dec 29 02:14:35 2010 -0600 @@ -0,0 +1,179 @@ +############################################################################### +# +# A generalized cmake file for developing cross-platform games. +# +# Copyright (C) 2010 Sarah Eris Horsley Caffee +# +# This 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. +# +# This program 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 this program. If not, see . +# +# +# Instructions: +# This cmake file assumes that your source files are laid in out in the +# following manner: +# +# project_dir\ Top level directory of the project. +# |---include\ Header files are here. +# |---src\ Source files are here. +# |---build\ Binaries/objects go here. Run cmake from here. +# !---cmake\ +# | |---modules\ Custom cmake include files, if any, go here. +# |---CMakeLists.txt This file. +# +# You may have more directories, of course, but these are assumed. You probably +# want more than one build directory. I normally have build-linux\ +# and build-windows\ directories. +# +# Set the App_Name variable, below, to the name of your application and you +# are ready to start. Run ccmake, or cmake-gui from within your build +# directory, choose the options you need, such as enabling SDL, and you +# should be good to go. +# +# You can uncomment the "SET (CMAKE_VERBOSE_MAKEFILE ON) command if you +# need to debug the actual makefile that is generated. +# +# On windows, you may need to set the SDLDIR environment variable to the location +# of your SDL installation before you run cmake-gui. +# +# When writing path names on Windows, such as when manually specifiying a +# file or directory name, either use unix-style forward slashes '/' in the +# path names or use double backslashes. If you use a single backslash as the +# path name seperator, then cmake will interpret it as an esacpe sequence. +# Thus, write "C:/source" or "C:\\source" instead of "C:\source". It's +# probably best to use forward slashes in case to ever have a situation +# where cmake needs to do recursive processing: each level of cmake will +# strip out one of the slashes, so if there are two lev3els of cmake you +# need to write \\\, three levels requires \\\\, etc. +# +# Note that some of the cmake support scripts that find libraries for you +# can be controlled by environment variables. For example, you can set the +# SDLDIR environment variable before running cmake in order to point to +# a different version of SDL than your systems default copy. This is useful +# for trying out cutting edge versions of libraries without installing them +# system wide. + +cmake_minimum_required (VERSION 2.6 FATAL_ERROR) +#set (CMAKE_VERBOSE_MAKEFILE ON) + +# Name your program! +set (App_Name "LinkedList") +if (App_Name STREQUAL "") + message (FATAL_ERROR "You must set the App_Name variable!") +endif () + +# Every project must have a name. +project (${App_Name}) + + +################################################################################ +# Special options + + +################################################################################ +# Ensure that we are not building in our source directories. + +set (Build_Dir_OK "TRUE") +string (REGEX MATCH "^${CMAKE_SOURCE_DIR}" In_Sub_Dir ${CMAKE_BINARY_DIR}) +if (In_Sub_Dir) + string (REGEX MATCH "^${CMAKE_SOURCE_DIR}/build" In_Build_Dir ${CMAKE_BINARY_DIR}) + if (NOT In_Build_Dir) + set (Build_Dir_OK "FALSE") + endif () +endif () + +if (NOT Build_Dir_OK) + message (FATAL_ERROR "You must run cmake from a directory that is not in your source tree, or that is in a special subdirectory of the tree whose name begins with 'build'.") +endif () + + +################################################################################ +# Set up the basic build environment +# A build type defines which options are passed to the compiler, and there are +# several that CMake defines by default. It does not set one by default, though +# so we need to set the build type manually here, and we are setting it to the +# generally useful "Release with debug info" + +if (CMAKE_BUILD_TYPE STREQUAL "") + # CMake defaults to leaving CMAKE_BUILD_TYPE empty. This messes up + # differentiation between debug and release builds. + set (CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." FORCE) +endif () + + +################################################################################ +# When using GCC turn on lots of warnings. + +if (CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-pedantic -Wall) +endif () + + +################################################################################ + +option(Option_Profile_Program "Build for gprof profiling." OFF) +if (Option_Profile_Program) + add_definitions(-pg) + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pg") +endif () + + +################################################################################ +# The core project files + +set (SRCS_LinkedList + src/LinkedList.c + include/LinkedList.h +) + +include_directories ( + ${PROJECT_SOURCE_DIR}/include +) + +# Build both static and shared libraries +# The target properties are needed because, by default, the output name +# will be the name in the add_library command, and we need to have different +# names in the two commands for the shared and static versions, even though +# we want the final files to have the same names with different extensions. +# +# The prefix is needed mostly in case we build on windows, which has no prefix +# by default. +# +# The clean_direct_output option makes sure that the two lib builds don't +# clobber each others temp files since they are being built from the same +# sources. + +add_library (LinkedList SHARED + ${SRCS_LinkedList} +) +set_target_properties (LinkedList PROPERTIES OUTPUT_NAME "LinkedList") +set_target_properties (LinkedList PROPERTIES PREFIX "lib") +set_target_properties (LinkedList PROPERTIES CLEAN_DIRECT_OUTPUT 1) + +add_library (LinkedList-static STATIC + ${SRCS_LinkedList} +) +set_target_properties (LinkedList-static PROPERTIES OUTPUT_NAME "LinkedList") +set_target_properties (LinkedList-static PROPERTIES PREFIX "lib") +set_target_properties (LinkedList-static PROPERTIES CLEAN_DIRECT_OUTPUT 1) + +# Build a test application. + +add_executable (test + src/main.c +) + +target_link_libraries (test + LinkedList +) + + diff -r 000000000000 -r 5db060528d2b include/LinkedList.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/include/LinkedList.h Wed Dec 29 02:14:35 2010 -0600 @@ -0,0 +1,55 @@ +/******************************************************************************* + * linked_list + * + * A simple doubly linked list class in C. + * + * Not thread safe. + * + * Since this class does not attempt to manage memory for the actual stored + * objects, there is no "clear" method to delete the entire list. Instead, + * the user must pop the entire list and delete the individually returned + * objects one at a time. + * + * A potential improvement would be to allow the registration of an object + * destructor at list creation which could then be used by a clear() method. + * + * + * + * + * OOH SHINY! + * http://tinobox.com/wordpress/object-oriented-c-coding/ + * + * Looks liks good stuff. Must read. + * + ******************************************************************************/ + +#ifndef LINKEDLIST_H +#define LINKEDLIST_H + +typedef struct ll_node ll_node; + +typedef struct LinkedList LinkedList; +struct LinkedList + { + /* Public */ + void * (* push) (LinkedList * this, void * data); + void * (* pop) (LinkedList * this); + void * (* insert)(LinkedList * this, void * data); + void * (* remove)(LinkedList * this); + void * (* insert_at_head)(LinkedList * this, void * data); + int (* size) (LinkedList * this); + void * (* head) (LinkedList * this); + void * (* tail) (LinkedList * this); + void * (* next) (LinkedList * this); + void * (* prev) (LinkedList * this); + void * (* data) (LinkedList * this); + + /* Private (notionally, at least) */ + ll_node * Head; + ll_node * Curr; + ll_node * Tail; + int Size; + }; + +#endif + diff -r 000000000000 -r 5db060528d2b src/LinkedList.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/LinkedList.c Wed Dec 29 02:14:35 2010 -0600 @@ -0,0 +1,312 @@ +/******************************************************************************* + * LinkedList + * + * A simple doubly linked list class in C. + * + * Not thread safe. + * + ******************************************************************************/ + +#include "LinkedList.h" + +#include + +/******************************************************************************* + * "Private" inner class. + */ +struct ll_node + { + ll_node * next; + ll_node * prev; + void * data; + }; + + +/******************************************************************************* + * Insert an element at end of list. + * Sets curr and tail pointers to the new node. + * Returns data on success, NULL on error. + */ +void * ll_push(LinkedList * this, void * data) + { + ll_node * new_node; + + if ((!this) || (!data)) + return NULL; + + if (!(new_node = calloc(1, sizeof(ll_node)))) + return NULL; + + new_node->data = data; + + if (!(this->Tail)) + { + /* empty list */ + this->Head = this->Tail = this->Curr = new_node; + } + else + { + new_node->prev = this->Tail; + this->Tail->next = new_node; + this->Tail = this->Curr = new_node; + } + + this->Size++; + return this->Curr->data; + } + + +/******************************************************************************* + * Insert an element after the one pointed to by this->curr. + * Sets curr pointer to the new node (and tail if curr = tail when called). + * Returns data on success, NULL on error. + */ +void * ll_insert(LinkedList * this, void * data) + { + ll_node * new_node; + + if ((!this) || (!data)) + return NULL; + + if (this->Curr == this->Tail) + { + return ll_push(this, data); + } + + if (!(new_node = calloc(1, sizeof(ll_node)))) + return NULL; + + new_node->data = data; + new_node->prev = this->Curr; + new_node->next = this->Curr->next; + this->Curr->next = new_node; + new_node->next->prev = new_node; + this->Curr = new_node; + + this->Size++; + return this->Curr->data; + } + + +/******************************************************************************* + * Insert an element and make it the new head. + * Sets head and curr pointers to the new node. + * Returns data on success, NULL on error. + */ +void * ll_insert_at_head(LinkedList * this, void * data) + { + ll_node * new_node; + + if ((!this) || (!data)) + return NULL; + + if (!(new_node = calloc(1, sizeof(ll_node)))) + return NULL; + + new_node->data = data; + new_node->prev = NULL; + new_node->next = this->Head;; + + if (this->Head) + this->Head->prev = new_node; + this->Head = this->Curr = new_node; + + this->Size++; + return this->Curr->data; + } + + +/******************************************************************************* + * Remove the tail element from the list. + * Sets curr to tail. + * Return data, or NULL if the list is empty. + */ +void * ll_pop(LinkedList * this) + { + void * data; + ll_node * tmp; + + if (!this) + return NULL; + + if (!(this->Tail)) + return NULL; + + tmp = this->Tail; + data = this->Tail->data; + + if (!(this->Tail->prev)) + { + /* Only element in list */ + this->Head = this->Tail = this->Curr = NULL; + } + else + { + this->Tail->prev->next = NULL; + this->Tail = this->Curr = this->Tail->prev; + } + + free(tmp); + this->Size--; + + return data; + } + + +/******************************************************************************* + * Delete the element pointed to by this->curr. + * A pointer to the stored data is returned, or NULL is no list or an empty list + * is specified. It must be freed by the caller. + */ +void * ll_remove(LinkedList * this) + { + void * data; + ll_node * tmp; + + if (!this) + return NULL; + + if (this->Curr == this->Tail) + return ll_pop(this); + + tmp = this->Curr; + data = this->Curr->data; + + if (this->Curr == this->Head) + { + this->Curr->next->prev = NULL; + this->Head = this->Curr = this->Head->next; + } + else + { + this->Curr->prev->next = this->Curr->next; + this->Curr->next->prev = this->Curr->prev; + } + + free(tmp); + this->Size--; + + return data; + } + + +/******************************************************************************* + * Return the size of the list, or -1 is list is null. + */ +int ll_size(LinkedList * this) + { + if (!this) return -1; + + return this->Size; + } + + +/******************************************************************************* + * Select the first element in the list if there is one. + * Return data pointer of new current element, or NULL is list is empty. + */ +void * ll_head(LinkedList * this) + { + if (!this) return NULL; + + this->Curr = this->Head; + + if (this->Curr) + return this->Curr->data; + else + return NULL; + } + + +/******************************************************************************* + * Select the last element in the list if there is one. + * Return data pointer of new current element, or NULL is list is empty. + */ +void * ll_tail(LinkedList * this) + { + if (!this) return NULL; + + this->Curr = this->Tail; + + if (this->Curr) + return this->Curr->data; + else + return NULL; + } + + +/******************************************************************************* + * Select the next element in the list if there is one. + * Return data pointer of new current element, or NULL is list is empty. + */ +void * ll_next(LinkedList * this) + { + if (!this) return NULL; + + if (this->Curr->next) + this->Curr = this->Curr->next; + + if (this->Curr) + return this->Curr->data; + else + return NULL; + } + + +/******************************************************************************* + * Select previous element in the list if there is one. + * Return data pointer of new current element, or NULL is list is empty. + */ +void * ll_prev(LinkedList * this) + { + if (!this) return NULL; + + if (this->Curr->prev) + this->Curr = this->Curr->prev; + + if (this->Curr) + return this->Curr->data; + else + return NULL; + } + + +/******************************************************************************* + * Return the data pointer of the current node, or NULL is list is empty. + */ +void * ll_data(LinkedList * this) + { + if (!this) return NULL; + + if (this->Curr) + return this->Curr->data; + else + return NULL; + } + + +/******************************************************************************* + * Constuctor. Call this when creating a new list. + */ +void ll_init(LinkedList * this) + { + if (this) + { + this->push = ll_push; + this->pop = ll_pop; + this->insert = ll_insert; + this->remove = ll_remove; + this->insert_at_head = ll_insert_at_head; + this->size = ll_size; + this->head = ll_head; + this->tail = ll_tail; + this->next = ll_next; + this->prev = ll_prev; + this->data = ll_data; + + this->Head = this->Tail = this->Curr = NULL; + this->Size = 0; + } + } + + diff -r 000000000000 -r 5db060528d2b src/main.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/main.c Wed Dec 29 02:14:35 2010 -0600 @@ -0,0 +1,172 @@ +/******************************************************************************* + * LinkedList + * + * A simple doubly linked list class in C. + * + * + * Test driver for LinkedList + * + ******************************************************************************/ + +#include "LinkedList.h" + +#include +#include + + +typedef struct mode_info mode_info; +struct mode_info + { + int sizeid; + int w; + int h; + int r; + }; + +int main (int argc, char ** argv) + { + LinkedList list1; + LinkedList list2; + + int * p_int; + mode_info * p_mode; + + int i; + int size; + + + ll_init(&list1); + ll_init(&list2); + + for (i=0; i<10; ++i) + { + p_int = malloc(sizeof(int)); + *p_int = i; + list1.push(&list1, p_int); + } + p_int = malloc(sizeof(int)); + *p_int = 17; + list1.push(&list1, p_int); + + list1.head(&list1); + list1.next(&list1); + p_int = malloc(sizeof(int)); + *p_int = 23; + list1.insert(&list1, p_int); + + list1.tail(&list1); + p_int = malloc(sizeof(int)); + *p_int = 109; + list1.insert(&list1, p_int); + + list1.head(&list1); + list1.next(&list1); + list1.next(&list1); + list1.next(&list1); + list1.next(&list1); + list1.next(&list1); + free(list1.remove(&list1)); + + list1.head(&list1); + free(list1.remove(&list1)); + + list1.tail(&list1); + free(list1.remove(&list1)); + + list1.prev(&list1); + list1.prev(&list1); + free(list1.remove(&list1)); + + p_int = malloc(sizeof(int)); + *p_int = 77; + list1.insert_at_head(&list1, p_int); + + + + p_mode = calloc(1, sizeof(mode_info)); + p_mode->sizeid = 1; + p_mode->w = 640; + p_mode->h = 480; + p_mode->r = 60; + list2.push(&list2, p_mode); + + p_mode = calloc(1, sizeof(mode_info)); + p_mode->sizeid = 2; + p_mode->w = 800; + p_mode->h = 600; + p_mode->r = 85; + list2.push(&list2, p_mode); + + p_mode = calloc(1, sizeof(mode_info)); + p_mode->sizeid = 3; + p_mode->w = 1024; + p_mode->h = 768; + p_mode->r = 72; + list2.push(&list2, p_mode); + + p_mode = calloc(1, sizeof(mode_info)); + p_mode->sizeid = 4; + p_mode->w = 1280; + p_mode->h = 1024; + p_mode->r = 60; + list2.push(&list2, p_mode); + + + printf("list2:\n"); + + list2.head(&list2); + size = list2.size(&list2); + for (i=0; isizeid, p_mode->w, p_mode->h, p_mode->r); + list2.next(&list2); + } + printf("\n\n"); + + size = list1.size(&list1); + printf("List1 has %d elements\n", size); + list1.head(&list1); + for (i=0; i