1 /* 2 * This file is part of gtkD. 3 * 4 * gtkD is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU Lesser General Public License 6 * as published by the Free Software Foundation; either version 3 7 * of the License, or (at your option) any later version, with 8 * some exceptions, please read the COPYING file. 9 * 10 * gtkD is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public License 16 * along with gtkD; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA 18 */ 19 20 module utils.GtkType; 21 22 import utils.GtkWrapper; 23 import utils.XML; 24 25 import std.algorithm: among, canFind; 26 import std.array: replace; 27 import std.conv: to; 28 29 /** 30 * Represent sthe type of an field or a parameter. 31 */ 32 final class GtkType 33 { 34 string name; 35 string cType; 36 string dType; 37 string doc; 38 bool constType; 39 40 int size = -1; /// The size of a fixed size array. 41 int length = -1; /// The index of the param representing the length, not counting the instance param. 42 bool zeroTerminated; /// Is this array zero-terminated. 43 GtkType elementType; /// The type of the array elements, also set for Glib.List, Glib.SList Glib.Array and GLib.HashTable. 44 GtkType keyType; /// The key type of a HashTable; 45 46 GtkWrapper wrapper; 47 48 this(GtkWrapper wrapper) 49 { 50 this.wrapper = wrapper; 51 } 52 53 void parse(T)(XMLReader!T reader) 54 { 55 if ( "c:type" in reader.front.attributes ) 56 cType = reader.front.attributes["c:type"]; 57 if ( "length" in reader.front.attributes ) 58 length = to!int(reader.front.attributes["length"]); 59 if ( "zero-terminated" in reader.front.attributes ) 60 zeroTerminated = to!int(reader.front.attributes["zero-terminated"]) == 1; 61 if ( "fixed-size" in reader.front.attributes ) 62 size = to!int(reader.front.attributes["fixed-size"]); 63 if ( "name" in reader.front.attributes ) 64 name = reader.front.attributes["name"]; 65 66 if ( cType is null && name is null ) 67 { 68 name = "none"; 69 cType = "void"; 70 } 71 72 if ( cType.canFind("const ") ) 73 { 74 constType = true; 75 fixType(); 76 } 77 78 if ( cType.canFind("unsigned ") ) 79 { 80 cType = cType.replace("unsigned ", "u"); 81 } 82 83 cType = cType.replace("volatile ", ""); 84 85 if ( cType == "unsigned" ) 86 cType = name; 87 88 removeInitialyUnowned(); 89 90 if ( cType is null && (name == "filename" || name == "utf8") ) 91 cType = "gchar*"; 92 93 if ( reader.front.type == XMLNodeType.EmptyTag ) 94 return; 95 96 reader.popFront(); 97 98 while ( !reader.empty && !reader.endTag("type", "array") ) 99 { 100 if ( elementType ) 101 keyType = elementType; 102 103 elementType = new GtkType(wrapper); 104 elementType.parse(reader); 105 106 reader.popFront(); 107 } 108 109 if ( cType == elementType.cType && !cType.among("void*", "gpointer", "gconstpointer") ) 110 cType ~= "*"; 111 112 if ( isArray() && cType == "void" ) 113 cType = elementType.cType ~"*"; 114 } 115 116 bool isArray() 117 { 118 if ( elementType is null ) 119 return false; 120 121 if ( name.among("GLib.List", "GLib.SList", "GLib.Array", "GLib.ByteArray", "GLib.HashTable", "GLib.PtrArray") ) 122 return false; 123 124 if ( name.among("List", "SList", "Array", "ByteArray", "HashTable", "PtrArray") ) 125 return false; 126 127 if ( elementType ) 128 return true; 129 130 return false; 131 } 132 133 private void fixType() 134 { 135 if ( name == "utf8" && !cType.canFind("**") ) 136 { 137 cType = "const(char)*"; 138 return; 139 } 140 141 cType = cType.replace("const ", "").replace(" const", ""); 142 } 143 144 private void removeInitialyUnowned() 145 { 146 if ( name.among("GObject.InitiallyUnowned", "InitiallyUnowned") ) 147 { 148 if ( name == "GObject.InitiallyUnowned" ) 149 name = "GObject.Object"; 150 else if ( name == "InitiallyUnowned" ) 151 name = "Object"; 152 153 if ( cType == "GInitiallyUnowned" ) 154 cType = "GObject"; 155 else if ( cType == "GInitiallyUnowned*" ) 156 cType = "GObject*"; 157 } 158 else if ( name.among("GObject.InitiallyUnownedClass", "InitiallyUnownedClass") ) 159 { 160 if ( name == "GObject.InitiallyUnownedClass" ) 161 name = "GObject.ObjectClass"; 162 else if ( name == "InitiallyUnownedClass" ) 163 name = "ObjectClass"; 164 165 if ( cType == "GInitiallyUnownedClass" ) 166 cType = "GObjectClass"; 167 else if ( cType == "GInitiallyUnownedClass*" ) 168 cType = "GObjectClass*"; 169 } 170 } 171 }