1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/src/Packages.h Tue Jan 01 15:34:07 2013 -0800
1.3 @@ -0,0 +1,193 @@
1.4 +/*
1.5 + * Copyright (C) 2012 David Anderson
1.6 + *
1.7 + * This file is part of SourcePawn.
1.8 + *
1.9 + * SourcePawn is free software: you can redistribute it and/or modify it under
1.10 + * the terms of the GNU General Public License as published by the Free
1.11 + * Software Foundation, either version 3 of the License, or (at your option)
1.12 + * any later version.
1.13 + *
1.14 + * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
1.15 + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
1.16 + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
1.17 + *
1.18 + * You should have received a copy of the GNU General Public License along with
1.19 + * SourcePawn. If not, see http://www.gnu.org/licenses/.
1.20 + */
1.21 +#ifndef _include_sp2_packages_h_
1.22 +#define _include_sp2_packages_h_
1.23 +
1.24 +#include "PoolAllocator.h"
1.25 +#include "Objects.h"
1.26 +#include "HashTable.h"
1.27 +
1.28 +namespace ke {
1.29 +
1.30 +class String;
1.31 +class Module;
1.32 +class Package;
1.33 +class ImportStatement;
1.34 +class VirtualObjectVisitor;
1.35 +
1.36 +template <typename T> class List;
1.37 +
1.38 +struct PathComponent : PoolObject
1.39 +{
1.40 + PathComponent(ScopedRoot<String> *name, PathComponent *next)
1.41 + : name(*name),
1.42 + next(next)
1.43 + {
1.44 + }
1.45 + ScopedRoot<String> &name;
1.46 + PathComponent *next;
1.47 +};
1.48 +
1.49 +class Importable : public Object
1.50 +{
1.51 + public:
1.52 + Package *parent() {
1.53 + return parent_;
1.54 + }
1.55 + String *path() {
1.56 + return path_;
1.57 + }
1.58 + String *name() {
1.59 + return name_;
1.60 + }
1.61 +
1.62 + bool isModule() {
1.63 + return is(MapKind_Module);
1.64 + }
1.65 + bool isPackage() {
1.66 + return is(MapKind_Package);
1.67 + }
1.68 +
1.69 + static inline size_t offsetOfName() {
1.70 + return OFFSETOF(Importable, name_);
1.71 + }
1.72 + static inline size_t offsetOfParent() {
1.73 + return OFFSETOF(Importable, parent_);
1.74 + }
1.75 + static inline size_t offsetOfPath() {
1.76 + return OFFSETOF(Importable, path_);
1.77 + }
1.78 +
1.79 + static inline Importable *cast(Object *obj) {
1.80 + assert(!obj || obj->is(MapKind_Module) || obj->is(MapKind_Package));
1.81 + return reinterpret_cast<Importable *>(obj);
1.82 + }
1.83 +
1.84 + protected:
1.85 + Barriered<String> name_;
1.86 + Barriered<Package> parent_;
1.87 + Barriered<String> path_;
1.88 +};
1.89 +
1.90 +// A package is a single folder in the file system, and contains any number of
1.91 +// modules and sub-packages. The package hierarchy forms a tree. For simplicity
1.92 +// the root of the tree is an anonymous package that contains no modules.
1.93 +//
1.94 +// Each package in the package hierarchy has two components of path information:
1.95 +// (1) Canonical path. This is a normalized path used to compute the paths of
1.96 +// modules.
1.97 +// (2) Name. This is the package's name as it would appear in a path
1.98 +// component. It is optional.
1.99 +//
1.100 +// Packages may be "hidden", meaning that even if they have names, their name
1.101 +// is not accessible from any import statements. Packages may also be "jailed",
1.102 +// meaning that other names in the package are not visible to each other.
1.103 +//
1.104 +// Packages are created in a few ways:
1.105 +//
1.106 +// (1) System Roots. A system root is a default search location for imports,
1.107 +// and they are installed at the top-level of the hierarchy by the host
1.108 +// application. A system root has a unique top-level name and path.
1.109 +// System roots are always hidden.
1.110 +//
1.111 +// (2) Imports. When importing, the package hierarchy may be extended as
1.112 +// new paths are discovered. Packages discovered this way are never
1.113 +// hidden or jailed.
1.114 +//
1.115 +// (3) Via Package::New(), which creates an empty package. This can be used
1.116 +// to create custom packages.
1.117 +class Package : public Importable
1.118 +{
1.119 + public:
1.120 + enum {
1.121 + Normal = 0,
1.122 +
1.123 + // These must match the flags in the public API for Package.
1.124 + Hidden = (1 << 0),
1.125 + Jailed = (1 << 1)
1.126 + };
1.127 +
1.128 + public:
1.129 + static Package *NewNormalized(Zone *zone,
1.130 + Handle<Package> parent,
1.131 + Handle<String> path,
1.132 + Handle<String> name,
1.133 + unsigned flags);
1.134 + static Package *New(Zone *zone,
1.135 + Handle<Package> parent,
1.136 + const char *path,
1.137 + Handle<String> name,
1.138 + unsigned flags);
1.139 +
1.140 + bool add(Zone *zone, Handle<Importable> component);
1.141 +
1.142 + bool hidden() {
1.143 + return !!(flags_ & Package::Hidden);
1.144 + }
1.145 + bool jailed() {
1.146 + return !!(flags_ & Package::Jailed);
1.147 + }
1.148 +
1.149 + void setNativeIdentity(void *identity) {
1.150 + nativeIdentity_ = identity;
1.151 + }
1.152 + void *getNativeIdentity() {
1.153 + return nativeIdentity_;
1.154 + }
1.155 + Importable *import(Handle<String> name);
1.156 +
1.157 + // Begin GC descriptor.
1.158 + static inline size_t offsetOfContents() {
1.159 + return OFFSETOF(Package, contents_);
1.160 + }
1.161 + // End GC descriptor.
1.162 +
1.163 + static inline Package *cast(Object *obj) {
1.164 + assert(!obj || obj->is(MapKind_Package));
1.165 + return reinterpret_cast<Package *>(obj);
1.166 + }
1.167 +
1.168 + private:
1.169 + unsigned flags_;
1.170 + Barriered<List<Importable> > contents_;
1.171 + void *nativeIdentity_;
1.172 +};
1.173 +
1.174 +class PackageCache
1.175 +{
1.176 + public:
1.177 + PackageCache(Zone *zone);
1.178 + ~PackageCache();
1.179 + bool initialize();
1.180 +
1.181 + bool findOrAdd(Handle<Package> package, PathComponent *path, Importable **out);
1.182 +
1.183 + void accept(VirtualObjectVisitor *visitor);
1.184 +
1.185 + private:
1.186 + bool import(Handle<Package> package, PathComponent *path, Importable **out);
1.187 + bool checkfs(Handle<Package> package, PathComponent *path, Importable **out);
1.188 +
1.189 + private:
1.190 + Zone *zone_;
1.191 + Vector<Unbarriered<Package> > roots_;
1.192 +};
1.193 +
1.194 +} // namespace ke
1.195 +
1.196 +#endif // _include_sp2_packages_h_