root/core/Multiname.cpp

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. getNamespace
  2. contains
  3. matches
  4. format
  5. format
  6. setMultiname

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is [Open Source Virtual Machine.].
 *
 * The Initial Developer of the Original Code is
 * Adobe System Incorporated.
 * Portions created by the Initial Developer are Copyright (C) 2004-2006
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Adobe AS3 Team
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * ***** END LICENSE BLOCK ***** */


#include "avmplus.h"

namespace avmplus
{
        Namespacep Multiname::getNamespace(int32_t i) const
        {
                AvmAssert(!isRtns() && !isAnyNamespace());
                if (flags&NSSET)
                {
                        AvmAssert(i >= 0 && i < namespaceCount());
                        return nsset ? nsset->nsAt(i) : NULL;
                }
                else
                {
                        AvmAssert(i == 0);
                        return ns;
                }
        }

        bool Multiname::contains(Namespacep ns) const
        {
                if (flags & NSSET)
                {
            return nsset && nsset->contains(ns);
                }
                else
                {
                        return this->ns == ns;
                }
        }

        bool Multiname::matches(const Multiname* qname) const
        {
                // For attributes (XML::getprop page 12)
                //if (((n.[[Name]].localName == "*") || (n.[[Name]].localName == a.[[Name]].localName)) &&
                //      ((n.[[Name]].uri == nulll) || (n.[[Name]].uri == a.[[Name]].uri)))

                // For regular element props (XML::getprop page 12)
                //      if (n.localName = "*" OR m2 and (m2.localName == n.localName)
                //      and (!n.uri) or (m2) and (n.uri == m2.uri)))

                //Stringp n1 = core->string(this->name);

                if (qname)
                {
                        //Stringp n2 = core->string(m2->name);

                        if (this->isAttr() != qname->isAttr())
                                return false;
                }

                // An anyName that is not qualified matches all properties
                if (this->isAnyName() && !this->isQName())
                        return true;

                // Not an anyName, if m2 is valid, verify names are identical
                if (!this->isAnyName() && qname && (this->name != qname->getName()))
                        return false;

                if (!qname)
                        return false;

                if (this->isAnyNamespace())
                        return true;

                // find a matching namespace between m2 and this
                // if no match return false
                Stringp u2 = qname->getNamespace()->getURI();
        uint8 type2 = (uint8)(qname->getNamespace()->getType());
                //Stringp s2 = core->string(u2);
                
                for (int i = 0; i < this->namespaceCount(); i++)
                {
                        // We'd like to just compare namespace objects but we need
                        // to check URIs since two namespaces with different prefixes
                        // are considered a match
                        Stringp u1 = getNamespace(i)->getURI();
            uint8 type1 = (uint8)(getNamespace(i)->getType());
                        //Stringp s1 = core->string(u1);
                        if (u1 == u2 && type1 == type2)
                                return true;
                }

                return false;
        }

        /* static */ 
        Stringp Multiname::format(AvmCore *core, Namespacep ns, Stringp name, bool attr, bool hideNonPublicNamespaces)
        {
                if (ns->isPublic() ||
                        (hideNonPublicNamespaces && // backwards compatibility
                        ns->getType() != Namespace::NS_Public))
                {
                        return name;
                }
                else
                {
                        Stringp uri = ns->getURI();
                        if (attr)
                        {
                                return core->concatStrings(core->newConstantStringLatin1("@"), core->concatStrings(uri,
                                        core->concatStrings(core->newConstantStringLatin1("::"), name)));
                        }
                        else
                        {
                                return core->concatStrings(uri,
                                        core->concatStrings(core->newConstantStringLatin1("::"), name));
                        }
                }
        }

//#ifdef AVMPLUS_VERBOSE
        // Made available in non-AVMPLUS_VERBOSE builds for describeType
        Stringp Multiname::format(AvmCore* core , MultiFormat form) const
        {
                Stringp attr = this->isAttr() ? core->newConstantStringLatin1("@") : (Stringp)core->kEmptyString;
                Stringp name = this->isAnyName() 
                        ? core->newConstantStringLatin1("*") 
                        : (this->isRtname()
                                ? core->newConstantStringLatin1("[]")
                                : getName());

                if (isAnyNamespace())
                {
                        return core->concatStrings(attr, core->concatStrings(core->newConstantStringLatin1("*::"), name));
                }
                else if (isRtns())
                {
                        return core->concatStrings(attr, core->concatStrings(core->newConstantStringLatin1("[]::"), name));
                }
                else if (namespaceCount() == 1 && isQName()) 
                {
                        return format(core, getNamespace(), core->concatStrings(attr,name), false, false);
                }
                else
                {
                        // various switches
                        bool showNs = (form == MULTI_FORMAT_FULL) || (form == MULTI_FORMAT_NS_ONLY);
                        bool showName = (form == MULTI_FORMAT_FULL) || (form == MULTI_FORMAT_NAME_ONLY);
                        bool showBrackets = (form == MULTI_FORMAT_FULL);
                        Stringp s = attr;
                        if (showNs)
                        {
                                if (showBrackets)
                                        s = core->concatStrings(s, core->newConstantStringLatin1("{"));

                                for (int i=0,n=namespaceCount(); i < n; i++) 
                                {                       
                                        if (getNamespace(i)->isPublic())
                                                s = core->concatStrings(s, core->newConstantStringLatin1("public"));
                                        else
                                                s = core->concatStrings(s, getNamespace(i)->getURI());
                                        if (i+1 < n)
                                                s = core->concatStrings(s, core->newConstantStringLatin1(","));
                                }

                                if (showBrackets)
                                        s = core->concatStrings(s, core->newConstantStringLatin1("}::"));
                        }

                        if (showName)
                                s = core->concatStrings(s, name);
                        return s;
                }
        }
//#endif

        // NOTE NOTE NOTE
        // Write barrier note: the container for a HeapMultiname is *not* 'this'; 
        // HeapMultiname figures as a field in eg QNameObject and XMLListObject.
        // You *must* call FindBeginningFast(this) to get the right container.
        
        void HeapMultiname::setMultiname(const Multiname& that)
        {
                MMgc::GC* gc = this->gc();
                const void *container = gc->FindBeginningFast(this);
                WBRC(gc, container, &name.name, that.name);
                
                bool const this_nsset = name.isNsset() != 0;
                bool const that_nsset = that.isNsset() != 0;

                if (this_nsset != that_nsset)
                {
                        // gc->rc or vice versa... we have to explicitly null out
                        // any existing value (before setting a new one) because WB/WBRC
                        // assume any existing value is a GCObject/RCObject respectively.
                        if (this_nsset)
                                WB_NULL(&name.ns);
                        else
                                WBRC_NULL(&name.ns);
                }

                if (that_nsset) 
                {
                        WB(gc, container, &name.nsset, that.nsset);
                } 
                else 
                {
                        WBRC(gc, container, &name.ns, that.ns);
                }

                name.flags = that.flags;
                name.next_index = that.next_index;
        }

        HeapMultiname::~HeapMultiname()
        {
                // Our embedded Multiname will zero itself, but we should call WBRC to 
                // adjust the refcounts correctly...
                WBRC_NULL(&name.name);
                if (!name.isNsset())
                        WBRC_NULL(&name.ns);
        }
        
}

/* [<][>][^][v][top][bottom][index][help] */