src/Packages.h
author Asher Baker <asherkin@gmail.com>
Mon Jun 10 00:46:29 2013 +0100 (2013-06-10)
changeset 262 c4b1341297e5
parent 251 ca99a81745fe
child 263 ba85a47ee414
permissions -rw-r--r--
Fix warnings when building with clang.
     1 /*
     2  * Copyright (C) 2012 David Anderson
     3  *
     4  * This file is part of SourcePawn.
     5  *
     6  * SourcePawn is free software: you can redistribute it and/or modify it under
     7  * the terms of the GNU General Public License as published by the Free
     8  * Software Foundation, either version 3 of the License, or (at your option)
     9  * any later version.
    10  * 
    11  * SourcePawn is distributed in the hope that it will be useful, but WITHOUT ANY
    12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
    14  *
    15  * You should have received a copy of the GNU General Public License along with
    16  * SourcePawn. If not, see http://www.gnu.org/licenses/.
    17  */
    18 #ifndef _include_sp2_packages_h_
    19 #define _include_sp2_packages_h_
    20 
    21 #include "PoolAllocator.h"
    22 #include "Objects.h"
    23 #include "HashTable.h"
    24 
    25 namespace ke {
    26 
    27 class String;
    28 class Module;
    29 class Package;
    30 class ImportStatement;
    31 class VirtualObjectVisitor;
    32 
    33 template <typename T> class List;
    34 
    35 struct PathComponent : PoolObject
    36 {
    37     PathComponent(ScopedRoot<String> *name, PathComponent *next)
    38       : name(*name),
    39         next(next)
    40     {
    41     }
    42     ScopedRoot<String> &name;
    43     PathComponent *next;
    44 };
    45 
    46 class Importable : public Object
    47 {
    48   public:
    49     Package *parent() {
    50         return parent_;
    51     }
    52     String *path() {
    53         return path_;
    54     }
    55     String *name() {
    56         return name_;
    57     }
    58 
    59     bool isModule() {
    60         return is(MapKind_Module);
    61     }
    62     bool isPackage() {
    63         return is(MapKind_Package);
    64     }
    65 
    66     static inline size_t offsetOfName() {
    67         return OFFSETOF(Importable, name_);
    68     }
    69     static inline size_t offsetOfParent() {
    70         return OFFSETOF(Importable, parent_);
    71     }
    72     static inline size_t offsetOfPath() {
    73         return OFFSETOF(Importable, path_);
    74     }
    75 
    76     static inline Importable *cast(Object *obj) {
    77         assert(!obj || obj->is(MapKind_Module) || obj->is(MapKind_Package));
    78         return reinterpret_cast<Importable *>(obj);
    79     }
    80 
    81   protected:
    82     Barriered<String> name_;
    83     Barriered<Package> parent_;
    84     Barriered<String> path_;
    85 };
    86 
    87 // A package is a single folder in the file system, and contains any number of
    88 // modules and sub-packages. The package hierarchy forms a tree. For simplicity
    89 // the root of the tree is an anonymous package that contains no modules.
    90 //
    91 // Each package in the package hierarchy has two components of path information:
    92 //   (1) Canonical path. This is a normalized path used to compute the paths of
    93 //       modules.
    94 //   (2) Name. This is the package's name as it would appear in a path
    95 //       component. It is optional.
    96 //
    97 // Packages may be "hidden", meaning that even if they have names, their name
    98 // is not accessible from any import statements. Packages may also be "jailed",
    99 // meaning that other names in the package are not visible to each other.
   100 //
   101 // Packages are created in a few ways:
   102 //
   103 //   (1) System Roots. A system root is a default search location for imports,
   104 //       and they are installed at the top-level of the hierarchy by the host
   105 //       application. A system root has a unique top-level name and path.
   106 //       System roots are always hidden.
   107 //
   108 //   (2) Imports. When importing, the package hierarchy may be extended as
   109 //       new paths are discovered. Packages discovered this way are never
   110 //       hidden or jailed.
   111 //
   112 //   (3) Via Package::New(), which creates an empty package. This can be used
   113 //       to create custom packages.
   114 class Package : public Importable
   115 {
   116   public:
   117     enum {
   118         Normal = 0,
   119 
   120         // These must match the flags in the public API for Package.
   121         Hidden = (1 << 0),
   122         Jailed = (1 << 1)
   123     };
   124 
   125   public:
   126     static Package *NewNormalized(Zone *zone,
   127                                   Handle<Package> parent,
   128                                   Handle<String> path,
   129                                   Handle<String> name,
   130                                   unsigned flags);
   131     static Package *New(Zone *zone,
   132                         Handle<Package> parent,
   133                         const char *path,
   134                         Handle<String> name,
   135                         unsigned flags);
   136 
   137     bool add(Zone *zone, Handle<Importable> component);
   138 
   139     bool hidden() {
   140         return !!(flags_ & Package::Hidden);
   141     }
   142     bool jailed() {
   143         return !!(flags_ & Package::Jailed);
   144     }
   145 
   146     void setNativeIdentity(void *identity) {
   147         nativeIdentity_ = identity;
   148     }
   149     void *getNativeIdentity() {
   150         return nativeIdentity_;
   151     }
   152     Importable *import(Handle<String> name);
   153 
   154     // Begin GC descriptor.
   155     static inline size_t offsetOfContents() {
   156         return OFFSETOF(Package, contents_);
   157     }
   158     // End GC descriptor.
   159 
   160     static inline Package *cast(Object *obj) {
   161         assert(!obj || obj->is(MapKind_Package));
   162         return reinterpret_cast<Package *>(obj);
   163     }
   164 
   165   private:
   166     unsigned flags_;
   167     Barriered<List<Importable> > contents_;
   168     void *nativeIdentity_;
   169 };
   170 
   171 class PackageCache
   172 {
   173   public:
   174     PackageCache(Zone *zone);
   175     ~PackageCache();
   176     bool initialize();
   177 
   178     bool findOrAdd(Handle<Package> package, PathComponent *path, Importable **out);
   179 
   180     void accept(VirtualObjectVisitor *visitor);
   181 
   182   private:
   183     bool import(Handle<Package> package, PathComponent *path, Importable **out);
   184     bool checkfs(Handle<Package> package, PathComponent *path, Importable **out);
   185 
   186   private:
   187     Zone *zone_;
   188     Vector<Unbarriered<Package> > roots_;
   189 };
   190 
   191 } // namespace ke
   192 
   193 #endif // _include_sp2_packages_h_