DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (777e60ca8853)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef builtin_MapObject_h
#define builtin_MapObject_h

#include "jsobj.h"

#include "vm/Runtime.h"

namespace js {

/*
 * Comparing two ropes for equality can fail. The js::HashTable template
 * requires infallible hash() and match() operations. Therefore we require
 * all values to be converted to hashable form before being used as a key
 * in a Map or Set object.
 *
 * All values except ropes are hashable as-is.
 */
class HashableValue {
    EncapsulatedValue value;

  public:
    struct Hasher {
        typedef HashableValue Lookup;
        static HashNumber hash(const Lookup& v) { return v.hash(); }
        static bool match(const HashableValue& k, const Lookup& l) { return k == l; }
        static bool isEmpty(const HashableValue& v) { return v.value.isMagic(JS_HASH_KEY_EMPTY); }
        static void makeEmpty(HashableValue* vp) { vp->value = MagicValue(JS_HASH_KEY_EMPTY); }
    };

    HashableValue() : value(UndefinedValue()) {}

    bool setValue(JSContext* cx, HandleValue v);
    HashNumber hash() const;
    bool operator==(const HashableValue& other) const;
    HashableValue mark(JSTracer* trc) const;
    Value get() const { return value.get(); }
};

class AutoHashableValueRooter : private AutoGCRooter
{
  public:
    explicit AutoHashableValueRooter(JSContext* cx
                                     MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
        : AutoGCRooter(cx, HASHABLEVALUE)
        {
            MOZ_GUARD_OBJECT_NOTIFIER_INIT;
        }

    bool setValue(JSContext* cx, HandleValue v) {
        return value.setValue(cx, v);
    }

    operator const HashableValue & () {
        return value;
    }

    friend void AutoGCRooter::trace(JSTracer* trc);
    void trace(JSTracer* trc);

  private:
    HashableValue value;
    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};

template <class Key, class Value, class OrderedHashPolicy, class AllocPolicy>
class OrderedHashMap;

template <class T, class OrderedHashPolicy, class AllocPolicy>
class OrderedHashSet;

typedef OrderedHashMap<HashableValue,
                       RelocatableValue,
                       HashableValue::Hasher,
                       RuntimeAllocPolicy> ValueMap;

typedef OrderedHashSet<HashableValue,
                       HashableValue::Hasher,
                       RuntimeAllocPolicy> ValueSet;

class MapObject : public JSObject {
  public:
    enum IteratorKind { Keys, Values, Entries };

    static JSObject* initClass(JSContext* cx, JSObject* obj);
    static const Class class_;
  private:
    static const JSPropertySpec properties[];
    static const JSFunctionSpec methods[];
    ValueMap* getData() { return static_cast<ValueMap*>(getPrivate()); }
    static ValueMap & extract(CallReceiver call);
    static void mark(JSTracer* trc, JSObject* obj);
    static void finalize(FreeOp* fop, JSObject* obj);
    static bool construct(JSContext* cx, unsigned argc, Value* vp);

    static bool is(HandleValue v);

    static bool iterator_impl(JSContext* cx, CallArgs args, IteratorKind kind);

    static bool size_impl(JSContext* cx, CallArgs args);
    static bool size(JSContext* cx, unsigned argc, Value* vp);
    static bool get_impl(JSContext* cx, CallArgs args);
    static bool get(JSContext* cx, unsigned argc, Value* vp);
    static bool has_impl(JSContext* cx, CallArgs args);
    static bool has(JSContext* cx, unsigned argc, Value* vp);
    static bool set_impl(JSContext* cx, CallArgs args);
    static bool set(JSContext* cx, unsigned argc, Value* vp);
    static bool delete_impl(JSContext* cx, CallArgs args);
    static bool delete_(JSContext* cx, unsigned argc, Value* vp);
    static bool keys_impl(JSContext* cx, CallArgs args);
    static bool keys(JSContext* cx, unsigned argc, Value* vp);
    static bool values_impl(JSContext* cx, CallArgs args);
    static bool values(JSContext* cx, unsigned argc, Value* vp);
    static bool entries_impl(JSContext* cx, CallArgs args);
    static bool entries(JSContext* cx, unsigned argc, Value* vp);
    static bool clear_impl(JSContext* cx, CallArgs args);
    static bool clear(JSContext* cx, unsigned argc, Value* vp);
};

class SetObject : public JSObject {
  public:
    enum IteratorKind { Values, Entries };
    static JSObject* initClass(JSContext* cx, JSObject* obj);
    static const Class class_;
  private:
    static const JSPropertySpec properties[];
    static const JSFunctionSpec methods[];
    ValueSet* getData() { return static_cast<ValueSet*>(getPrivate()); }
    static ValueSet & extract(CallReceiver call);
    static void mark(JSTracer* trc, JSObject* obj);
    static void finalize(FreeOp* fop, JSObject* obj);
    static bool construct(JSContext* cx, unsigned argc, Value* vp);

    static bool is(HandleValue v);

    static bool iterator_impl(JSContext* cx, CallArgs args, IteratorKind kind);

    static bool size_impl(JSContext* cx, CallArgs args);
    static bool size(JSContext* cx, unsigned argc, Value* vp);
    static bool has_impl(JSContext* cx, CallArgs args);
    static bool has(JSContext* cx, unsigned argc, Value* vp);
    static bool add_impl(JSContext* cx, CallArgs args);
    static bool add(JSContext* cx, unsigned argc, Value* vp);
    static bool delete_impl(JSContext* cx, CallArgs args);
    static bool delete_(JSContext* cx, unsigned argc, Value* vp);
    static bool values_impl(JSContext* cx, CallArgs args);
    static bool values(JSContext* cx, unsigned argc, Value* vp);
    static bool entries_impl(JSContext* cx, CallArgs args);
    static bool entries(JSContext* cx, unsigned argc, Value* vp);
    static bool clear_impl(JSContext* cx, CallArgs args);
    static bool clear(JSContext* cx, unsigned argc, Value* vp);
};

} /* namespace js */

extern JSObject*
js_InitMapClass(JSContext* cx, js::HandleObject obj);

extern JSObject*
js_InitSetClass(JSContext* cx, js::HandleObject obj);

#endif /* builtin_MapObject_h */