# HG changeset patch # User John Tsiombikas # Date 1414919265 -7200 # Node ID 0a45dfe93e6639c3090646fbf09f3fade9234bde initial commit diff -r 000000000000 -r 0a45dfe93e66 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,4 @@ +\.o$ +\.swp$ +\.d$ +^mtglist$ diff -r 000000000000 -r 0a45dfe93e66 Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,12 @@ +src = $(wildcard src/*.c) +obj = $(src:.c=.o) +bin = mtglist + +CFLAGS = -pedantic -Wall -g + +$(bin): $(obj) + $(CC) -o $@ $(obj) $(LDFLAGS) + +.PHONE: clean +clean: + rm -f $(obj) $(bin) diff -r 000000000000 -r 0a45dfe93e66 cardlist --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cardlist Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,374 @@ +-|Crystal Vein|Land|2|6ed| +-|Geothermal Crevice|Land|1|inv| +-|High Market|Land|1|mmq|foil +-|Mystic Monastery|Land|1|ktk| +-|Sulfur Vent|Land|1|inv| +*|Armadillo Cloak|Enchantment|2|inv|Green/White +*|Aura Mutation|Instant|1|inv|Green/White +*|Battlefield Forge|Land|1|apc|Red/White +*|Captain's Maneuver|Instant|1|apc|Red/White +*|Chief of the Scale|Creature|1|ktk|White/Black +*|Cinder Shade|Creature|1|inv|Black/Red +*|Gaea's Skyfolk|Creature|1|apc|Green/Blue +*|Galina's Knight|Creature|1|inv|White/Blue +*|Hanna, Ship's Navigator|Creature|1|inv|White/Blue +*|Heroes' Reunion|Instant|1|inv|Green/White +*|Jungle Barrier|Creature|1|apc|Green/Blue +*|Jungle Hollow|Land|1|ktk|Black/Green +*|Llanowar Dead|Creature|1|apc|Black/Green +*|Ordered Migration|Sorcery|1|inv|White/Blue +*|Putrid Warrior|Creature|1|apc|White/Black +*|Shivan Zombie|Creature|1|inv|Black/Red +*|Sorin, Solemn Visitor|Planeswalker|1|ktk|White/Black +*|Tainted Field|Land|1|tor|White/Black +*|Temporal Spring|Sorcery|1|apc|Green/Blue +*|Yavimaya Kavu|Creature|1|inv|Red/Green +Artifact|Amulet of Kroog|Artifact|1|5ed| +Artifact|Ashnod's Transmogrant|Artifact|1|5ed| +Artifact|Coiled Tinviper|Creature|1|tmp| +Artifact|Crooked Scales|Artifact|1|mmq| +Artifact|Dancing Scimitar|Creature|1|9ed| +Artifact|Dodecapod|Creature|1|apc| +Artifact|Glasses of Urza|Artifact|1|5ed| +Artifact|Iron Lance|Artifact|1|mmq| +Artifact|Iron Star|Artifact|1|5ed| +Artifact|Ivory Cup|Artifact|1|6ed| +Artifact|Juggernaut|Artifact|1|m15| +Artifact|Patagia Golem|Creature|1|6ed| +Artifact|Rod of Ruin|Artifact|1|9ed| +Artifact|Rusting Golem|Creature|1|nms| +Artifact|Skull Catapult|Artifact|1|5ed| +Artifact|Throne of Bone|Artifact|1|5ed| +Artifact|Tigereye Cameo|Artifact|1|apc| +Artifact|Tyrant's Machine|Artifact|1|m15|foil +Artifact|Urza's Blueprints|Artifact|1|ulg| +Artifact|Wall of Spears|Creature|1|5ed| +Black|Agonizing Demise|Instant|1|inv| +Black|Black Cat|Creature|1|m15| +Black|Blight|Enchantment|1|6ed| +Black|Blood Pet|Creature|1|6ed| +Black|Bog Wraith|Creature|1|5ed| +Black|Bog Wraith|Creature|1|6ed| +Black|Cabal Ritual|Instant|1|tor| +Black|Cackling Witch|Creature|1|mmq| +Black|Carrion Crow|Creature|1|m15| +Black|Cateran Persuader|Creature|1|mmq| +Black|Coercion|Sorcery|1|5ed| +Black|Covenant of Blood|Sorcery|1|m15| +Black|Crypt Sliver|Creature|1|lgn| +Black|Cursed Land|Enchantment|1|5ed| +Black|Dark Banishing|Instant|1|tmp| +Black|Dark Ritual|Instant|1|5ed| +Black|Dark Triumph|Instant|1|nms| +Black|Dauthi Horror|Creature|1|tmp| +Black|Dead Ringers|Sorcery|1|apc| +Black|Despondency|Enchantment|1|usg| +Black|Drain Life|Sorcery|1|5ed| +Black|Fallen Angel|Creature|1|5ed| +Black|Firescreamer|Creature|1|inv| +Black|Frozen Shade|Creature|1|5ed| +Black|Grave Defiler|Creature|1|apc| +Black|Gravebane Zombie|Creature|2|6ed| +Black|Gravedigger|Creature|1|6ed| +Black|Haunted Crossroads|Enchantment|1|mmq| +Black|Krovikan Fetish|Enchantment|1|5ed| +Black|Lost Soul|Creature|1|5ed| +Black|Maggot Therapy|Enchantment|1|mmq| +Black|Mind Extraction|Sorcery|1|apc| +Black|Mind Swords|Sorcery|1|nms| +Black|Necra Disciple|Creature|1|apc| +Black|Nightscape Apprentice|Creature|1|inv| +Black|Phyrexian Slayer|Creature|1|inv| +Black|Putrid Imp|Creature|1|tor| +Black|Python|Creature|2|6ed| +Black|Quagmire Druid|Creature|1|apc| +Black|Razortooth Rats|Creature|1|6ed| +Black|Reckless Spite|Instant|2|inv| +Black|Rouse|Instant|1|mmq| +Black|Scathe Zombies|Creature|1|6ed| +Black|Sever Soul|Sorcery|1|mmq| +Black|Shambling Attendants|Creature|1|ktk| +Black|Skulking Fugitive|Creature|1|mmq|foil +Black|Snuff Out|Instant|1|mmq| +Black|Swamp|Land|18|*|9x5ed,1x6ed,6xinv,2xm15 +Black|Syphon Soul|Sorcery|2|6ed| +Black|Terror|Instant|1|5ed| +Black|Undertaker|Creature|1|mmq| +Black|Unmake the Graves|Instant|1|m15| +Black|Vampiric Tutor|Instant|1|6ed| +Black|Vicious Hunger|Sorcery|1|nms| +Black|Vile Deacon|Creature|1|lgn| +Black|Waste Away|Instant|1|tor| +Black|Weakness|Enchantment|1|5ed| +Black|Zombie Master|Creature|1|6ed| +Blue|Barrin's Unmaking|Instant|1|inv| +Blue|Boomerang|Instant|1|5ed| +Blue|Boomerang|Instant|1|6ed| +Blue|Brainstorm|Instant|1|5ed| +Blue|Brainstorm|Instant|1|mmq| +Blue|Buoyancy|Enchantment|1|mmq| +Blue|Cephalid Aristocrat|Creature|1|tor| +Blue|Cephalid Sage|Creature|1|tor| +Blue|Cephalid Snitch|Creature|1|tor| +Blue|Cloud Sprite|Creature|2|mmq| +Blue|Coastal Drake|Creature|1|apc| +Blue|Coral Eel|Creature|2|9ed| +Blue|Counterspell|Instant|1|5ed| +Blue|Dark Maze|Creature|1|5ed| +Blue|Daze|Instant|1|nms| +Blue|Deep Analysis|Sorcery|1|tor| +Blue|Diffusion Sliver|Creature|1|m15| +Blue|Diplomatic Escort|Creature|2|mmq| +Blue|Diplomatic Immunity|Enchantment|1|mmq| +Blue|Dream Thrush|Creature|1|inv| +Blue|Faerie Squadron|Creature|1|inv| +Blue|Flight|Enchantment|1|5ed| +Blue|Fugitive Wizard|Creature|1|9ed| +Blue|Gaseous Form|Enchantment|1|5ed| +Blue|Giant Crab|Creature|1|tmp| +Blue|Giant Octopus|Creature|3|9ed| +Blue|Glacial Crasher|Creature|1|m15| +Blue|Harmattan Efreet|Creature|1|6ed| +Blue|Horned Turtle|Creature|1|6ed| +Blue|Index|Sorcery|1|9ed| +Blue|Inspiration|Instant|2|6ed| +Blue|Invisibility|Enchantment|1|m15| +Blue|Island|Land|22|*|8x5ed,6xinv,8x9ed +Blue|Jeskai Windscout|Creature|1|ktk| +Blue|Jilt|Instant|1|apc| +Blue|Juxtapose|Sorcery|1|5ed| +Blue|Living Airship|Creature|1|apc| +Blue|Manipulate Fate|Sorcery|2|inv| +Blue|Memory Lapse|Instant|1|5ed| +Blue|Mind Bomb|Sorcery|1|5ed| +Blue|Mistform Sliver|Creature|1|lgn| +Blue|Oraxid|Creature|1|nms| +Blue|Phantasmal Terrain|Enchantment|1|5ed| +Blue|Phantasmal Terrain|Enchantment|1|inv| +Blue|Port Inspector|Creature|2|mmq| +Blue|Power Sink|Instant|1|5ed| +Blue|Prodigal Sorcerer|Creature|1|5ed| +Blue|Prohibit|Instant|2|inv| +Blue|Psychic Venom|Enchantment|1|5ed| +Blue|Psychic Venom|Enchantment|2|6ed| +Blue|Sapphire Leech|Creature|1|inv| +Blue|Saprazzan Outrigger|Creature|1|mmq| +Blue|Sea Monster|Creature|1|tmp| +Blue|Segovian Leviathan|Creature|1|5ed| +Blue|Segovian Leviathan|Creature|1|6ed| +Blue|Shadow Rift|Instant|1|tor| +Blue|Sneaky Homunculus|Creature|1|nms| +Blue|Spell Blast|Instant|1|tmp| +Blue|Storm Crow|Creature|1|6ed| +Blue|Stringing Licid|Creature|1|tmp| +Blue|Synapse Sliver|Creature|1|lgn| +Blue|Talas Air Ship|Creature|1|po2| +Blue|Telepathy|Enchantment|1|9ed| +Blue|Tower Drake|Creature|1|inv| +Blue|Updraft|Instant|1|5ed| +Blue|Vizzerdrix|Creature|2|9ed| +Blue|Vodalian Merchant|Creature|1|inv| +Blue|Vodalian Serpent|Creature|1|inv| +Blue|Voidmage Apprentice|Creature|1|lgn| +Blue|Warped Researcher|Creature|1|lgn| +Blue|Welkin Tern|Creature|1|m15| +Blue|Whirlpool Warrior|Creature|1|apc| +Blue|Wind Drake|Creature|1|9ed| +Blue|Worldly Counsel|Instant|1|inv| +Green|Aggressive Urge|Instant|1|inv| +Green|Aurochs|Creature|1|5ed| +Green|Berserk Murlodont|Creature|1|lgn| +Green|Birds of Paradise|Creature|1|6ed| +Green|Blanchwood Armor|Enchantment|1|9ed| +Green|Cat Warriors|Creature|1|6ed| +Green|Cockatrice|Creature|1|5ed| +Green|Craw Wurm|Creature|1|9ed| +Green|Eladamri, Lord of Leaves|Creature|1|tmp| +Green|Elven Cache|Sorcery|1|6ed| +Green|Enormous Baloth|Creature|2|9ed| +Green|Femeref Archers|Creature|1|6ed| +Green|Ferocity|Enchantment|1|mmq| +Green|Forest|Land|29|*|9x5ed,6x6ed,6xinv,8x9ed +Green|Gaea's Balance|Sorcery|1|apc| +Green|Gather Courage|Instant|1|m15| +Green|Giant Growth|Instant|2|6ed| +Green|Glade Gnarr|Creature|2|apc| +Green|Gorilla Chieftain|Creature|1|6ed| +Green|Grizzly Bears|Creature|1|5ed| +Green|Grizzly Bears|Creature|2|9ed| +Green|Gurzigost|Creature|1|tor| +Green|Hickory Woodlot|Land|1|mmq| +Green|Horned Sliver|Creature|1|tmp| +Green|Hungry Mist|Creature|1|5ed| +Green|Kavu Climber|Creature|1|inv| +Green|Krosan Constrictor|Creature|1|tor| +Green|Living Totem|Creature|1|m15| +Green|Llanowar Elite|Creature|1|inv| +Green|Llanowar Vanguard|Creature|1|inv| +Green|Longshot Squad|Creature|1|ktk| +Green|Meandering Towershell|Creature|1|ktk|foil +Green|Naturalize|Instant|1|9ed| +Green|Norwood Ranger|Creature|2|9ed| +Green|Penumbra Bobcat|Creature|1|apc| +Green|Pincer Spider|Creature|1|inv| +Green|Pulse of Llanowar|Enchantment|1|inv| +Green|Quick Sliver|Creature|1|lgn| +Green|Rampant Growth|Sorcery|1|9ed| +Green|Reclamation Sage|Creature|1|m15| +Green|Regeneration|Enchantment|1|5ed| +Green|Regeneration|Enchantment|2|6ed| +Green|Rootbreaker Wurm|Creature|1|tmp| +Green|Runeclaw Bear|Creature|1|m15| +Green|Rushwood Dryad|Creature|1|mmq| +Green|Rushwood Grove|Land|1|mmq| +Green|Rushwood Herbalist|Creature|2|mmq| +Green|Saproling Burst|Enchantment|1|nms| +Green|Satyr Wayfinder|Creature|1|m15| +Green|Savage Punch|Sorcery|1|ktk| +Green|Scaled Wurm|Creature|2|5ed| +Green|Scryb Sprites|Creature|1|5ed| +Green|Shrink|Instant|1|5ed| +Green|Skyshroud Ridgeback|Creature|1|nms| +Green|Skyshroud Sentinel|Creature|1|nms| +Green|Snorting Gahr|Creature|1|mmq| +Green|Spined Wurm|Creature|1|9ed| +Green|Spontaneous Generation|Sorcery|1|mmq| +Green|Stream of Life|Sorcery|1|6ed| +Green|Sylvan Library|Enchantment|1|5ed| +Green|Thicket Basilisk|Creature|1|6ed| +Green|Tiger Claws|Enchantment|1|mmq| +Green|Tranquil Path|Sorcery|1|apc| +Green|Treefolk Healer|Creature|1|inv| +Green|Untamed Wilds|Sorcery|1|6ed| +Green|Verdant Haven|Enchantment|1|m15| +Green|Vigorous Charge|Instant|1|inv| +Green|Wandering Stream|Sorcery|1|inv| +Green|Wanderlust|Enchantment|1|5ed| +Green|Wild Growth|Enchantment|1|5ed| +Green|Winter Blast|Sorcery|1|5ed| +Green|Woodripper|Creature|1|nms| +Green|Yavimaya Wurm|Creature|1|ulg| +Green/Black|Life/Death|Sorcery|1|apc| +Red|Act on Impulse|Sorcery|1|m15| +Red|Aether Flash|Enchantment|1|6ed| +Red|Anaba Shaman|Creature|1|6ed| +Red|Anaba Shaman|Creature|1|9ed| +Red|Battle Rampart|Creature|1|mmq| +Red|Blood Frenzy|Instant|1|tmp| +Red|Bloodfire Dwarf|Creature|2|apc| +Red|Bloodstoke Howler|Creature|1|lgn| +Red|Bring Low|Instant|1|ktk| +Red|Burning Anger|Enchantment|1|m15| +Red|Cave Sense|Enchantment|1|mmq| +Red|Collapsing Borders|Enchantment|1|inv| +Red|Crackling Club|Enchantment|1|tor| +Red|Detonate|Sorcery|1|5ed| +Red|Dwarven Landslide|Sorcery|1|apc| +Red|Dwarven Soldier|Creature|1|5ed| +Red|Dwarven Warriors|Creature|1|5ed| +Red|Enslaved Dwarf|Creature|1|tor| +Red|Firebrand Ranger|Creature|1|inv| +Red|Flame Spirit|Creature|2|6ed| +Red|Flamewave Invoker|Creature|1|lgn| +Red|Flaming Sword|Enchantment|1|mmq| +Red|Generator Servant|Creature|1|m15| +Red|Goblin Dynamo|Creature|1|lgn| +Red|Goblin Elite Infantry|Creature|1|6ed| +Red|Goblin Hero|Creature|1|6ed| +Red|Goblin Raider|Creature|2|9ed| +Red|Goblin Roughrider|Creature|1|m15| +Red|Goblin War Drums|Enchantment|1|5ed| +Red|Goblin Warrens|Enchantment|1|6ed| +Red|Heart Sliver|Creature|1|tmp| +Red|Hill Giant|Creature|2|9ed| +Red|Hill Giant|Creature|1|5ed| +Red|Hooded Kavu|Creature|1|inv| +Red|Hulking Cyclops|Creature|1|6ed| +Red|Ironclaw Orcs|Creature|1|5ed| +Red|Kavu Scout|Creature|1|inv| +Red|Laccolith Grunt|Creature|1|nms| +Red|Laccolith Rig|Enchantment|1|nms| +Red|Lava Axe|Sorcery|2|9ed| +Red|Lightning Blast|Instant|1|6ed| +Red|Maniacal Rage|Enchantment|2|inv| +Red|Mountain|Land|27|*|10x5ed,1x6ed,6xinv,9x9ed,1xktk +Red|Ogre Taskmaster|Creature|1|9ed| +Red|Orcish Oriflamme|Enchantment|1|5ed| +Red|Orgg|Creature|1|5ed| +Red|Petravark|Creature|1|tor| +Red|Pyrotechnics|Sorcery|2|6ed| +Red|Sandstone Needle|Land|1|mmq| +Red|Scarred Puma|Creature|1|inv| +Red|Scorching Lava|Instant|2|inv| +Red|Shadowstorm|Sorcery|1|tmp| +Red|Shatter|Instant|1|6ed| +Red|Shatter|Instant|1|ktk| +Red|Skirk Marauder|Creature|1|lgn| +Red|Slimy Kavu|Creature|1|inv| +Red|Spitting Earth|Sorcery|1|6ed| +Red|Stone Rain|Sorcery|1|9ed| +Red|Tahngarth's Glare|Sorcery|1|apc| +Red|Thundering Giant|Creature|1|m15| +Red|Viashino Warrior|Creature|1|6ed| +Red|Volcanic Hammer|Sorcery|2|9ed| +Red|Wall of Fire|Creature|1|m15| +Red|Zap|Instant|1|apc| +White|Abzan Falconer|Creature|1|ktk| +White|Armageddon|Sorcery|1|5ed| +White|Armored Pegasus|Creature|1|6ed| +White|Avacyn, Guardian Angel|Creature|1|m15| +White|Blessed Wine|Instant|1|5ed| +White|Charm Peddler|Creature|2|mmq| +White|Circle of Protection: Artifacts|Enchantment|1|5ed| +White|Circle of Protection: Black|Enchantment|1|5ed| +White|Circle of Protection: Blue|Enchantment|1|6ed| +White|Circle of Protection: Green|Enchantment|1|6ed| +White|Circle of Protection: White|Enchantment|1|5ed| +White|Congregate|Instant|1|m15| +White|D'Avenant Archer|Creature|2|6ed| +White|Daru Mender|Creature|1|lgn| +White|Daru Sanctifier|Creature|1|lgn| +White|Daru Stinger|Creature|1|lgn| +White|Death Ward|Instant|1|5ed| +White|Devout Witness|Creature|1|mmq| +White|Disenchant|Instant|1|5ed| +White|Dismantling Blow|Instant|1|inv| +White|Eager Cadet|Creature|1|9ed| +White|Erase|Instant|1|ktk| +White|Fanatical Devotion|Enchantment|1|nms| +White|Glimmering Angel|Creature|1|inv| +White|Glory Seeker|Creature|4|9ed| +White|Holy Day|Instant|1|9ed| +White|Honor Guard|Creature|1|9ed| +White|Icatian Town|Sorcery|1|5ed| +White|Infantry Veteran|Creature|1|6ed| +White|Last Breath|Instant|1|mmq| +White|Liberate|Instant|1|inv| +White|Light of Day|Enchantment|1|6ed| +White|Manacles of Decay|Enchantment|1|apc| +White|Meditation Puzzle|Instant|1|m15| +White|Moment of Silence|Instant|1|mmq| +White|Mystic Familiar|Creature|1|tor| +White|Nightwind Glider|Creature|1|mmq| +White|Off Balance|Instant|1|nms| +White|Oppressive Rays|Enchantment|1|m15| +White|Order of the White Shield|Creature|1|5ed| +White|Orim's Touch|Instant|1|inv| +White|Pearled Unicorn|Creature|1|5ed| +White|Pikemen|Creature|1|5ed| +White|Plains|Land|23|*|8x5ed,6xinv,9x9ed +White|Prison Barricade|Creature|1|inv| +White|Sacred Nectar|Sorcery|2|9ed| +White|Samite Healer|Creature|1|5ed| +White|Samite Healer|Creature|1|6ed| +White|Serra Angel|Creature|1|9ed|foil +White|Shield of Duty and Reason|Enchantment|2|apc| +White|Siegecraft|Enchantment|1|ktk| +White|Strenght of Isolation|Enchantment|1|tor| +White|Strength of Unity|Enchantment|1|inv| +White|Thermal Glider|Creature|1|mmq| +White|Tireless Missionaries|Creature|1|m15| +White|Trap Runner|Creature|2|mmq| +White|Triplicate Spirits|Sorcery|1|m15| +White|Tundra Wolves|Creature|2|5ed| +White|Vengeance|Sorcery|2|9ed| diff -r 000000000000 -r 0a45dfe93e66 editions.cfg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/editions.cfg Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,101 @@ +LEA|Limited Edition Alpha +LEB|Limited Edition Beta +2ED|Unlimited +ARN|Arabian Nights +ATQ|Antiquities +3ED|Revised +LEG|Legends +DRK|The Dark +FEM|Fallen Empires +4ED|4th Edition +ICE|Ice Age +CHR|Chronicles +HML|Homelands +ALL|Alliances +MIR|Mirage +VIS|Visions +5ED|5th Edition +POR|Portal +WTH|Weatherlight +TMP|Tempest +STH|Stronghold +PO2|Portal The Second Age +EXO|Exodus +USG|Urza's Saga +ULG|Urza's Legacy +6ED|6th Edition +UDS|Urza's Destiny +S99|Starter 1999 +MMQ|Mercadian Masques +NMS|Nemesis +PCY|Prophecy +INV|Invasion +BTD|Beatdown +PLS|Planeshift +7ED|7th Edition +APC|Apocalypse +ODY|Odyssey +DKM|Deckmasters 2001 +TOR|Torment +JUD|Judgment +ONS|Onslaught +LGN|Legions +SCG|Scourge +8ED|8th Edition +MRD|Mirrodin +DST|Darksteel +5DN|Fifth Dawn +CHK|Champions of Kamigawa +BOK|Betrayers of Kamigawa +SOK|Saviors of Kamigawa +9ED|9th Edition +RAV|Ravnica: City of Guilds +GPT|Guildpact +DIS|Dissension +CLD|Coldsnap +TSP|Time Spiral +PLC|Planar Chaos +FST|Future Sight +10E|10th Edition +LRW|Lorwyn +MOR|Morningtide +SHM|Shadowmoor +EVE|Eventide +ALA|Shards of Alara +CON|Conflux +DDC|Duel Decks: Divine vs. Demonic +ARB|Alara Reborn +M10|Magic 2010 +ZEN|Zendikar +H09|Premium Deck Series: Slivers +WWK|Worldwake +DDE|Duel Decks: Phyrexia vs. the Coalition +ROE|Rise of the Eldrazi +M11|Magic 2011 +DDF|Duel Decks: Elspeth vs. Tezzeret +SOM|Scars of Mirrodin +MBS|Mirrodin Besieged +DDG|Duel Decks: Knights vs. Dragons +NPH|New Phyrexia +CMD|Commander +M12|Magic 2012 +DDH|Duel Decks: Ajani vs. Nicol Bolas +ISD|Innistrad +DKA|Dark Ascension +DDI|Duel Decks: Venser vs. Koth +AVR|Avacyn Restored +M13|Magic 2013 +DDJ|Duel Decks: Izzet Vs. Golgari +RTR|Return to Ravnica +GTC|Gatecrash +DDK|Duel Decks: Sorin vs. Tibalt +DGM|Dragon's Maze +MMA|Modern Masters +M14|Magic 2014 +THS|Theros +C13|Commander 2013 +BNG|Born of the Gods +JOU|Journey into Nyx +CNS|Conspiracy +M15|Magic 2015 +KTK|Khans of Tarkir diff -r 000000000000 -r 0a45dfe93e66 src/mtg.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mtg.c Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,290 @@ +#include +#include +#include +#include +#include +#include "rbtree.h" +#include "mtg.h" + +#define ED_FNAME "editions.cfg" + +static int load_editions(void); +static unsigned int parse_color(const char *colstr, const char *notes); +static int strcmp_lower(const char *a, const char *b); +static void rbdel(struct rbnode *node, void *cls); + +static struct { + enum mtg_card_type type; + const char *name; +} type_names[] = { + {MTG_TYPE_LAND, "Land"}, + {MTG_TYPE_CREATURE, "Creature"}, + {MTG_TYPE_SORCERY, "Sorcery"}, + {MTG_TYPE_INSTANT, "Instant"}, + {MTG_TYPE_ENCHANTMENT, "Enchantment"}, + {MTG_TYPE_ARTIFACT, "Artifact"}, + {MTG_TYPE_PLANESWALKER, "Planeswalker"}, + {MTG_TYPE_UNKNOWN, 0} +}; + +static struct rbtree *cards; +static struct rbtree *editions; + + +int mtg_init(void) +{ + if(cards || editions) { + fprintf(stderr, "mtg already initialized\n"); + return -1; + } + + if(!(cards = rb_create((rb_cmp_func_t)strcmp_lower))) { + goto err; + } + rb_set_delete_func(cards, rbdel, 0); + + if(!(editions = rb_create((rb_cmp_func_t)strcmp_lower))) { + goto err; + } + rb_set_delete_func(editions, rbdel, 0); + + if(load_editions() == -1) { + goto err; + } + return 0; + +err: + if(cards) rb_destroy(cards); + if(editions) rb_destroy(editions); + return -1; +} + +void mtg_destroy(void) +{ + rb_free(cards); + rb_free(editions); + cards = editions = 0; +} + +int mtg_load_cards(const char *fname) +{ + int i; + FILE *fp; + char buf[512]; + + if(!(fp = fopen(fname, "r"))) { + fprintf(stderr, "failed to open magic list: %s: %s\n", fname, strerror(errno)); + return -1; + } + + while(fgets(buf, sizeof buf, fp)) { + struct mtg_card *card; + char *field[6]; + + for(i=0; i<6; i++) { + field[i] = strtok(i ? 0 : buf, "|\n\r\t\v;"); + } + + if(!(card = malloc(sizeof *card))) { + continue; + } + if(!field[1] || !(card->name = strdup(field[1]))) { + free(card); + continue; + } + card->color = parse_color(field[0], field[5]); + card->type = mtg_str_type(field[2]); + card->edition = mtg_edition(field[4]); + card->count = atoi(field[3]); + + rb_insert(cards, card->name, card); + } + + fclose(fp); + return 0; +} + +void mtg_iter_begin(void) +{ + rb_begin(cards); +} + +const struct mtg_card *mtg_iter_next(void) +{ + struct rbnode *node = rb_next(cards); + return node ? rb_node_data(node) : 0; +} + +#define ADDCOL(x) \ + do { \ + if(*str) { \ + strcat(str, "/"); \ + } \ + strcat(str, x); \ + } while(0) + +const char *mtg_color_str(unsigned int color) +{ + static char str[128]; + str[0] = 0; + + if(color == MTG_COL_MULTI) { + return "multicolor"; + } + + if(color & MTG_COL_RED) { + ADDCOL("red"); + } + if(color & MTG_COL_GREEN) { + ADDCOL("green"); + } + if(color & MTG_COL_BLUE) { + ADDCOL("blue"); + } + if(color & MTG_COL_BLACK) { + ADDCOL("black"); + } + if(color & MTG_COL_WHITE) { + ADDCOL("white"); + } + if(color & MTG_COL_ARTIFACT) { + ADDCOL("artifact"); + } + return str[0] ? str : "colorless"; +} + +const char *mtg_type_str(enum mtg_card_type type) +{ + int i; + for(i=0; type_names[i].name; i++) { + if(type_names[i].type == type) { + return type_names[i].name; + } + } + return MTG_TYPE_UNKNOWN; +} + +enum mtg_card_type mtg_str_type(const char *s) +{ + int i; + for(i=0; type_names[i].name; i++) { + if(strcmp_lower(type_names[i].name, s) == 0) { + return type_names[i].type; + } + } + return MTG_TYPE_UNKNOWN; +} + +const char *mtg_edition(const char *edcode) +{ + struct rbnode *node = rb_find(editions, (void*)edcode); + if(!node) { + return "unknown"; + } + return rb_node_data(node); +} + +int mtg_is_multicolor(unsigned int color) +{ + int i, bits = 0; + + for(i=0; i<16; i++) { + if(color & 1) ++bits; + color >>= 1; + } + return bits > 1; +} + +static void dbgprint(struct rbnode *node, void *cls) +{ + fprintf(stderr, "%s\n", (char*)rb_node_key(node)); +} + +static int load_editions(void) +{ + FILE *fp; + char buf[128]; + + if(!(fp = fopen(ED_FNAME, "r"))) { + perror("failed to open editions config file: " ED_FNAME); + return -1; + } + + while(fgets(buf, sizeof buf, fp)) { + char *code, *name; + + code = strtok(buf, "|\n\r"); + if(!code) continue; + + name = strtok(0, "|\n\r"); + if(!name) continue; + + rb_insert(editions, strdup(code), strdup(name)); + } + + rb_foreach(editions, dbgprint, 0); + + fclose(fp); + return 0; +} + +static unsigned int parse_multicolor(const char *str) +{ + int i; + unsigned int mask = 0; + + char *cstr = alloca(strlen(str) + 1); + for(i=0; str[i]; i++) { + cstr[i] = tolower(str[i]); + } + cstr[i] = 0; + + if(strstr(cstr, "red")) mask |= MTG_COL_RED; + if(strstr(cstr, "green")) mask |= MTG_COL_GREEN; + if(strstr(cstr, "blue")) mask |= MTG_COL_BLUE; + if(strstr(cstr, "black")) mask |= MTG_COL_BLACK; + if(strstr(cstr, "white")) mask |= MTG_COL_WHITE; + if(strstr(cstr, "artifact")) mask |= MTG_COL_ARTIFACT; + + return mask; +} + +static unsigned int parse_color(const char *colstr, const char *notes) +{ + int i; + unsigned int res = 0; + char *cstr = alloca(strlen(colstr) + 1); + for(i=0; colstr[i]; i++) { + cstr[i] = tolower(colstr[i]); + } + cstr[i] = 0; + + if((res = parse_multicolor(colstr))) { + return res; + } + + if(strcmp(cstr, "*") == 0) { + if((res = parse_multicolor(notes))) { + return res; + } + return MTG_COL_MULTI; + } + + return MTG_COL_NONE; +} + +static int strcmp_lower(const char *a, const char *b) +{ + return strcasecmp(a, b); + while(*a && tolower(*a) == tolower(*b)) { + ++a; + ++b; + } + return tolower(*a) - tolower(*b); +} + +static void rbdel(struct rbnode *node, void *cls) +{ + free(rb_node_key(node)); + free(rb_node_data(node)); +} diff -r 000000000000 -r 0a45dfe93e66 src/mtg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mtg.h Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,52 @@ +#ifndef MTG_H_ +#define MTG_H_ + +#define MTG_COL_NONE 0 +#define MTG_COL_RED 1 +#define MTG_COL_GREEN 2 +#define MTG_COL_BLUE 4 +#define MTG_COL_BLACK 8 +#define MTG_COL_WHITE 16 +#define MTG_COL_ARTIFACT 32 +#define MTG_COL_MULTI 0xff + +enum mtg_card_type { + MTG_TYPE_UNKNOWN, + + MTG_TYPE_LAND, + MTG_TYPE_CREATURE, + MTG_TYPE_SORCERY, + MTG_TYPE_INSTANT, + MTG_TYPE_ENCHANTMENT, + MTG_TYPE_ARTIFACT, + MTG_TYPE_PLANESWALKER +}; + + +struct mtg_card { + char *name; + unsigned int color; + enum mtg_card_type type; + const char *edition; + int count; +}; + +int mtg_init(void); +void mtg_destroy(void); + +int mtg_load_cards(const char *fname); + +void mtg_iter_begin(void); +const struct mtg_card *mtg_iter_next(void); + +const char *mtg_color_str(unsigned int color); + +const char *mtg_type_str(enum mtg_card_type type); +enum mtg_card_type mtg_str_type(const char *s); + +const char *mtg_edition(const char *edcode); + +int mtg_is_multicolor(unsigned int color); + + +#endif /* MTG_H_ */ diff -r 000000000000 -r 0a45dfe93e66 src/mtglist.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mtglist.c Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,40 @@ +#include +#include +#include +#include "mtg.h" + +int main(int argc, char **argv) +{ + const struct mtg_card *card; + const char *fname = "cardlist"; + int ncards; + + if(argv[1]) fname = argv[1]; + + if(mtg_init() == -1) { + return 1; + } + + if(mtg_load_cards(fname) == -1) { + mtg_destroy(); + return 1; + } + + ncards = 0; + + mtg_iter_begin(); + while((card = mtg_iter_next())) { + printf("%3d ", card->count); + printf("%-11s ", mtg_color_str(card->color)); + printf("%-32s ", card->name); + printf("%-12s ", mtg_type_str(card->type)); + printf("%s\n", card->edition); + + ncards += card->count; + } + + printf("Total cards: %d\n", ncards); + + mtg_destroy(); + return 0; +} diff -r 000000000000 -r 0a45dfe93e66 src/rbtree.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rbtree.c Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,501 @@ +/* +rbtree - simple balanced binary search tree (red-black tree) library. +Copyright (C) 2011-2014 John Tsiombikas + +rbtree is free software, feel free to use, modify, and redistribute it, under +the terms of the 3-clause BSD license. See COPYING for details. + */ +#include +#include +#include +#include +#include "rbtree.h" + +#define INT2PTR(x) ((void*)(intptr_t)(x)) +#define PTR2INT(x) ((int)(intptr_t)(x)) + +struct rbtree { + struct rbnode *root; + + rb_alloc_func_t alloc; + rb_free_func_t free; + + rb_cmp_func_t cmp; + rb_del_func_t del; + void *del_cls; + + struct rbnode *rstack, *iter; +}; + +static int cmpaddr(const void *ap, const void *bp); +static int cmpint(const void *ap, const void *bp); + +static int count_nodes(struct rbnode *node); +static void del_tree(struct rbnode *node, void (*delfunc)(struct rbnode*, void*), void *cls); +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data); +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key); +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key);*/ +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls); + +struct rbtree *rb_create(rb_cmp_func_t cmp_func) +{ + struct rbtree *rb; + + if(!(rb = malloc(sizeof *rb))) { + return 0; + } + if(rb_init(rb, cmp_func) == -1) { + free(rb); + return 0; + } + return rb; +} + +void rb_free(struct rbtree *rb) +{ + rb_destroy(rb); + free(rb); +} + + +int rb_init(struct rbtree *rb, rb_cmp_func_t cmp_func) +{ + memset(rb, 0, sizeof *rb); + + if(!cmp_func) { + rb->cmp = cmpaddr; + } else if(cmp_func == RB_KEY_INT) { + rb->cmp = cmpint; + } else if(cmp_func == RB_KEY_STRING) { + rb->cmp = (rb_cmp_func_t)strcmp; + } else { + rb->cmp = cmp_func; + } + + rb->alloc = malloc; + rb->free = free; + return 0; +} + +void rb_destroy(struct rbtree *rb) +{ + del_tree(rb->root, rb->del, rb->del_cls); +} + +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free) +{ + rb->alloc = alloc; + rb->free = free; +} + + +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func) +{ + rb->cmp = func; +} + +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls) +{ + rb->del = func; + rb->del_cls = cls; +} + + +void rb_clear(struct rbtree *rb) +{ + del_tree(rb->root, rb->del, rb->del_cls); + rb->root = 0; +} + +int rb_copy(struct rbtree *dest, struct rbtree *src) +{ + struct rbnode *node; + + rb_clear(dest); + rb_begin(src); + while((node = rb_next(src))) { + if(rb_insert(dest, node->key, node->data) == -1) { + return -1; + } + } + return 0; +} + +int rb_size(struct rbtree *rb) +{ + return count_nodes(rb->root); +} + +int rb_insert(struct rbtree *rb, void *key, void *data) +{ + rb->root = insert(rb, rb->root, key, data); + rb->root->red = 0; + return 0; +} + +int rb_inserti(struct rbtree *rb, int key, void *data) +{ + rb->root = insert(rb, rb->root, INT2PTR(key), data); + rb->root->red = 0; + return 0; +} + + +int rb_delete(struct rbtree *rb, void *key) +{ + rb->root = delete(rb, rb->root, key); + rb->root->red = 0; + return 0; +} + +int rb_deletei(struct rbtree *rb, int key) +{ + rb->root = delete(rb, rb->root, INT2PTR(key)); + rb->root->red = 0; + return 0; +} + + +struct rbnode *rb_find(struct rbtree *rb, void *key) +{ + struct rbnode *node = rb->root; + + while(node) { + int cmp = rb->cmp(key, node->key); + if(cmp == 0) { + return node; + } + node = cmp < 0 ? node->left : node->right; + } + return 0; +} + +struct rbnode *rb_findi(struct rbtree *rb, int key) +{ + return rb_find(rb, INT2PTR(key)); +} + + +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls) +{ + traverse(rb->root, func, cls); +} + + +struct rbnode *rb_root(struct rbtree *rb) +{ + return rb->root; +} + +void rb_begin(struct rbtree *rb) +{ + rb->rstack = 0; + rb->iter = rb->root; +} + +#define push(sp, x) ((x)->next = (sp), (sp) = (x)) +#define pop(sp) ((sp) = (sp)->next) +#define top(sp) (sp) + +struct rbnode *rb_next(struct rbtree *rb) +{ + struct rbnode *res = 0; + + while(rb->rstack || rb->iter) { + if(rb->iter) { + push(rb->rstack, rb->iter); + rb->iter = rb->iter->left; + } else { + rb->iter = top(rb->rstack); + pop(rb->rstack); + res = rb->iter; + rb->iter = rb->iter->right; + break; + } + } + return res; +} + +void *rb_node_key(struct rbnode *node) +{ + return node ? node->key : 0; +} + +int rb_node_keyi(struct rbnode *node) +{ + return node ? PTR2INT(node->key) : 0; +} + +void *rb_node_data(struct rbnode *node) +{ + return node ? node->data : 0; +} + +static int cmpaddr(const void *ap, const void *bp) +{ + return ap < bp ? -1 : (ap > bp ? 1 : 0); +} + +static int cmpint(const void *ap, const void *bp) +{ + return PTR2INT(ap) - PTR2INT(bp); +} + + +/* ---- left-leaning 2-3 red-black implementation ---- */ + +/* helper prototypes */ +static int is_red(struct rbnode *tree); +static void color_flip(struct rbnode *tree); +static struct rbnode *rot_left(struct rbnode *a); +static struct rbnode *rot_right(struct rbnode *a); +static struct rbnode *find_min(struct rbnode *tree); +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree); +/*static struct rbnode *move_red_right(struct rbnode *tree);*/ +static struct rbnode *move_red_left(struct rbnode *tree); +static struct rbnode *fix_up(struct rbnode *tree); + +static int count_nodes(struct rbnode *node) +{ + if(!node) + return 0; + + return 1 + count_nodes(node->left) + count_nodes(node->right); +} + +static void del_tree(struct rbnode *node, rb_del_func_t delfunc, void *cls) +{ + if(!node) + return; + + del_tree(node->left, delfunc, cls); + del_tree(node->right, delfunc, cls); + + if(delfunc) { + delfunc(node, cls); + } + free(node); +} + +static struct rbnode *insert(struct rbtree *rb, struct rbnode *tree, void *key, void *data) +{ + int cmp; + + if(!tree) { + struct rbnode *node = rb->alloc(sizeof *node); + node->red = 1; + node->key = key; + node->data = data; + node->left = node->right = 0; + return node; + } + + cmp = rb->cmp(key, tree->key); + + if(cmp < 0) { + tree->left = insert(rb, tree->left, key, data); + } else if(cmp > 0) { + tree->right = insert(rb, tree->right, key, data); + } else { + tree->data = data; + } + + /* fix right-leaning reds */ + if(is_red(tree->right)) { + tree = rot_left(tree); + } + /* fix two reds in a row */ + if(is_red(tree->left) && is_red(tree->left->left)) { + tree = rot_right(tree); + } + + /* if 4-node, split it by color inversion */ + if(is_red(tree->left) && is_red(tree->right)) { + color_flip(tree); + } + + return tree; +} + +static struct rbnode *delete(struct rbtree *rb, struct rbnode *tree, void *key) +{ + int cmp; + + if(!tree) { + return 0; + } + + cmp = rb->cmp(key, tree->key); + + if(cmp < 0) { + if(!is_red(tree->left) && !is_red(tree->left->left)) { + tree = move_red_left(tree); + } + tree->left = delete(rb, tree->left, key); + } else { + /* need reds on the right */ + if(is_red(tree->left)) { + tree = rot_right(tree); + } + + /* found it at the bottom (XXX what certifies left is null?) */ + if(cmp == 0 && !tree->right) { + if(rb->del) { + rb->del(tree, rb->del_cls); + } + rb->free(tree); + return 0; + } + + if(!is_red(tree->right) && !is_red(tree->right->left)) { + tree = move_red_left(tree); + } + + if(key == tree->key) { + struct rbnode *rmin = find_min(tree->right); + tree->key = rmin->key; + tree->data = rmin->data; + tree->right = del_min(rb, tree->right); + } else { + tree->right = delete(rb, tree->right, key); + } + } + + return fix_up(tree); +} + +/*static struct rbnode *find(struct rbtree *rb, struct rbnode *node, void *key) +{ + int cmp; + + if(!node) + return 0; + + if((cmp = rb->cmp(key, node->key)) == 0) { + return node; + } + return find(rb, cmp < 0 ? node->left : node->right, key); +}*/ + +static void traverse(struct rbnode *node, void (*func)(struct rbnode*, void*), void *cls) +{ + if(!node) + return; + + traverse(node->left, func, cls); + func(node, cls); + traverse(node->right, func, cls); +} + +/* helpers */ + +static int is_red(struct rbnode *tree) +{ + return tree && tree->red; +} + +static void color_flip(struct rbnode *tree) +{ + tree->red = !tree->red; + tree->left->red = !tree->left->red; + tree->right->red = !tree->right->red; +} + +static struct rbnode *rot_left(struct rbnode *a) +{ + struct rbnode *b = a->right; + a->right = b->left; + b->left = a; + b->red = a->red; + a->red = 1; + return b; +} + +static struct rbnode *rot_right(struct rbnode *a) +{ + struct rbnode *b = a->left; + a->left = b->right; + b->right = a; + b->red = a->red; + a->red = 1; + return b; +} + +static struct rbnode *find_min(struct rbnode *tree) +{ + if(!tree) + return 0; + + while(tree->left) { + tree = tree->left; + } + return tree; +} + +static struct rbnode *del_min(struct rbtree *rb, struct rbnode *tree) +{ + if(!tree->left) { + if(rb->del) { + rb->del(tree->left, rb->del_cls); + } + rb->free(tree->left); + return 0; + } + + /* make sure we've got red (3/4-nodes) at the left side so we can delete at the bottom */ + if(!is_red(tree->left) && !is_red(tree->left->left)) { + tree = move_red_left(tree); + } + tree->left = del_min(rb, tree->left); + + /* fix right-reds, red-reds, and split 4-nodes on the way up */ + return fix_up(tree); +} + +#if 0 +/* push a red link on this node to the right */ +static struct rbnode *move_red_right(struct rbnode *tree) +{ + /* flipping it makes both children go red, so we have a red to the right */ + color_flip(tree); + + /* if after the flip we've got a red-red situation to the left, fix it */ + if(is_red(tree->left->left)) { + tree = rot_right(tree); + color_flip(tree); + } + return tree; +} +#endif + +/* push a red link on this node to the left */ +static struct rbnode *move_red_left(struct rbnode *tree) +{ + /* flipping it makes both children go red, so we have a red to the left */ + color_flip(tree); + + /* if after the flip we've got a red-red on the right-left, fix it */ + if(is_red(tree->right->left)) { + tree->right = rot_right(tree->right); + tree = rot_left(tree); + color_flip(tree); + } + return tree; +} + +static struct rbnode *fix_up(struct rbnode *tree) +{ + /* fix right-leaning */ + if(is_red(tree->right)) { + tree = rot_left(tree); + } + /* change invalid red-red pairs into a proper 4-node */ + if(is_red(tree->left) && is_red(tree->left->left)) { + tree = rot_right(tree); + } + /* split 4-nodes */ + if(is_red(tree->left) && is_red(tree->right)) { + color_flip(tree); + } + return tree; +} diff -r 000000000000 -r 0a45dfe93e66 src/rbtree.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rbtree.h Sun Nov 02 11:07:45 2014 +0200 @@ -0,0 +1,78 @@ +/* +rbtree - simple balanced binary search tree (red-black tree) library. +Copyright (C) 2011-2014 John Tsiombikas + +rbtree is free software, feel free to use, modify, and redistribute it, under +the terms of the 3-clause BSD license. See COPYING for details. + */ +#ifndef RBTREE_H_ +#define RBTREE_H_ + +struct rbtree; + + +struct rbnode { + void *key, *data; + int red; + struct rbnode *left, *right; + struct rbnode *next; /* for iterator stack */ +}; + + +typedef void *(*rb_alloc_func_t)(size_t); +typedef void (*rb_free_func_t)(void*); + +typedef int (*rb_cmp_func_t)(const void*, const void*); +typedef void (*rb_del_func_t)(struct rbnode*, void*); + +#define RB_KEY_ADDR (rb_cmp_func_t)(0) +#define RB_KEY_INT (rb_cmp_func_t)(1) +#define RB_KEY_STRING (rb_cmp_func_t)(3) + + +#ifdef __cplusplus +extern "C" { +#endif + +struct rbtree *rb_create(rb_cmp_func_t cmp_func); +void rb_free(struct rbtree *rb); + +int rb_init(struct rbtree *rb, rb_cmp_func_t cmp_func); +void rb_destroy(struct rbtree *rb); + +void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free); +void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func); +void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls); +/* TODO add user deep copy function */ + +void rb_clear(struct rbtree *rb); +int rb_copy(struct rbtree *dest, struct rbtree *src); + +int rb_size(struct rbtree *rb); + +int rb_insert(struct rbtree *rb, void *key, void *data); +int rb_inserti(struct rbtree *rb, int key, void *data); + +int rb_delete(struct rbtree *rb, void *key); +int rb_deletei(struct rbtree *rb, int key); + +struct rbnode *rb_find(struct rbtree *rb, void *key); +struct rbnode *rb_findi(struct rbtree *rb, int key); + +void rb_foreach(struct rbtree *rb, void (*func)(struct rbnode*, void*), void *cls); + +struct rbnode *rb_root(struct rbtree *rb); + +void rb_begin(struct rbtree *rb); +struct rbnode *rb_next(struct rbtree *rb); + +void *rb_node_key(struct rbnode *node); +int rb_node_keyi(struct rbnode *node); +void *rb_node_data(struct rbnode *node); + +#ifdef __cplusplus +} +#endif + + +#endif /* RBTREE_H_ */