michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * JavaScript Debugging support - Atom support michael@0: */ michael@0: michael@0: #include "jsd.h" michael@0: michael@0: /* #define TEST_ATOMS 1 */ michael@0: michael@0: #ifdef TEST_ATOMS michael@0: static void michael@0: _testAtoms(JSDContext*jsdc) michael@0: { michael@0: JSDAtom* atom0 = jsd_AddAtom(jsdc, "foo"); michael@0: JSDAtom* atom1 = jsd_AddAtom(jsdc, "foo"); michael@0: JSDAtom* atom2 = jsd_AddAtom(jsdc, "bar"); michael@0: JSDAtom* atom3 = jsd_CloneAtom(jsdc, atom1); michael@0: JSDAtom* atom4 = jsd_CloneAtom(jsdc, atom2); michael@0: michael@0: const char* c0 = JSD_ATOM_TO_STRING(atom0); michael@0: const char* c1 = JSD_ATOM_TO_STRING(atom1); michael@0: const char* c2 = JSD_ATOM_TO_STRING(atom2); michael@0: const char* c3 = JSD_ATOM_TO_STRING(atom3); michael@0: const char* c4 = JSD_ATOM_TO_STRING(atom4); michael@0: michael@0: jsd_DropAtom(jsdc, atom0); michael@0: jsd_DropAtom(jsdc, atom1); michael@0: jsd_DropAtom(jsdc, atom2); michael@0: jsd_DropAtom(jsdc, atom3); michael@0: jsd_DropAtom(jsdc, atom4); michael@0: } michael@0: #endif michael@0: michael@0: static int michael@0: _atom_smasher(JSHashEntry *he, int i, void *arg) michael@0: { michael@0: MOZ_ASSERT(he); michael@0: MOZ_ASSERT(he->value); michael@0: MOZ_ASSERT(((JSDAtom*)(he->value))->str); michael@0: michael@0: free(((JSDAtom*)(he->value))->str); michael@0: free(he->value); michael@0: he->value = nullptr; michael@0: he->key = nullptr; michael@0: return HT_ENUMERATE_NEXT; michael@0: } michael@0: michael@0: static int michael@0: _compareAtomKeys(const void *v1, const void *v2) michael@0: { michael@0: return 0 == strcmp((const char*)v1, (const char*)v2); michael@0: } michael@0: michael@0: static int michael@0: _compareAtoms(const void *v1, const void *v2) michael@0: { michael@0: return 0 == strcmp(((JSDAtom*)v1)->str, ((JSDAtom*)v2)->str); michael@0: } michael@0: michael@0: michael@0: bool michael@0: jsd_CreateAtomTable(JSDContext* jsdc) michael@0: { michael@0: jsdc->atoms = JS_NewHashTable(256, JS_HashString, michael@0: _compareAtomKeys, _compareAtoms, michael@0: nullptr, nullptr); michael@0: #ifdef TEST_ATOMS michael@0: _testAtoms(jsdc); michael@0: #endif michael@0: return !!jsdc->atoms; michael@0: } michael@0: michael@0: void michael@0: jsd_DestroyAtomTable(JSDContext* jsdc) michael@0: { michael@0: if( jsdc->atoms ) michael@0: { michael@0: JS_HashTableEnumerateEntries(jsdc->atoms, _atom_smasher, nullptr); michael@0: JS_HashTableDestroy(jsdc->atoms); michael@0: jsdc->atoms = nullptr; michael@0: } michael@0: } michael@0: michael@0: JSDAtom* michael@0: jsd_AddAtom(JSDContext* jsdc, const char* str) michael@0: { michael@0: JSDAtom* atom; michael@0: michael@0: if(!str) michael@0: { michael@0: MOZ_ASSERT(0); michael@0: return nullptr; michael@0: } michael@0: michael@0: JSD_LOCK_ATOMS(jsdc); michael@0: michael@0: atom = (JSDAtom*) JS_HashTableLookup(jsdc->atoms, str); michael@0: michael@0: if( atom ) michael@0: atom->refcount++; michael@0: else michael@0: { michael@0: atom = (JSDAtom*) malloc(sizeof(JSDAtom)); michael@0: if( atom ) michael@0: { michael@0: atom->str = strdup(str); michael@0: atom->refcount = 1; michael@0: if(!JS_HashTableAdd(jsdc->atoms, atom->str, atom)) michael@0: { michael@0: free(atom->str); michael@0: free(atom); michael@0: atom = nullptr; michael@0: } michael@0: } michael@0: } michael@0: michael@0: JSD_UNLOCK_ATOMS(jsdc); michael@0: return atom; michael@0: } michael@0: michael@0: JSDAtom* michael@0: jsd_CloneAtom(JSDContext* jsdc, JSDAtom* atom) michael@0: { michael@0: JSD_LOCK_ATOMS(jsdc); michael@0: atom->refcount++; michael@0: JSD_UNLOCK_ATOMS(jsdc); michael@0: return atom; michael@0: } michael@0: michael@0: void michael@0: jsd_DropAtom(JSDContext* jsdc, JSDAtom* atom) michael@0: { michael@0: JSD_LOCK_ATOMS(jsdc); michael@0: if(! --atom->refcount) michael@0: { michael@0: JS_HashTableRemove(jsdc->atoms, atom->str); michael@0: free(atom->str); michael@0: free(atom); michael@0: } michael@0: JSD_UNLOCK_ATOMS(jsdc); michael@0: } michael@0: