/* Metallurgy - Higher Level Interface to Chordata * Copyright (C) 2001-2002 Jay Freeman (saurik) */ /* * Redistribution and use in source and binary * forms, with or without modification, are permitted * provided that the following conditions are met: * * 1. Redistributions of source code must retain the * above copyright notice, this list of conditions * and the following disclaimer. * 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions * and the following disclaimer in the documentation * and/or other materials provided with the * distribution. * 3. The name of the author may not be used to endorse * or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "stdafx.h" #include "metallurgy/Element.h" #include "metallurgy/Signature.h" #include "metallurgy/Type.h" #include "chordata/Signature.h" #include "chordata/Utils.h" using namespace Chordata::Utils; namespace Metallurgy { Element::Element(const Module *module, const Chordata::Element::Type corType) : module(module), array(NULL), extra(NULL), nested(NULL), type(NULL), intrinsic(corType) {} Element::Element(const IHasElement *type) : module(dynamic_cast(type)->getModule()), array(NULL), extra(NULL), nested(NULL), type(type), intrinsic(Chordata::Element::Class) { } Element::Element(const Module *module, const Chordata::Signature * &blob) : module(module), array(NULL), extra(NULL), nested(NULL), type(NULL) { intrinsic = Uncompress(blob); while (intrinsic & Chordata::Element::Modifier) { mods.push_back(intrinsic); intrinsic = Uncompress(blob); } if (IsPrimitive(intrinsic)) return; switch (intrinsic) { case Chordata::Element::Ptr: case Chordata::Element::ByRef: extra = new Element(module, blob); break; case Chordata::Element::TypedByRef: case Chordata::Element::Object: case Chordata::Element::I: case Chordata::Element::U: return; break; case Chordata::Element::ValueType: case Chordata::Element::Class: type = dynamic_cast(module->ResolveToken(DecodeToken(Uncompress(blob)))); break; case Chordata::Element::CMod_Reqd: case Chordata::Element::CMod_Opt: type = dynamic_cast(module->ResolveToken(DecodeToken(Uncompress(blob)))); extra = new Element(module, blob); break; case Chordata::Element::FnPtr: nested = new Signature(module, blob); break; case Chordata::Element::SZArray: extra = new Element(module, blob); array = new DimensionVector(); break; case Chordata::Element::Array: { extra = new Element(module, blob); array = new DimensionVector(Uncompress(blob)); uint32_t dims = Uncompress(blob); for (uint32_t i(0); i < dims; i++) array->operator [](i).size = Uncompress(blob); dims = Uncompress(blob); for (i = 0; i < dims; i++) array->operator [](i).bound = Uncompress(blob); } break; default: throw std::wstring(L"unsupported element type"); break; } } Element::~Element() { delete nested; delete extra; delete array; } void Element::Render(std::wstring &builder) const { switch (intrinsic) { case Chordata::Element::Void: builder.insert(0, L"void"); break; case Chordata::Element::Boolean: builder.insert(0, L"bool"); break; case Chordata::Element::Char: builder.insert(0, L"char"); break; case Chordata::Element::I1: builder.insert(0, L"sbyte"); break; case Chordata::Element::U1: builder.insert(0, L"byte"); break; case Chordata::Element::I2: builder.insert(0, L"short"); break; case Chordata::Element::U2: builder.insert(0, L"ushort"); break; case Chordata::Element::I4: builder.insert(0, L"int"); break; case Chordata::Element::U4: builder.insert(0, L"uint"); break; case Chordata::Element::I8: builder.insert(0, L"long"); break; case Chordata::Element::U8: builder.insert(0, L"ulong"); break; case Chordata::Element::R4: builder.insert(0, L"float"); break; case Chordata::Element::R8: builder.insert(0, L"double"); break; case Chordata::Element::String: builder.insert(0, L"string"); break; case Chordata::Element::Object: builder.insert(0, L"object"); break; case Chordata::Element::I: builder.insert(0, L"IntPtr"); break; case Chordata::Element::U: builder.insert(0, L"UIntPtr"); break; case Chordata::Element::ByRef: extra->Render(builder); builder.insert(0, L"ref "); break; case Chordata::Element::Ptr: extra->Render(builder); builder.append(L" *"); break; case Chordata::Element::Class: case Chordata::Element::ValueType: { const Metallurgy::Type *defref = dynamic_cast(type); if (defref == NULL) type->getElement()->Render(builder); else { std::wstring name = defref->getName().getFull(); if (name == L"System.String") builder.insert(0, L"string"); else builder.insert(0, name.c_str()); } } break; case Chordata::Element::SZArray: builder.insert(0, L"[]"); extra->Render(builder); break; case Chordata::Element::Array: { wchar_t buff[16]; extra->Render(builder); builder.append(L"["); for (uint32_t i(0); i < array->size(); i++) { if (i != 0) builder.append(L","); uint32_t size = (*array)[i].size; if (size != 0) builder.append(_itow(size, buff, 10)); } builder.append(L"]"); } break; /*default: std::cerr << std::endl << "Unable to build type :(. [" << std::setbase(16) << element->Intrinsic << std::setbase(10) << "]" << std::endl; exit(1); break;*/ } } const Module *Element::getModule() const { return module; } const IHasElement *Element::getType() const { return type; } const Element *Element::getExtra() const { return extra; } const Signature *Element::getNested() const { return nested; } Chordata::Element::Type Element::getIntrinsic() const { return intrinsic; } const Element::DimensionVector *Element::getArray() const { return array; } std::wstring Element::getXmlMemberKey() const { switch (intrinsic) { case Chordata::Element::Void: return L"System.Void"; break; case Chordata::Element::Boolean: return L"System.Boolean"; break; case Chordata::Element::Char: return L"System.Char"; break; case Chordata::Element::I1: return L"System.SByte"; break; case Chordata::Element::U1: return L"System.Byte"; break; case Chordata::Element::I2: return L"System.Int16"; break; case Chordata::Element::U2: return L"System.UInt16"; break; case Chordata::Element::I4: return L"System.Int32"; break; case Chordata::Element::U4: return L"System.UInt32"; break; case Chordata::Element::I8: return L"System.Int64"; break; case Chordata::Element::U8: return L"System.UInt64"; break; case Chordata::Element::R4: return L"System.Single"; break; case Chordata::Element::R8: return L"System.Double"; break; case Chordata::Element::String: return L"System.String"; break; case Chordata::Element::Object: return L"System.Object"; break; case Chordata::Element::I: return L"System.IntPtr"; break; case Chordata::Element::U: return L"System.UIntPtr"; break; case Chordata::Element::ByRef: return extra->getXmlMemberKey() + L"@"; break; case Chordata::Element::Ptr: return extra->getXmlMemberKey() + L"*"; break; case Chordata::Element::Class: case Chordata::Element::ValueType: { const Metallurgy::Type *defref = dynamic_cast(type); return (defref == NULL) ? type->getElement()->getXmlMemberKey() : defref->getName().getFull(); } break; case Chordata::Element::SZArray: return extra->getXmlMemberKey() + L"[]"; break; case Chordata::Element::Array: { std::wstring key = extra->getXmlMemberKey() + L"["; wchar_t buff[16]; for (uint32_t i(0); i < array->size(); i++) { if (i != 0) key += L","; key += L"0:"; uint32_t size = (*array)[i].size; if (size != 0) key += _itow(size, buff, 10); } return key + L"]"; } break; default: ::MessageBox(NULL, L"Unable to render XmlMemberKey.", L"Error", MB_OK | MB_ICONERROR); return L"{Error}"; break; } } bool Element::isVoid() const { switch (intrinsic) { case Chordata::Element::CMod_Opt: return extra->isVoid(); default: return mods.size() == 0 && intrinsic == Chordata::Element::Void; } } }