diff src/basic/SourceLocation.d @ 206:d3c148ca429b

Major moving of files. all src now goes into src, all docs in docs.
author Anders Johnsen <skabet@gmail.com>
date Tue, 12 Aug 2008 18:14:56 +0200
parents
children e0551773a005
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/basic/SourceLocation.d	Tue Aug 12 18:14:56 2008 +0200
@@ -0,0 +1,145 @@
+module basic.SourceLocation;
+
+/// Shorter alias for SourceLocation
+public alias SourceLocation SLoc;
+
+/// SourceLocation points to a place in some buffer
+struct SourceLocation
+{
+    /// Returns true, if the location is from a real file
+    bool isReal() { return (val & 0x80_00_00_00) == 0; }
+    /// Returns true, if the location is not from a real file
+    bool isVirtual() { return (val & 0x80_00_00_00) != 0; }
+
+    /// Check if this location is invalid or not
+    bool isValid() { return val != uint.max; }
+    /// ditto
+    bool isInvalid() { return val == uint.max; }
+
+    /**
+      Extracts the file id.
+
+      Warning: In release mode this may return junk, if the loc is not from a
+      file
+     **/
+    uint fileID() {
+        assert(isValid, "Location is invalid");
+        assert(isReal, "You can only extract fileID from a real location");
+        // Here we can rely on two facts, first that the high bit is zero
+        // since its a real position, second that FileOffset is saved in the
+        // high end, so all we need is some shifting
+        return val >> Bits.FileOffset;
+    }
+
+    /**
+      Extracts the offset into the "file". (actually in to the referenced
+      chunk)
+
+      Warning: In release mode this may return junk, if the loc is not from a
+      file
+     **/
+    uint fileOffset() {
+        assert(isValid, "Location is invalid");
+        assert(isReal, "You can only extract fileOffset from real locations");
+        // FileOffset is stored in the lower bits, so all that is needed is a
+        // binary and with all ones in the lower bits.
+        return val & (1 << Bits.FileOffset) - 1;
+    }
+
+    /// Get a new location, placed n bytes after the given location
+    SourceLocation opAdd(int n)
+    {
+        SourceLocation res = *this;
+        res.val += n;
+        return res;
+    }
+
+    /// Get a new location, placed n bytes before the given location
+    SourceLocation opSub(int n)
+    {
+        SourceLocation res = *this;
+        res.val -= n;
+        return res;
+    }
+
+    /// Creates a SourceLocation from a File ID
+    static SourceLocation fromFileID(uint fileID)
+    {
+        assert(fileID < Bits.MaxFileID, "To large fileID");
+        SourceLocation res;
+        res.val = fileID << Bits.FileOffset;
+        return res;
+    }
+
+    /**
+      Used for invalid/unknown locations. (also the default value, but this is
+      more explicit)
+     **/
+    static const SourceLocation Invalid = {val: uint.max};
+
+private:
+    /**
+      A SourceLocation consists of 1 bit, indicating real or virtual, meaning
+      if the location points to a file(real), a string mixin or has been
+      affected by #line(virtual). That information is saved in the most
+      significant bit.
+      The rest depends on which type we are dealing with.
+      Real:
+           13 bits for a file identifier
+           18 bits for offset into that "file" (one file may be split)
+      Virtual:
+           Unknown for now. Likely skewed toward more ids and some meta data
+      An invalid location is uint.max, this might happen by accident but its
+      unlikely.
+     **/
+    uint val = uint.max;
+
+    /**
+      This enum contains some constants that are useful for manipulating
+      SourceLocation's, like the size of various “members” of val.
+     **/
+    static enum Bits {
+        /// Number of bits used for the offset into file buffers
+        FileOffset = 18,
+        /// Number of bits used to identify which file buffer this is from
+        FileID = 31 - FileOffset,
+
+        /// Indicates how much can be indexed within one block(2^FileOffset)
+        MaxFileOffset = 1 << FileOffset,
+        MaxFileID = 1 << FileID,
+    }
+}
+
+/// A simple pair used to describe a range in a buffer and not just a point.
+struct SourceRange
+{
+    SourceLocation begin, end;
+
+    static SourceRange opCall(SourceLocation loc)
+    {
+        return SourceRange(loc, loc + 1);
+    }
+
+    static SourceRange opCall(SourceLocation begin, SourceLocation end)
+    {
+        SourceRange res;
+        res.begin = begin;
+        res.end = end;
+        return res;
+    }
+
+    bool isValid() { return begin.isValid && end.isValid; }
+    bool isInvalid() { return begin.isInvalid || end.isInvalid; }
+
+    bool isReal() { return begin.isReal && end.isReal; }
+
+    /// Get a new range spanning both ranges
+    SourceRange opAdd(SourceRange that)
+    {
+        assert(this.isValid && that.isValid, "Invalid range");
+        return SourceRange(
+                this.begin.val < that.begin.val? this.begin : that.begin,
+                this.end.val > that.end.val? this.end : that.end);
+    }
+}
+