1 /* 2 * This file is part of gir-to-d. 3 * 4 * gir-to-d 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. 8 * 9 * gir-to-d is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public License 15 * along with gir-to-d. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 module gtd.GirType; 19 20 import std.algorithm: among, canFind, startsWith; 21 import std.array: replace; 22 import std.conv: to; 23 import std.range: empty; 24 25 import gtd.GirWrapper; 26 import gtd.XMLReader; 27 28 /** 29 * Represent sthe type of an field or a parameter. 30 */ 31 final class GirType 32 { 33 string name; 34 string cType; 35 string dType; 36 string doc; 37 bool constType; 38 39 int size = -1; /// The size of a fixed size array. 40 int length = -1; /// The index of the param representing the length, not counting the instance param. 41 bool zeroTerminated; /// Is this array zero-terminated. 42 bool girArray = false; /// The gir file specifies this as an array. Use isArray to check if this is actually an array. 43 GirType elementType; /// The type of the array elements, also set for Glib.List, Glib.SList Glib.Array and GLib.HashTable. 44 GirType keyType; /// The key type of a HashTable; 45 46 GirWrapper wrapper; 47 48 this(GirWrapper wrapper) 49 { 50 this.wrapper = wrapper; 51 } 52 53 void parse(T)(XMLReader!T reader) 54 { 55 if ( reader.front.value == "array" ) 56 girArray = true; 57 58 if ( "c:type" in reader.front.attributes ) 59 cType = reader.front.attributes["c:type"]; 60 if ( "length" in reader.front.attributes ) 61 length = to!int(reader.front.attributes["length"]); 62 if ( "zero-terminated" in reader.front.attributes ) 63 zeroTerminated = to!int(reader.front.attributes["zero-terminated"]) == 1; 64 if ( "fixed-size" in reader.front.attributes ) 65 size = to!int(reader.front.attributes["fixed-size"]); 66 if ( "name" in reader.front.attributes ) 67 name = reader.front.attributes["name"]; 68 69 if ( cType is null && name is null ) 70 { 71 name = "none"; 72 } 73 74 // Some GIR files have a none type name. 75 if (name == "none") { 76 cType = "void"; 77 } 78 79 if ( cType.canFind(" const") || cType.canFind("const ") ) 80 { 81 constType = true; 82 fixType(); 83 } 84 85 if ( cType.canFind("unsigned ") ) 86 { 87 cType = cType.replace("unsigned ", "u"); 88 } 89 90 if ( name == "long double" ) 91 { 92 name = "greal"; 93 cType = "greal"; 94 } 95 96 cType = cType.replace("volatile ", ""); 97 98 if ( cType == "unsigned" ) 99 cType = name; 100 101 removeInitialyUnowned(); 102 103 if ( cType is null && (name == "filename" || name == "utf8") ) 104 cType = "gchar*"; 105 106 if ( reader.front.type == XMLNodeType.EmptyTag ) 107 return; 108 109 reader.popFront(); 110 111 while ( !reader.empty && !reader.endTag("type", "array") ) 112 { 113 if ( elementType ) 114 keyType = elementType; 115 116 elementType = new GirType(wrapper); 117 elementType.parse(reader); 118 119 reader.popFront(); 120 } 121 122 if ( cType == elementType.cType && !cType.among("void*", "gpointer", "gconstpointer") && size < 0 ) 123 cType ~= "*"; 124 125 if ( isArray() && (cType == "void" || cType.empty) ) 126 { 127 if ( size > 0 ) 128 cType = elementType.cType; 129 else 130 cType = elementType.cType ~"*"; 131 } 132 } 133 134 bool isString() 135 { 136 if ( cType.startsWith("gchar*", "char*", "const(char)*") ) 137 return true; 138 if ( name.among("utf8", "filename") ) 139 return true; 140 if ( isArray() && elementType.cType.startsWith("gchar", "char", "const(char)") ) 141 return true; 142 143 return false; 144 } 145 146 bool isArray() 147 { 148 if ( elementType is null ) 149 return false; 150 151 // The GLib Arrays are in the GIR files as arrays but they shouldn't be wrapped as such. 152 if ( name.among("GLib.Array", "Array", "GLib.ByteArray", "ByteArray", "GLib.PtrArray", "PtrArray") ) 153 return false; 154 155 if ( girArray ) 156 return true; 157 158 return false; 159 } 160 161 private void fixType() 162 { 163 if ( name == "utf8" && !cType.canFind("**") ) 164 { 165 cType = "const(char)*"; 166 return; 167 } 168 169 cType = cType.replace("const ", "").replace(" const", ""); 170 } 171 172 private void removeInitialyUnowned() 173 { 174 if ( name.among("GObject.InitiallyUnowned", "InitiallyUnowned") ) 175 { 176 if ( name == "GObject.InitiallyUnowned" ) 177 name = "GObject.Object"; 178 else if ( name == "InitiallyUnowned" ) 179 name = "Object"; 180 181 if ( cType == "GInitiallyUnowned" ) 182 cType = "GObject"; 183 else if ( cType == "GInitiallyUnowned*" ) 184 cType = "GObject*"; 185 } 186 else if ( name.among("GObject.InitiallyUnownedClass", "InitiallyUnownedClass") ) 187 { 188 if ( name == "GObject.InitiallyUnownedClass" ) 189 name = "GObject.ObjectClass"; 190 else if ( name == "InitiallyUnownedClass" ) 191 name = "ObjectClass"; 192 193 if ( cType == "GInitiallyUnownedClass" ) 194 cType = "GObjectClass"; 195 else if ( cType == "GInitiallyUnownedClass*" ) 196 cType = "GObjectClass*"; 197 } 198 } 199 }