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