Add negative numbers to primitive parsing

pragma solidity ^0.4.2;

library JsmnSol {

    enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }
    enum JsmnError { INVALID, ERROR_PART, NO_MEMORY}

    struct Token {
        JsmnType jsmnType;
        uint start;
        bool startSet;
        uint end;
        bool endSet;
        uint8 size;
    }

    struct Parser {
        uint pos;
        uint toknext;
        int toksuper;
    }

    function init(uint length) internal returns (Parser, Token[]) {
        Parser memory p = Parser(0, 0, -1);
        Token[] memory t = new Token[](length);
        return (p, t);
    }

    function allocateToken(Parser parser, Token[] tokens) internal returns (bool, Token) {
        if (parser.toknext >= tokens.length) {
            // no more space in tokens
            return (false, tokens[tokens.length-1]);
        }
        Token memory token = Token(JsmnType.UNDEFINED, 0, false, 0, false, 0);
        tokens[parser.toknext] = token;
        parser.toknext++;
        return (true, token);
    }

    function fillToken(Token token, JsmnType jsmnType, uint start, uint end) internal {
        token.jsmnType = jsmnType;
        token.start = start;
        token.startSet = true;
        token.end = end;
        token.endSet = true;
        token.size = 0;
    }

    function parseString(Parser parser, Token[] tokens, bytes s) internal returns (int) {
        uint start = parser.pos;
        parser.pos++;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // Quote -> end of string
            if (c == '"') {
                var (success, token) = allocateToken(parser, tokens);
                if (!success) {
                    parser.pos = start;
                    return int(JsmnError.NO_MEMORY);
                }
                fillToken(token, JsmnType.STRING, start+1, parser.pos);
                return 0;
            }

            if (c == '\\') {
                // TODO handle escaped characters
            }
        }
        parser.pos = start;
        return int(JsmnError.ERROR_PART);
    }

    function parsePrimitive(Parser parser, Token[] tokens, bytes s) internal returns (int) {
        bool found = false;
        uint start = parser.pos;
        byte c;
        for (; parser.pos < s.length; parser.pos++) {
            c = s[parser.pos];
            if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == ','
                || c == 0x7d || c == 0x5d) {
                    found = true;
                    break;
            }
            if (c < 32 || c > 127) {
                parser.pos = start;
                return int(JsmnError.INVALID);
            }
        }
        if (!found) {
            parser.pos = start;
            return int(JsmnError.ERROR_PART);
        }

        // found the end
        var (success, token) = allocateToken(parser, tokens);
        if (!success) {
            parser.pos = start;
            return int(JsmnError.NO_MEMORY);
        }
        fillToken(token, JsmnType.PRIMITIVE, start, parser.pos);
        parser.pos--;
        return 0;
    }

    function parse(string json, uint numberElements) internal returns (bool, Token[], uint) {
        bytes memory s = bytes(json);
        var (parser, tokens) = init(numberElements);

        // Token memory token;
        int r;
        uint count = parser.toknext;
        uint i;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // 0x7b, 0x5b opening parentheses
            if (c == 0x7b || c == 0x5b) {
                count++;
                var (success, token)= allocateToken(parser, tokens);
                if (!success) {
                    return (false, tokens, 0);
                    //JsmnError.NO_MEMORY;
                }
                if (parser.toksuper != -1) {
                    tokens[uint(parser.toksuper)].size++;
                }
                token.jsmnType = (c == 0x7b ? JsmnType.OBJECT : JsmnType.ARRAY);
                token.start = parser.pos;
                token.startSet = true;
                parser.toksuper = int(parser.toknext - 1);
                continue;
            }

            // closing parentheses
            if (c == 0x7d || c == 0x5d) {
                JsmnType tokenType = (c == 0x7d ? JsmnType.OBJECT : JsmnType.ARRAY);
                bool isUpdated = false;
                for (i=parser.toknext-1; i>=0; i--) {
                    token = tokens[i];
                    if (token.startSet && !token.endSet) {
                        if (token.jsmnType != tokenType) {
                            // found a token that hasn't been closed but from a different type
                            return (false, tokens, 0);
                            //JsmnError.INVALID;
                        }
                        parser.toksuper = -1;
                        tokens[i].end = parser.pos + 1;
                        tokens[i].endSet = true;
                        isUpdated = true;
                        break;
                    }
                }
                if (!isUpdated) {
                    return (false, tokens, 0);
                    //JsmnError.INVALID;
                }
                for (; i>0; i--) {
                    token = tokens[i];
                    if (token.startSet && !token.endSet) {
                        parser.toksuper = int(i);
                        break;
                    }
                }

                if (i==0) {
                    token = tokens[i];
                    if (token.startSet && !token.endSet) {
                        parser.toksuper = uint128(i);
                    }
                }
                continue;
            }

            // 0x42
            if (c == '"') {
                r = parseString(parser, tokens, s);
                if (r < 0) return (false, tokens, 0);
                //JsmnError.INVALID;
                count++;
				if (parser.toksuper != -1)
					tokens[uint(parser.toksuper)].size++;
                continue;
            }

            // ' ', \r, \t, \n
            if (c == ' ' || c == 0x11 || c == 0x12 || c == 0x14) {
                continue;
            }

            // 0x3a
            if (c == ':') {
                parser.toksuper = int(parser.toknext -1);
                continue;
            }

            if (c == ',') {
                if (parser.toksuper != -1
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.ARRAY
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.OBJECT) {
                        for(i = parser.toknext-1; i>=0; i--) {
                            if (tokens[i].jsmnType == JsmnType.ARRAY || tokens[i].jsmnType == JsmnType.OBJECT) {
                                if (tokens[i].startSet && !tokens[i].endSet) {
                                    parser.toksuper = int(i);
                                    break;
                                }
                            }
                        }
                    }
                continue;
            }

            // Primitive
            // FIXME Doesn't handle negative numbers (Can I just include '-'?)
            if ((c >= '0' && c <= '9') || c == '-' || c == 'f' || c == 't' || c == 'n') {
                if (parser.toksuper != -1) {
                    token = tokens[uint(parser.toksuper)];
                    if (token.jsmnType == JsmnType.OBJECT
                        || (token.jsmnType == JsmnType.STRING && token.size != 0)) {
                            return (false, tokens, 0);
                            // JsmnError.INVALID;
                        }
                }

                r = parsePrimitive(parser, tokens, s);
                if (r < 0) { return (false, tokens, 0);
                    // JsmnError.INVALID;
                }
                count++;
                if (parser.toksuper != -1) {
                    tokens[uint(parser.toksuper)].size++;
                }
                continue;
            }

            // printable char
            if (c >= 0x20 && c <= 0x7e) {
                continue;
            }
        }

        return (true, tokens, parser.toknext-1);
    }
}

pragma solidity ^0.4.2;

library JsmnSol {

    enum JsmnType { UNDEFINED, OBJECT, ARRAY, STRING, PRIMITIVE }
    enum JsmnError { INVALID, ERROR_PART, NO_MEMORY}

    struct Token {
        JsmnType jsmnType;
        uint start;
        bool startSet;
        uint end;
        bool endSet;
        uint8 size;
    }

    struct Parser {
        uint pos;
        uint toknext;
        int toksuper;
    }

    function init(uint length) internal returns (Parser, Token[]) {
        Parser memory p = Parser(0, 0, -1);
        Token[] memory t = new Token[](length);
        return (p, t);
    }

    function allocateToken(Parser parser, Token[] tokens) internal returns (bool, Token) {
        if (parser.toknext >= tokens.length) {
            // no more space in tokens
            return (false, tokens[tokens.length-1]);
        }
        Token memory token = Token(JsmnType.UNDEFINED, 0, false, 0, false, 0);
        tokens[parser.toknext] = token;
        parser.toknext++;
        return (true, token);
    }

    function fillToken(Token token, JsmnType jsmnType, uint start, uint end) internal {
        token.jsmnType = jsmnType;
        token.start = start;
        token.startSet = true;
        token.end = end;
        token.endSet = true;
        token.size = 0;
    }

    function parseString(Parser parser, Token[] tokens, bytes s) internal returns (int) {
        uint start = parser.pos;
        parser.pos++;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // Quote -> end of string
            if (c == '"') {
                var (success, token) = allocateToken(parser, tokens);
                if (!success) {
                    parser.pos = start;
                    return int(JsmnError.NO_MEMORY);
                }
                fillToken(token, JsmnType.STRING, start+1, parser.pos);
                return 0;
            }

            if (c == '\\') {
                // TODO handle escaped characters
            }
        }
        parser.pos = start;
        return int(JsmnError.ERROR_PART);
    }

    function parsePrimitive(Parser parser, Token[] tokens, bytes s) internal returns (int) {
        bool found = false;
        uint start = parser.pos;
        byte c;
        for (; parser.pos < s.length; parser.pos++) {
            c = s[parser.pos];
            if (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == ','
                || c == 0x7d || c == 0x5d) {
                    found = true;
                    break;
            }
            if (c < 32 || c > 127) {
                parser.pos = start;
                return int(JsmnError.INVALID);
            }
        }
        if (!found) {
            parser.pos = start;
            return int(JsmnError.ERROR_PART);
        }

        // found the end
        var (success, token) = allocateToken(parser, tokens);
        if (!success) {
            parser.pos = start;
            return int(JsmnError.NO_MEMORY);
        }
        fillToken(token, JsmnType.PRIMITIVE, start, parser.pos);
        parser.pos--;
        return 0;
    }

    function parse(string json, uint numberElements) internal returns (bool, Token[], uint) {
        bytes memory s = bytes(json);
        var (parser, tokens) = init(numberElements);

        // Token memory token;
        int r;
        uint count = parser.toknext;
        uint i;

        for (; parser.pos<s.length; parser.pos++) {
            bytes1 c = s[parser.pos];

            // 0x7b, 0x5b opening parentheses
            if (c == 0x7b || c == 0x5b) {
                count++;
                var (success, token)= allocateToken(parser, tokens);
                if (!success) {
                    return (false, tokens, 0);
                    //JsmnError.NO_MEMORY;
                }
                if (parser.toksuper != -1) {
                    tokens[uint(parser.toksuper)].size++;
                }
                token.jsmnType = (c == 0x7b ? JsmnType.OBJECT : JsmnType.ARRAY);
                token.start = parser.pos;
                token.startSet = true;
                parser.toksuper = int(parser.toknext - 1);
                continue;
            }

            // closing parentheses
            if (c == 0x7d || c == 0x5d) {
                JsmnType tokenType = (c == 0x7d ? JsmnType.OBJECT : JsmnType.ARRAY);
                bool isUpdated = false;
                for (i=parser.toknext-1; i>=0; i--) {
                    token = tokens[i];
                    if (token.startSet && !token.endSet) {
                        if (token.jsmnType != tokenType) {
                            // found a token that hasn't been closed but from a different type
                            return (false, tokens, 0);
                            //JsmnError.INVALID;
                        }
                        parser.toksuper = -1;
                        tokens[i].end = parser.pos + 1;
                        tokens[i].endSet = true;
                        isUpdated = true;
                        break;
                    }
                }
                if (!isUpdated) {
                    return (false, tokens, 0);
                    //JsmnError.INVALID;
                }
                for (; i>0; i--) {
                    token = tokens[i];
                    if (token.startSet && !token.endSet) {
                        parser.toksuper = int(i);
                        break;
                    }
                }

                if (i==0) {
                    token = tokens[i];
                    if (token.startSet && !token.endSet) {
                        parser.toksuper = uint128(i);
                    }
                }
                continue;
            }

            // 0x42
            if (c == '"') {
                r = parseString(parser, tokens, s);
                if (r < 0) return (false, tokens, 0);
                //JsmnError.INVALID;
                count++;
				if (parser.toksuper != -1)
					tokens[uint(parser.toksuper)].size++;
                continue;
            }

            // ' ', \r, \t, \n
            if (c == ' ' || c == 0x11 || c == 0x12 || c == 0x14) {
                continue;
            }

            // 0x3a
            if (c == ':') {
                parser.toksuper = int(parser.toknext -1);
                continue;
            }

            if (c == ',') {
                if (parser.toksuper != -1
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.ARRAY
                    && tokens[uint(parser.toksuper)].jsmnType != JsmnType.OBJECT) {
                        for(i = parser.toknext-1; i>=0; i--) {
                            if (tokens[i].jsmnType == JsmnType.ARRAY || tokens[i].jsmnType == JsmnType.OBJECT) {
                                if (tokens[i].startSet && !tokens[i].endSet) {
                                    parser.toksuper = int(i);
                                    break;
                                }
                            }
                        }
                    }
                continue;
            }

            if ((c >= '0' && c <= '9') || c == 'f' || c == 't' || c == 'n') {
                if (parser.toksuper != -1) {
                    token = tokens[uint(parser.toksuper)];
                    if (token.jsmnType == JsmnType.OBJECT
                        || (token.jsmnType == JsmnType.STRING && token.size != 0)) {
                            return (false, tokens, 0);
                            // JsmnError.INVALID;
                        }
                }

                r = parsePrimitive(parser, tokens, s);
                if (r < 0) { return (false, tokens, 0);
                    // JsmnError.INVALID;
                }
                count++;
                if (parser.toksuper != -1) {
                    tokens[uint(parser.toksuper)].size++;
                }
                continue;
            }

            // printable char
            if (c >= 0x20 && c <= 0x7e) {
                continue;
            }
        }

        return (true, tokens, parser.toknext-1);
    }
}


Document addInterval behavior

Document addInterval behavior

pragma solidity ^0.4.15;

import "./vendor/grove/GroveLib.sol";

library IntervalTreeLib {
  using GroveLib for GroveLib.Index;

  bool constant TRAVERSE_BEFORE = false;
  bool constant TRAVERSE_AFTER = true;

  struct Tree {
    // global table of intervals
    mapping (uint => Interval) intervals;
    uint numIntervals;

    // tree nodes
    mapping (uint => Node) nodes;
    uint numNodes;

    // pointer to root of tree
    uint rootNode;
  }

  struct Node {
    uint center;
    uint nodeBefore;
    uint nodeAfter;
    uint count;
    GroveLib.Index beginIndex;
    GroveLib.Index endIndex;

    // references to boundary intervals (GroveLib.Index node IDs)
    bytes32 lowestBeginIndexNode;
    bytes32 highestEndIndexNode;
  }

  struct Interval {
    uint begin;
    uint end;
    bytes32 data;
  }

  function addInterval(Tree storage tree, uint begin, uint end, bytes32 data) internal {
    uint intervalID = _createInterval(tree, begin, end, data);

    // if the tree is empty, create the root
    if (tree.rootNode == 0) {
      var nodeID = _createNode(tree, begin, end);
      tree.rootNode = nodeID;

      var node = tree.nodes[nodeID];
      _addIntervalToNode(node, begin, end, intervalID);

      return;
    }

    // depth-first search tree for place to add interval.
    // for each step of the search:
    //   if the new interval contains the current node's center:
    //     add interval to current node
    //     stop search
    //
    //   if the new interval < center:
    //     recurse "before"
    //   if the new interval > center:
    //     recurse "after"
    uint curID = tree.rootNode;
    Node storage curNode = tree.nodes[curID];
    bool found = false;
    while (!found) {
      // track direction of recursion each step, to update correct pointer
      // upon needing to add a new node
      bool recurseDirection;

      if (end <= curNode.center) {
	// traverse before
	curID = curNode.nodeBefore;
	recurseDirection = TRAVERSE_BEFORE;
      } else if (begin > curNode.center) {
	// traverse after
	curID = curNode.nodeAfter;
	recurseDirection = TRAVERSE_AFTER;
      } else {
	// found!
	found = true;
	break;
      }

      // if traversing yields null pointer for child node, must create
      if (curID == 0) {
	curID = _createNode(tree, begin, end);

	// update appropriate pointer
	if (recurseDirection == TRAVERSE_BEFORE) {
	  curNode.nodeBefore = curID;
	} else {
	  curNode.nodeAfter = curID;
	}
      }

      // fetch node definition for new curID + update var
      curNode = tree.nodes[curID];
    }

    // loop exits with curNode set to correct location for interval
    // add it!
    _addIntervalToNode(curNode, begin, end, intervalID);
  }

  /*
   * search
   */
  function intervalsAt(Tree storage tree, uint point)
    constant
    returns (uint)
  {
    return search(tree, point).length;
  }

  function intervalAt(Tree storage tree, uint point, uint offset)
    constant
    returns (uint begin, uint end, bytes32 data)
  {
    var results = search(tree, point);

    require(offset < results.length);

    var interval = tree.intervals[results[offset]];

    return (interval.begin, interval.end, interval.data);
  }

  function search(Tree storage tree, uint point)
    constant
    internal
    returns (uint[] memory intervalIDs)
  {
    intervalIDs = new uint[](0);
    uint[] memory tempIDs;
    uint[] memory addedIDs;
    uint i;
    bool searchLower;
    bool searchHigher;

    uint curID = tree.rootNode;
    var curNode = tree.nodes[curID];
    (addedIDs, searchLower, searchHigher) = _searchNode(curNode, point);
    tempIDs = new uint[](intervalIDs.length + addedIDs.length);
    for (i = 0; i < intervalIDs.length; i++) {
      tempIDs[i] = intervalIDs[i];
    }
    for (i = 0; i < addedIDs.length; i++) {
      tempIDs[i + intervalIDs.length] = addedIDs[i];
    }
    intervalIDs = tempIDs;

    while (searchLower || searchHigher) {
      if (searchLower) {
	curID = curNode.nodeBefore;
      } else { // searchHigher
	curID = curNode.nodeAfter;
      }
      if (curID == 0x0) {
	break;
      }

      curNode = tree.nodes[curID];
      (addedIDs, searchLower, searchHigher) = _searchNode(curNode, point);

      tempIDs = new uint[](intervalIDs.length + addedIDs.length);
      for (i = 0; i < intervalIDs.length; i++) {
	tempIDs[i] = intervalIDs[i];
      }
      for (i = 0; i < addedIDs.length; i++) {
	tempIDs[i + intervalIDs.length] = addedIDs[i];
      }
      intervalIDs = tempIDs;
    }
  }

  /*
   * insert helpers
   */
  function _createInterval(Tree storage tree, uint begin, uint end, bytes32 data)
    internal
    returns (uint intervalID)
  {
    intervalID = ++tree.numIntervals;

    tree.intervals[intervalID] = Interval({
      begin: begin,
      end: end,
      data: data
    });
  }

  function _createNode(Tree storage tree, uint begin, uint end) returns (uint nodeID) {
    nodeID = ++tree.numNodes;
    tree.nodes[nodeID] = Node({
      center: begin + (end - begin) / 2,
      nodeBefore: 0,
      nodeAfter: 0,
      count: 0,
      lowestBeginIndexNode: 0x0,
      highestEndIndexNode: 0x0,
      beginIndex: GroveLib.Index(sha3(this, bytes32(nodeID * 2))),
      endIndex: GroveLib.Index(sha3(this, bytes32(nodeID * 2 + 1)))
    });
  }

  function _addIntervalToNode(Node storage node, uint begin, uint end, uint intervalID) {
    var _intervalID = bytes32(intervalID);
    var _begin = _getBeginIndexKey(begin);
    var _end = _getEndIndexKey(end);

    node.beginIndex.insert(_intervalID, _begin);
    node.endIndex.insert(_intervalID, _end);
    node.count++;

    if (node.count == 1) {
      node.lowestBeginIndexNode = node.beginIndex.root;
      node.highestEndIndexNode = node.endIndex.root;

      return;
    }

    var newLowest = node.beginIndex.getPreviousNode(node.lowestBeginIndexNode);
    if (newLowest != 0x0) {
      node.lowestBeginIndexNode = newLowest;
    }

    var newHighest = node.endIndex.getNextNode(node.highestEndIndexNode);
    if (newHighest != 0x0) {
      node.highestEndIndexNode = newHighest;
    }
  }

  /*
   * search helpers
   */
  function _searchNode(Node storage node, uint point)
    constant
    internal
    returns (uint[] memory intervalIDs, bool searchLower, bool searchHigher)
  {
    uint[] memory _intervalIDs = new uint[](node.count);
    uint num = 0;

    bytes32 cur;

    if (point < node.center) {
      searchLower = true;
      searchHigher = false;

      cur = node.lowestBeginIndexNode;
      while (cur != 0x0) {
	uint begin = _begin(node, cur);
	if (begin > point) {
	  break;
	}

	_intervalIDs[num] = uint(node.beginIndex.getNodeId(cur));
	num++;

	cur = _next(node, cur);
      }
    }

    if (point >= node.center) {
      searchHigher = true;
      searchLower = false;

      cur = node.highestEndIndexNode;
      while (cur != 0x0) {
	uint end = _end(node, cur);
	if (end <= point) {
	  break;
	}

	_intervalIDs[num] = uint(node.endIndex.getNodeId(cur));
	num++;

	cur = _previous(node, cur);
      }
    }

    if (num == _intervalIDs.length) {
      intervalIDs = _intervalIDs;
    } else {
      intervalIDs = new uint[](num);
      for (uint i = 0; i < num; i++) {
	intervalIDs[i] = _intervalIDs[i];
      }
    }
  }

  /*
   * Grove linked list traversal
   */
  function _begin(Node storage node, bytes32 indexNode) constant returns (uint) {
    return _getBegin(node.beginIndex.getNodeValue(indexNode));
  }

  function _end(Node storage node, bytes32 indexNode) constant returns (uint) {
    return _getEnd(node.endIndex.getNodeValue(indexNode));
  }

  function _next(Node storage node, bytes32 cur) constant returns (bytes32) {
    return node.beginIndex.getNextNode(cur);
  }

  function _previous(Node storage node, bytes32 cur) constant returns (bytes32) {
    return node.endIndex.getPreviousNode(cur);
  }

  /*
   * uint / int conversions for Grove nodeIDs
   */
  function _getBeginIndexKey(uint begin) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(begin - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getEndIndexKey(uint end) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(end - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getBegin(int beginIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(beginIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }

  function _getEnd(int endIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(endIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }
}

pragma solidity ^0.4.15;

import "./vendor/grove/GroveLib.sol";

library IntervalTreeLib {
  using GroveLib for GroveLib.Index;

  struct Tree {
    // global table of intervals
    mapping (uint => Interval) intervals;
    uint numIntervals;

    // tree nodes
    mapping (uint => Node) nodes;
    uint numNodes;

    // pointer to root of tree
    uint rootNode;
  }

  struct Node {
    uint center;
    uint nodeBefore;
    uint nodeAfter;
    uint count;
    GroveLib.Index beginIndex;
    GroveLib.Index endIndex;

    // references to boundary intervals (GroveLib.Index node IDs)
    bytes32 lowestBeginIndexNode;
    bytes32 highestEndIndexNode;
  }

  struct Interval {
    uint begin;
    uint end;
    bytes32 data;
  }

  function addInterval(Tree storage tree, uint begin, uint end, bytes32 data) internal {
    uint intervalID = _createInterval(tree, begin, end, data);

    if (tree.rootNode == 0) {
      var nodeID = _createNode(tree, begin, end);
      tree.rootNode = nodeID;

      var node = tree.nodes[nodeID];
      _addIntervalToNode(node, begin, end, intervalID);

      return;
    }

    uint curID = tree.rootNode;
    var curNode = tree.nodes[curID];

    bool found = false;

    while (!found) {
      bool updateBefore = false;

      if (end <= curNode.center) {
	curID = curNode.nodeBefore;
	updateBefore = true;
      } else if (begin > curNode.center) {
	curID = curNode.nodeAfter;
      } else {
	found = true;
	break;
      }

      if (curID == 0) {
	curID = _createNode(tree, begin, end);

	if (updateBefore) {
	  curNode.nodeBefore = curID;
	} else {
	  curNode.nodeAfter = curID;
	}
      }

      curNode = tree.nodes[curID];
    }

    _addIntervalToNode(curNode, begin, end, intervalID);
  }

  /*
   * search
   */
  function intervalsAt(Tree storage tree, uint point)
    constant
    returns (uint)
  {
    return search(tree, point).length;
  }

  function intervalAt(Tree storage tree, uint point, uint offset)
    constant
    returns (uint begin, uint end, bytes32 data)
  {
    var results = search(tree, point);

    require(offset < results.length);

    var interval = tree.intervals[results[offset]];

    return (interval.begin, interval.end, interval.data);
  }

  function search(Tree storage tree, uint point)
    constant
    internal
    returns (uint[] memory intervalIDs)
  {
    intervalIDs = new uint[](0);
    uint[] memory tempIDs;
    uint[] memory addedIDs;
    uint i;
    bool searchLower;
    bool searchHigher;

    uint curID = tree.rootNode;
    var curNode = tree.nodes[curID];
    (addedIDs, searchLower, searchHigher) = _searchNode(curNode, point);
    tempIDs = new uint[](intervalIDs.length + addedIDs.length);
    for (i = 0; i < intervalIDs.length; i++) {
      tempIDs[i] = intervalIDs[i];
    }
    for (i = 0; i < addedIDs.length; i++) {
      tempIDs[i + intervalIDs.length] = addedIDs[i];
    }
    intervalIDs = tempIDs;

    while (searchLower || searchHigher) {
      if (searchLower) {
	curID = curNode.nodeBefore;
      } else { // searchHigher
	curID = curNode.nodeAfter;
      }
      if (curID == 0x0) {
	break;
      }

      curNode = tree.nodes[curID];
      (addedIDs, searchLower, searchHigher) = _searchNode(curNode, point);

      tempIDs = new uint[](intervalIDs.length + addedIDs.length);
      for (i = 0; i < intervalIDs.length; i++) {
	tempIDs[i] = intervalIDs[i];
      }
      for (i = 0; i < addedIDs.length; i++) {
	tempIDs[i + intervalIDs.length] = addedIDs[i];
      }
      intervalIDs = tempIDs;
    }
  }

  /*
   * insert helpers
   */
  function _createInterval(Tree storage tree, uint begin, uint end, bytes32 data)
    internal
    returns (uint intervalID)
  {
    intervalID = ++tree.numIntervals;

    tree.intervals[intervalID] = Interval({
      begin: begin,
      end: end,
      data: data
    });
  }

  function _createNode(Tree storage tree, uint begin, uint end) returns (uint nodeID) {
    nodeID = ++tree.numNodes;
    tree.nodes[nodeID] = Node({
      center: begin + (end - begin) / 2,
      nodeBefore: 0,
      nodeAfter: 0,
      count: 0,
      lowestBeginIndexNode: 0x0,
      highestEndIndexNode: 0x0,
      beginIndex: GroveLib.Index(sha3(this, bytes32(nodeID * 2))),
      endIndex: GroveLib.Index(sha3(this, bytes32(nodeID * 2 + 1)))
    });
  }

  function _addIntervalToNode(Node storage node, uint begin, uint end, uint intervalID) {
    var _intervalID = bytes32(intervalID);
    var _begin = _getBeginIndexKey(begin);
    var _end = _getEndIndexKey(end);

    node.beginIndex.insert(_intervalID, _begin);
    node.endIndex.insert(_intervalID, _end);
    node.count++;

    if (node.count == 1) {
      node.lowestBeginIndexNode = node.beginIndex.root;
      node.highestEndIndexNode = node.endIndex.root;

      return;
    }

    var newLowest = node.beginIndex.getPreviousNode(node.lowestBeginIndexNode);
    if (newLowest != 0x0) {
      node.lowestBeginIndexNode = newLowest;
    }

    var newHighest = node.endIndex.getNextNode(node.highestEndIndexNode);
    if (newHighest != 0x0) {
      node.highestEndIndexNode = newHighest;
    }
  }

  /*
   * search helpers
   */
  function _searchNode(Node storage node, uint point)
    constant
    internal
    returns (uint[] memory intervalIDs, bool searchLower, bool searchHigher)
  {
    uint[] memory _intervalIDs = new uint[](node.count);
    uint num = 0;

    bytes32 cur;

    if (point < node.center) {
      searchLower = true;
      searchHigher = false;

      cur = node.lowestBeginIndexNode;
      while (cur != 0x0) {
	uint begin = _begin(node, cur);
	if (begin > point) {
	  break;
	}

	_intervalIDs[num] = uint(node.beginIndex.getNodeId(cur));
	num++;

	cur = _next(node, cur);
      }
    }

    if (point >= node.center) {
      searchHigher = true;
      searchLower = false;

      cur = node.highestEndIndexNode;
      while (cur != 0x0) {
	uint end = _end(node, cur);
	if (end <= point) {
	  break;
	}

	_intervalIDs[num] = uint(node.endIndex.getNodeId(cur));
	num++;

	cur = _previous(node, cur);
      }
    }

    if (num == _intervalIDs.length) {
      intervalIDs = _intervalIDs;
    } else {
      intervalIDs = new uint[](num);
      for (uint i = 0; i < num; i++) {
	intervalIDs[i] = _intervalIDs[i];
      }
    }
  }

  /*
   * Grove linked list traversal
   */
  function _begin(Node storage node, bytes32 indexNode) constant returns (uint) {
    return _getBegin(node.beginIndex.getNodeValue(indexNode));
  }

  function _end(Node storage node, bytes32 indexNode) constant returns (uint) {
    return _getEnd(node.endIndex.getNodeValue(indexNode));
  }

  function _next(Node storage node, bytes32 cur) constant returns (bytes32) {
    return node.beginIndex.getNextNode(cur);
  }

  function _previous(Node storage node, bytes32 cur) constant returns (bytes32) {
    return node.endIndex.getPreviousNode(cur);
  }

  /*
   * uint / int conversions for Grove nodeIDs
   */
  function _getBeginIndexKey(uint begin) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(begin - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getEndIndexKey(uint end) constant internal returns (int) {
    // convert to signed int in order-preserving manner
    return int(end - 0x8000000000000000000000000000000000000000000000000000000000000000);
  }

  function _getBegin(int beginIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(beginIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }

  function _getEnd(int endIndexKey) constant internal returns (uint) {
    // convert to unsigned int in order-preserving manner
    return uint(endIndexKey) + 0x8000000000000000000000000000000000000000000000000000000000000000;
  }
}


Put premium into renewal price as a future proof incase we use premium for renewals

pragma solidity >=0.8.4;
pragma experimental ABIEncoderV2;

import "../registry/ENS.sol";
import "./ETHRegistrarController.sol";
import "./IETHRegistrarController.sol";
import "../resolvers/Resolver.sol";
import "./IBulkRenewal.sol";

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

contract BulkRenewal is IBulkRenewal {
    bytes32 private constant ETH_NAMEHASH =
        0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;

    ENS public immutable ens;

    constructor(ENS _ens) {
        ens = _ens;
    }

    function getController() internal view returns (ETHRegistrarController) {
        Resolver r = Resolver(ens.resolver(ETH_NAMEHASH));
        return
            ETHRegistrarController(
                r.interfaceImplementer(
                    ETH_NAMEHASH,
                    type(IETHRegistrarController).interfaceId
                )
            );
    }

    function rentPrice(string[] calldata names, uint256 duration)
        external
        view
        override
        returns (uint256 total)
    {
        ETHRegistrarController controller = getController();
        for (uint256 i = 0; i < names.length; i++) {
            (uint256 basePrice, ) = controller.rentPrice(names[i], duration);
            total += basePrice;
        }
    }

    function renewAll(string[] calldata names, uint256 duration)
        external
        payable
        override
    {
        ETHRegistrarController controller = getController();
        for (uint256 i = 0; i < names.length; i++) {
            (uint256 basePrice, uint256 premium) = controller.rentPrice(names[i], duration);
            controller.renew{value: basePrice + premium}(names[i]);
        }
        // Send any excess funds back
        payable(msg.sender).transfer(address(this).balance);
    }

    function supportsInterface(bytes4 interfaceID)
        external
        pure
        returns (bool)
    {
        return
            interfaceID == type(IERC165).interfaceId ||
            interfaceID == type(IBulkRenewal).interfaceId;
    }
}

pragma solidity >=0.8.4;
pragma experimental ABIEncoderV2;

import "../registry/ENS.sol";
import "./ETHRegistrarController.sol";
import "./IETHRegistrarController.sol";
import "../resolvers/Resolver.sol";
import "./IBulkRenewal.sol";

import "@openzeppelin/contracts/utils/introspection/IERC165.sol";

contract BulkRenewal is IBulkRenewal {
    bytes32 private constant ETH_NAMEHASH =
        0x93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae;

    ENS public immutable ens;

    constructor(ENS _ens) {
        ens = _ens;
    }

    function getController() internal view returns (ETHRegistrarController) {
        Resolver r = Resolver(ens.resolver(ETH_NAMEHASH));
        return
            ETHRegistrarController(
                r.interfaceImplementer(
                    ETH_NAMEHASH,
                    type(IETHRegistrarController).interfaceId
                )
            );
    }

    function rentPrice(string[] calldata names, uint256 duration)
        external
        view
        override
        returns (uint256 total)
    {
        ETHRegistrarController controller = getController();
        for (uint256 i = 0; i < names.length; i++) {
            (uint256 basePrice, ) = controller.rentPrice(names[i], duration);
            total += basePrice;
        }
    }

    function renewAll(string[] calldata names, uint256 duration)
        external
        payable
        override
    {
        ETHRegistrarController controller = getController();
        for (uint256 i = 0; i < names.length; i++) {
            (uint256 basePrice, ) = controller.rentPrice(names[i], duration);
            controller.renew{value: basePrice}(names[i]);
        }
        // Send any excess funds back
        payable(msg.sender).transfer(address(this).balance);
    }

    function supportsInterface(bytes4 interfaceID)
        external
        pure
        returns (bool)
    {
        return
            interfaceID == type(IERC165).interfaceId ||
            interfaceID == type(IBulkRenewal).interfaceId;
    }
}


Compact into one line

Compact into one line

import "Adjudicator.sol";
import "TicTacToeLockedState.sol";

/**
 * TicTacToeAdjudicator
 *
 * Adjudicates a TicTacToe game.
 */
contract TicTacToeAdjudicator is Adjudicator {

    /**
     * Creates a new TicTacToeAdjudicator
     *
     * addressX: The address of the X player
     * addressO: The address of the O player
     * _timeout: The amount of time required before the state channel can be closed normally.
     */
    function TicTacToeAdjudicator(address addressX, address addressO, uint _timeout)
        Adjudicator(new address[](2), 2, _timeout)
    {
		addresses = [addressX, addressO];
    }

    // creates and returns a new TicTacToeLockedState
    function createLockedState() internal returns (LockedState) {
        return new TicTacToeLockedState(addresses[0], addresses[1], 0);
    }
}

import "Adjudicator.sol";
import "TicTacToeLockedState.sol";

/**
 * TicTacToeAdjudicator
 *
 * Adjudicates a TicTacToe game.
 */
contract TicTacToeAdjudicator is Adjudicator {

    /**
     * Creates a new TicTacToeAdjudicator
     *
     * addressX: The address of the X player
     * addressO: The address of the O player
     * _timeout: The amount of time required before the state channel can be closed normally.
     */
    function TicTacToeAdjudicator(address addressX, address addressO, uint _timeout)
        Adjudicator(new address[](2), 2, _timeout)
    {
        addresses[0] = addressX;
        addresses[1] = addressO;
    }

    // creates and returns a new TicTacToeLockedState
    function createLockedState() internal returns (LockedState) {
        return new TicTacToeLockedState(addresses[0], addresses[1], 0);
    }
}


Add missing doxygen param.

Add missing doxygen param.

pragma solidity ^0.4.0;

import "AbstractBlobStore.sol";

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore is AbstractBlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // True if the blob is updatable. After creation can only be disabled.
        bool enforceRevisions;      // True if the blob is enforcing revisions. After creation can only be enabled.
        bool retractable;           // True if the blob can be retracted. After creation can only be disabled.
        bool transferable;          // True if the blob be transfered to another user or disowned. After creation can only be disabled.
        uint32 revisionCount;       // Number of revisions including revision 0.
        uint32 blockNumber;         // Block number which contains revision 0.
        address owner;              // Who owns this blob.
    }

    mapping (bytes32 => BlobInfo) blobInfo;
    mapping (bytes32 => mapping (uint => bytes32)) packedBlockNumbers;
    mapping (bytes32 => mapping (address => bool)) enabledTransfers;

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    /**
     * @dev A blob revision has been published.
     * @param id Id of the blob.
     * @param revisionId Id of the revision (the highest at time of logging).
     * @param blob Contents of the blob.
     */
    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);

    /**
     * @dev A revision has been retracted.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     */
    event logRetractRevision(bytes32 indexed id, uint revisionId);

    /**
     * @dev An entire blob has been retracted. This cannot be undone.
     * @param id Id of the blob.
     */
    event logRetract(bytes32 indexed id);

    /**
     * @dev A blob has been transfered to a new address.
     * @param id Id of the blob.
     * @param recipient The address that now owns the blob.
     */
    event logTransfer(bytes32 indexed id, address recipient);

    /**
     * @dev A blob has been disowned. This cannot be undone.
     * @param id Id of the blob.
     */
    event logDisown(bytes32 indexed id);

    /**
     * @dev A blob has been set as not updatable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotUpdatable(bytes32 indexed id);

    /**
     * @dev A blob has been set as enforcing revisions. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetEnforceRevisions(bytes32 indexed id);

    /**
     * @dev A blob has been set as not retractable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotRetractable(bytes32 indexed id);

    /**
     * @dev A blob has been set as not transferable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotTransferable(bytes32 indexed id);

    /**
     * @dev Throw if the blob has not been used before or it has been retracted.
     * @param id Id of the blob.
     */
    modifier exists(bytes32 id) {
        BlobInfo info = blobInfo[id];
        if (info.blockNumber == 0 || info.blockNumber == uint32(-1)) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the owner of the blob is not the message sender.
     * @param id Id of the blob.
     */
    modifier isOwner(bytes32 id) {
        if (blobInfo[id].owner != msg.sender) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not updatable.
     * @param id Id of the blob.
     */
    modifier isUpdatable(bytes32 id) {
        if (!blobInfo[id].updatable) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not enforcing revisions.
     * @param id Id of the blob.
     */
    modifier isNotEnforceRevisions(bytes32 id) {
        if (blobInfo[id].enforceRevisions) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw is the blob is not retractable.
     * @param id Id of the blob.
     */
    modifier isRetractable(bytes32 id) {
        if (!blobInfo[id].retractable) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not transferable.
     * @param id Id of the blob.
     */
    modifier isTransferable(bytes32 id) {
        if (!blobInfo[id].transferable) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not transferable to a specific user.
     * @param id Id of the blob.
     * @param recipient Address of the user.
     */
    modifier isTransferEnabled(bytes32 id, address recipient) {
        if (!enabledTransfers[id][recipient]) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob only has one revision.
     * @param id Id of the blob.
     */
    modifier hasAdditionalRevisions(bytes32 id) {
        if (blobInfo[id].revisionCount < 2) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if a specific blob revision does not exist.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     */
    modifier revisionExists(bytes32 id, uint revisionId) {
        if (revisionId >= blobInfo[id].revisionCount) {
            throw;
        }
        _;
    }

    /**
     * @dev Stores new blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @param nonce Any value that the user has not used previously to create a blob.
     * @param updatable True if the blob should be updatable.
     * @param enforceRevisions True if the blob should enforce revisions.
     * @param retractable True if the blob should be retractable.
     * @param transferable True if the blob should be transferable.
     * @param anon True if the blob should be anonymous.
     * @return id Id of the blob.
     */
    function create(bytes blob, bytes32 nonce, bool updatable, bool enforceRevisions, bool retractable, bool transferable, bool anon) external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (blobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        blobInfo[id] = BlobInfo({
            updatable: updatable,
            enforceRevisions: enforceRevisions,
            retractable: retractable,
            transferable: transferable,
            revisionCount: 1,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Store a blob revision block number in a packed slot.
     * @param id Id of the blob.
     * @param offset The offset of the block number should be retreived.
     */
    function _setPackedBlockNumber(bytes32 id, uint offset) internal {
        // Get the slot.
        bytes32 slot = packedBlockNumbers[id][offset / 8];
        // Wipe the previous block number.
        slot &= ~bytes32(uint32(-1) * 2 ** ((offset % 8) * 32));
        // Insert the current block number.
        slot |= bytes32(uint32(block.number) * 2 ** ((offset % 8) * 32));
        // Store the slot.
        packedBlockNumbers[id][offset / 8] = slot;
    }

    /**
     * @dev Create a new blob revision.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the new revision. Typically a VCDIFF of an earlier revision.
     * @return revisionId The new revisionId.
     */
    function createNewRevision(bytes32 id, bytes blob) isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        // Increment the number of revisions.
        revisionId = blobInfo[id].revisionCount++;
        // Store the block number.
        _setPackedBlockNumber(id, revisionId - 1);
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Update a blob's latest revision.
     * @param id Id of the blob.
     * @param blob Blob that should replace the latest revision. Typically a VCDIFF if there is an earlier revision.
     */
    function updateLatestRevision(bytes32 id, bytes blob) isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        BlobInfo info = blobInfo[id];
        uint revisionId = info.revisionCount - 1;
        // Update the block number.
        if (revisionId == 0) {
            info.blockNumber = uint32(block.number);
        }
        else {
            _setPackedBlockNumber(id, revisionId - 1);
        }
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Retract a blob's latest revision. Revision 0 cannot be retracted.
     * @param id Id of the blob.
     */
    function retractLatestRevision(bytes32 id) isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) hasAdditionalRevisions(id) external {
        uint revisionId = --blobInfo[id].revisionCount;
        // Delete the slot if it is no longer required.
        if (revisionId % 8 == 1) {
            delete packedBlockNumbers[id][revisionId / 8];
        }
        // Log the retraction.
        logRetractRevision(id, revisionId);
    }

    /**
     * @dev Delete all of a blob's packed revision block numbers.
     * @param id Id of the blob.
     */
    function _deleteAllPackedRevisionBlockNumbers(bytes32 id) internal {
        // Determine how many slots should be deleted.
        // Block number of the first revision is stored in the blob info, so the first slot only needs to be deleted of there are at least 2 revisions.
        uint slotCount = (blobInfo[id].revisionCount + 6) / 8;
        // Delete the slots.
        for (uint i = 0; i < slotCount; i++) {
            delete packedBlockNumbers[id][i];
        }
    }

    /**
     * @dev Delete all a blob's revisions and replace it with a new blob.
     * @param id Id of the blob.
     * @param blob Blob that should be stored.
     */
    function restart(bytes32 id, bytes blob) isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        // Delete the packed revision block numbers.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Update the blob state info.
        BlobInfo info = blobInfo[id];
        info.revisionCount = 1;
        info.blockNumber = uint32(block.number);
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Retract a blob.
     * @param id Id of the blob. This id can never be used again.
     */
    function retract(bytes32 id) isOwner(id) isRetractable(id) external {
        // Delete the packed revision block numbers.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Mark this blob as retracted.
        blobInfo[id] = BlobInfo({
            updatable: false,
            enforceRevisions: false,
            retractable: false,
            transferable: false,
            revisionCount: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    /**
     * @dev Enable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferEnable(bytes32 id) isTransferable(id) external {
        // Record in state that the current user will accept this blob.
        enabledTransfers[id][msg.sender] = true;
    }

    /**
     * @dev Disable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferDisable(bytes32 id) isTransferEnabled(id, msg.sender) external {
        // Record in state that the current user will not accept this blob.
        enabledTransfers[id][msg.sender] = false;
    }

    /**
     * @dev Transfer a blob to a new user.
     * @param id Id of the blob.
     * @param recipient Address of the user to transfer to blob to.
     */
    function transfer(bytes32 id, address recipient) isOwner(id) isTransferable(id) isTransferEnabled(id, recipient) external {
        // Update ownership of the blob.
        blobInfo[id].owner = recipient;
        // Disable this transfer in future and free up the slot.
        enabledTransfers[id][recipient] = false;
        // Log the transfer.
        logTransfer(id, recipient);
    }

    /**
     * @dev Disown a blob.
     * @param id Id of the blob.
     */
    function disown(bytes32 id) isOwner(id) isTransferable(id) external {
        // Remove the owner from the blob's state.
        delete blobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    /**
     * @dev Set a blob as not updatable.
     * @param id Id of the blob.
     */
    function setNotUpdatable(bytes32 id) isOwner(id) external {
        // Record in state that the blob is not updatable.
        blobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    /**
     * @dev Set a blob to enforce revisions.
     * @param id Id of the blob.
     */
    function setEnforceRevisions(bytes32 id) isOwner(id) external {
        // Record in state that all changes to this blob must be new revisions.
        blobInfo[id].enforceRevisions = true;
        // Log that the blob now forces new revisions.
        logSetEnforceRevisions(id);
    }

    /**
     * @dev Set a blob to not be retractable.
     * @param id Id of the blob.
     */
    function setNotRetractable(bytes32 id) isOwner(id) external {
        // Record in state that the blob is not retractable.
        blobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    /**
     * @dev Set a blob to not be transferable.
     * @param id Id of the blob.
     */
    function setNotTransferable(bytes32 id) isOwner(id) external {
        // Record in state that the blob is not transferable.
        blobInfo[id].transferable = false;
        // Log that the blob is not transferable.
        logSetNotTransferable(id);
    }

    /**
     * @dev Get the id for this BlobStore contract.
     * @return Id of the contract.
     */
    function getContractId() constant external returns (bytes12) {
        return contractId;
    }

    /**
     * @dev Check if a blob exists.
     * @param id Id of the blob.
     * @return exists True if the blob exists.
     */
    function getExists(bytes32 id) constant external returns (bool exists) {
        BlobInfo info = blobInfo[id];
        exists = info.blockNumber != 0 && info.blockNumber != uint32(-1);
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function _getRevisionBlockNumber(bytes32 id, uint revisionId) internal returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = blobInfo[id].blockNumber;
        }
        else {
            bytes32 slot = packedBlockNumbers[id][(revisionId - 1) / 8];
            blockNumber = uint32(uint256(slot) / 2 ** (((revisionId - 1) % 8) * 32));
        }
    }

    /**
     * @dev Get the block numbers for all of a blob's revisions.
     * @param id Id of the blob.
     * @return blockNumbers Revision block numbers.
     */
    function _getAllRevisionBlockNumbers(bytes32 id) internal returns (uint[] blockNumbers) {
        uint revisionCount = blobInfo[id].revisionCount;
        blockNumbers = new uint[](revisionCount);
        for (uint revisionId = 0; revisionId < revisionCount; revisionId++) {
            blockNumbers[revisionId] = _getRevisionBlockNumber(id, revisionId);
        }
    }

    /**
     * @dev Get info about a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     * @return revisionCount How many revisions the blob has.
     * @return blockNumbers The block numbers of the revisions.
     * @return updatable Is the blob updatable?
     * @return enforceRevisions Does the blob enforce revisions?
     * @return retractable Is the blob retractable?
     * @return transferable Is the blob transferable?
     */
    function getInfo(bytes32 id) exists(id) constant external returns (address owner, uint revisionCount, uint[] blockNumbers, bool updatable, bool enforceRevisions, bool retractable, bool transferable) {
        BlobInfo info = blobInfo[id];
        owner = info.owner;
        revisionCount = info.revisionCount;
        blockNumbers = _getAllRevisionBlockNumbers(id);
        updatable = info.updatable;
        enforceRevisions = info.enforceRevisions;
        retractable = info.retractable;
        transferable = info.transferable;
    }

    /**
     * @dev Get the owner of a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     */
    function getOwner(bytes32 id) exists(id) constant external returns (address owner) {
        owner = blobInfo[id].owner;
    }

    /**
     * @dev Get the number of revisions a blob has.
     * @param id Id of the blob.
     * @return revisionCount How many revisions the blob has.
     */
    function getRevisionCount(bytes32 id) exists(id) constant external returns (uint revisionCount) {
        revisionCount = blobInfo[id].revisionCount;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function getRevisionBlockNumber(bytes32 id, uint revisionId) constant external returns (uint blockNumber) {
        blockNumber = _getRevisionBlockNumber(id, revisionId);
    }

    /**
     * @dev Get the block numbers for all of a blob's revisions.
     * @param id Id of the blob.
     * @return blockNumbers Revision block numbers.
     */
    function getAllRevisionBlockNumbers(bytes32 id) exists(id) constant external returns (uint[] blockNumbers) {
        blockNumbers = _getAllRevisionBlockNumbers(id);
    }

    /**
     * @dev Determine if a blob is updatable.
     * @param id Id of the blob.
     * @return updatable True if the blob is updatable.
     */
    function getUpdatable(bytes32 id) exists(id) constant external returns (bool updatable) {
        updatable = blobInfo[id].updatable;
    }

    /**
     * @dev Determine if a blob enforces revisions.
     * @param id Id of the blob.
     * @return enforceRevisions True if the blob enforces revisions.
     */
    function getEnforceRevisions(bytes32 id) exists(id) constant external returns (bool enforceRevisions) {
        enforceRevisions = blobInfo[id].enforceRevisions;
    }

    /**
     * @dev Determine if a blob is retractable.
     * @param id Id of the blob.
     * @return retractable True if the blob is blob retractable.
     */
    function getRetractable(bytes32 id) exists(id) constant external returns (bool retractable) {
        retractable = blobInfo[id].retractable;
    }

    /**
     * @dev Determine if a blob is transferable.
     * @param id Id of the blob.
     * @return transferable True if the blob is transferable.
     */
    function getTransferable(bytes32 id) exists(id) constant external returns (bool transferable) {
        transferable = blobInfo[id].transferable;
    }

}

pragma solidity ^0.4.0;

import "AbstractBlobStore.sol";

/**
 * @title BlobStore
 * @author Jonathan Brown <jbrown@bluedroplet.com>
 */
contract BlobStore is AbstractBlobStore {

    struct BlobInfo {               // Single slot.
        bool updatable;             // True if the blob is updatable. After creation can only be disabled.
        bool enforceRevisions;      // True if the blob is enforcing revisions. After creation can only be enabled.
        bool retractable;           // True if the blob can be retracted. After creation can only be disabled.
        bool transferable;          // True if the blob be transfered to another user or disowned. After creation can only be disabled.
        uint32 revisionCount;       // Number of revisions including revision 0.
        uint32 blockNumber;         // Block number which contains revision 0.
        address owner;              // Who owns this blob.
    }

    mapping (bytes32 => BlobInfo) blobInfo;
    mapping (bytes32 => mapping (uint => bytes32)) packedBlockNumbers;
    mapping (bytes32 => mapping (address => bool)) enabledTransfers;

    // Create a 96-bit id for this contract. This is unique across all blockchains.
    // Wait a few minutes after deploying for this id to settle.
    bytes12 contractId = bytes12(sha3(this, block.blockhash(block.number - 1)));

    /**
     * @dev A blob revision has been published.
     * @param id Id of the blob.
     * @param revisionId Id of the revision (the highest at time of logging).
     * @param blob Contents of the blob.
     */
    event logBlob(bytes32 indexed id, uint indexed revisionId, bytes blob);

    /**
     * @dev A revision has been retracted.
     * @param revisionId Id of the revision.
     */
    event logRetractRevision(bytes32 indexed id, uint revisionId);

    /**
     * @dev An entire blob has been retracted. This cannot be undone.
     * @param id Id of the blob.
     */
    event logRetract(bytes32 indexed id);

    /**
     * @dev A blob has been transfered to a new address.
     * @param id Id of the blob.
     * @param recipient The address that now owns the blob.
     */
    event logTransfer(bytes32 indexed id, address recipient);

    /**
     * @dev A blob has been disowned. This cannot be undone.
     * @param id Id of the blob.
     */
    event logDisown(bytes32 indexed id);

    /**
     * @dev A blob has been set as not updatable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotUpdatable(bytes32 indexed id);

    /**
     * @dev A blob has been set as enforcing revisions. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetEnforceRevisions(bytes32 indexed id);

    /**
     * @dev A blob has been set as not retractable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotRetractable(bytes32 indexed id);

    /**
     * @dev A blob has been set as not transferable. This cannot be undone.
     * @param id Id of the blob.
     */
    event logSetNotTransferable(bytes32 indexed id);

    /**
     * @dev Throw if the blob has not been used before or it has been retracted.
     * @param id Id of the blob.
     */
    modifier exists(bytes32 id) {
        BlobInfo info = blobInfo[id];
        if (info.blockNumber == 0 || info.blockNumber == uint32(-1)) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the owner of the blob is not the message sender.
     * @param id Id of the blob.
     */
    modifier isOwner(bytes32 id) {
        if (blobInfo[id].owner != msg.sender) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not updatable.
     * @param id Id of the blob.
     */
    modifier isUpdatable(bytes32 id) {
        if (!blobInfo[id].updatable) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not enforcing revisions.
     * @param id Id of the blob.
     */
    modifier isNotEnforceRevisions(bytes32 id) {
        if (blobInfo[id].enforceRevisions) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw is the blob is not retractable.
     * @param id Id of the blob.
     */
    modifier isRetractable(bytes32 id) {
        if (!blobInfo[id].retractable) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not transferable.
     * @param id Id of the blob.
     */
    modifier isTransferable(bytes32 id) {
        if (!blobInfo[id].transferable) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob is not transferable to a specific user.
     * @param id Id of the blob.
     * @param recipient Address of the user.
     */
    modifier isTransferEnabled(bytes32 id, address recipient) {
        if (!enabledTransfers[id][recipient]) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if the blob only has one revision.
     * @param id Id of the blob.
     */
    modifier hasAdditionalRevisions(bytes32 id) {
        if (blobInfo[id].revisionCount < 2) {
            throw;
        }
        _;
    }

    /**
     * @dev Throw if a specific blob revision does not exist.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     */
    modifier revisionExists(bytes32 id, uint revisionId) {
        if (revisionId >= blobInfo[id].revisionCount) {
            throw;
        }
        _;
    }

    /**
     * @dev Stores new blob in the transaction log. It is guaranteed that each user will get a different id from the same nonce.
     * @param blob Blob that should be stored.
     * @param nonce Any value that the user has not used previously to create a blob.
     * @param updatable True if the blob should be updatable.
     * @param enforceRevisions True if the blob should enforce revisions.
     * @param retractable True if the blob should be retractable.
     * @param transferable True if the blob should be transferable.
     * @param anon True if the blob should be anonymous.
     * @return id Id of the blob.
     */
    function create(bytes blob, bytes32 nonce, bool updatable, bool enforceRevisions, bool retractable, bool transferable, bool anon) external returns (bytes32 id) {
        // Determine the id.
        id = contractId | (sha3(msg.sender, nonce) & (2 ** 160 - 1));
        // Make sure this id has not been used before.
        if (blobInfo[id].blockNumber != 0) {
            throw;
        }
        // Store blob info in state.
        blobInfo[id] = BlobInfo({
            updatable: updatable,
            enforceRevisions: enforceRevisions,
            retractable: retractable,
            transferable: transferable,
            revisionCount: 1,
            blockNumber: uint32(block.number),
            owner: anon ? 0 : msg.sender,
        });
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Store a blob revision block number in a packed slot.
     * @param id Id of the blob.
     * @param offset The offset of the block number should be retreived.
     */
    function _setPackedBlockNumber(bytes32 id, uint offset) internal {
        // Get the slot.
        bytes32 slot = packedBlockNumbers[id][offset / 8];
        // Wipe the previous block number.
        slot &= ~bytes32(uint32(-1) * 2 ** ((offset % 8) * 32));
        // Insert the current block number.
        slot |= bytes32(uint32(block.number) * 2 ** ((offset % 8) * 32));
        // Store the slot.
        packedBlockNumbers[id][offset / 8] = slot;
    }

    /**
     * @dev Create a new blob revision.
     * @param id Id of the blob.
     * @param blob Blob that should be stored as the new revision. Typically a VCDIFF of an earlier revision.
     * @return revisionId The new revisionId.
     */
    function createNewRevision(bytes32 id, bytes blob) isOwner(id) isUpdatable(id) external returns (uint revisionId) {
        // Increment the number of revisions.
        revisionId = blobInfo[id].revisionCount++;
        // Store the block number.
        _setPackedBlockNumber(id, revisionId - 1);
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Update a blob's latest revision.
     * @param id Id of the blob.
     * @param blob Blob that should replace the latest revision. Typically a VCDIFF if there is an earlier revision.
     */
    function updateLatestRevision(bytes32 id, bytes blob) isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        BlobInfo info = blobInfo[id];
        uint revisionId = info.revisionCount - 1;
        // Update the block number.
        if (revisionId == 0) {
            info.blockNumber = uint32(block.number);
        }
        else {
            _setPackedBlockNumber(id, revisionId - 1);
        }
        // Store the new blob in a log in the current block.
        logBlob(id, revisionId, blob);
    }

    /**
     * @dev Retract a blob's latest revision. Revision 0 cannot be retracted.
     * @param id Id of the blob.
     */
    function retractLatestRevision(bytes32 id) isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) hasAdditionalRevisions(id) external {
        uint revisionId = --blobInfo[id].revisionCount;
        // Delete the slot if it is no longer required.
        if (revisionId % 8 == 1) {
            delete packedBlockNumbers[id][revisionId / 8];
        }
        // Log the retraction.
        logRetractRevision(id, revisionId);
    }

    /**
     * @dev Delete all of a blob's packed revision block numbers.
     * @param id Id of the blob.
     */
    function _deleteAllPackedRevisionBlockNumbers(bytes32 id) internal {
        // Determine how many slots should be deleted.
        // Block number of the first revision is stored in the blob info, so the first slot only needs to be deleted of there are at least 2 revisions.
        uint slotCount = (blobInfo[id].revisionCount + 6) / 8;
        // Delete the slots.
        for (uint i = 0; i < slotCount; i++) {
            delete packedBlockNumbers[id][i];
        }
    }

    /**
     * @dev Delete all a blob's revisions and replace it with a new blob.
     * @param id Id of the blob.
     * @param blob Blob that should be stored.
     */
    function restart(bytes32 id, bytes blob) isOwner(id) isUpdatable(id) isNotEnforceRevisions(id) external {
        // Delete the packed revision block numbers.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Update the blob state info.
        BlobInfo info = blobInfo[id];
        info.revisionCount = 1;
        info.blockNumber = uint32(block.number);
        // Store the blob in a log in the current block.
        logBlob(id, 0, blob);
    }

    /**
     * @dev Retract a blob.
     * @param id Id of the blob. This id can never be used again.
     */
    function retract(bytes32 id) isOwner(id) isRetractable(id) external {
        // Delete the packed revision block numbers.
        _deleteAllPackedRevisionBlockNumbers(id);
        // Mark this blob as retracted.
        blobInfo[id] = BlobInfo({
            updatable: false,
            enforceRevisions: false,
            retractable: false,
            transferable: false,
            revisionCount: 0,
            blockNumber: uint32(-1),
            owner: 0,
        });
        // Log that the blob has been retracted.
        logRetract(id);
    }

    /**
     * @dev Enable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferEnable(bytes32 id) isTransferable(id) external {
        // Record in state that the current user will accept this blob.
        enabledTransfers[id][msg.sender] = true;
    }

    /**
     * @dev Disable transfer of the blob to the current user.
     * @param id Id of the blob.
     */
    function transferDisable(bytes32 id) isTransferEnabled(id, msg.sender) external {
        // Record in state that the current user will not accept this blob.
        enabledTransfers[id][msg.sender] = false;
    }

    /**
     * @dev Transfer a blob to a new user.
     * @param id Id of the blob.
     * @param recipient Address of the user to transfer to blob to.
     */
    function transfer(bytes32 id, address recipient) isOwner(id) isTransferable(id) isTransferEnabled(id, recipient) external {
        // Update ownership of the blob.
        blobInfo[id].owner = recipient;
        // Disable this transfer in future and free up the slot.
        enabledTransfers[id][recipient] = false;
        // Log the transfer.
        logTransfer(id, recipient);
    }

    /**
     * @dev Disown a blob.
     * @param id Id of the blob.
     */
    function disown(bytes32 id) isOwner(id) isTransferable(id) external {
        // Remove the owner from the blob's state.
        delete blobInfo[id].owner;
        // Log as blob as disowned.
        logDisown(id);
    }

    /**
     * @dev Set a blob as not updatable.
     * @param id Id of the blob.
     */
    function setNotUpdatable(bytes32 id) isOwner(id) external {
        // Record in state that the blob is not updatable.
        blobInfo[id].updatable = false;
        // Log that the blob is not updatable.
        logSetNotUpdatable(id);
    }

    /**
     * @dev Set a blob to enforce revisions.
     * @param id Id of the blob.
     */
    function setEnforceRevisions(bytes32 id) isOwner(id) external {
        // Record in state that all changes to this blob must be new revisions.
        blobInfo[id].enforceRevisions = true;
        // Log that the blob now forces new revisions.
        logSetEnforceRevisions(id);
    }

    /**
     * @dev Set a blob to not be retractable.
     * @param id Id of the blob.
     */
    function setNotRetractable(bytes32 id) isOwner(id) external {
        // Record in state that the blob is not retractable.
        blobInfo[id].retractable = false;
        // Log that the blob is not retractable.
        logSetNotRetractable(id);
    }

    /**
     * @dev Set a blob to not be transferable.
     * @param id Id of the blob.
     */
    function setNotTransferable(bytes32 id) isOwner(id) external {
        // Record in state that the blob is not transferable.
        blobInfo[id].transferable = false;
        // Log that the blob is not transferable.
        logSetNotTransferable(id);
    }

    /**
     * @dev Get the id for this BlobStore contract.
     * @return Id of the contract.
     */
    function getContractId() constant external returns (bytes12) {
        return contractId;
    }

    /**
     * @dev Check if a blob exists.
     * @param id Id of the blob.
     * @return exists True if the blob exists.
     */
    function getExists(bytes32 id) constant external returns (bool exists) {
        BlobInfo info = blobInfo[id];
        exists = info.blockNumber != 0 && info.blockNumber != uint32(-1);
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function _getRevisionBlockNumber(bytes32 id, uint revisionId) internal returns (uint blockNumber) {
        if (revisionId == 0) {
            blockNumber = blobInfo[id].blockNumber;
        }
        else {
            bytes32 slot = packedBlockNumbers[id][(revisionId - 1) / 8];
            blockNumber = uint32(uint256(slot) / 2 ** (((revisionId - 1) % 8) * 32));
        }
    }

    /**
     * @dev Get the block numbers for all of a blob's revisions.
     * @param id Id of the blob.
     * @return blockNumbers Revision block numbers.
     */
    function _getAllRevisionBlockNumbers(bytes32 id) internal returns (uint[] blockNumbers) {
        uint revisionCount = blobInfo[id].revisionCount;
        blockNumbers = new uint[](revisionCount);
        for (uint revisionId = 0; revisionId < revisionCount; revisionId++) {
            blockNumbers[revisionId] = _getRevisionBlockNumber(id, revisionId);
        }
    }

    /**
     * @dev Get info about a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     * @return revisionCount How many revisions the blob has.
     * @return blockNumbers The block numbers of the revisions.
     * @return updatable Is the blob updatable?
     * @return enforceRevisions Does the blob enforce revisions?
     * @return retractable Is the blob retractable?
     * @return transferable Is the blob transferable?
     */
    function getInfo(bytes32 id) exists(id) constant external returns (address owner, uint revisionCount, uint[] blockNumbers, bool updatable, bool enforceRevisions, bool retractable, bool transferable) {
        BlobInfo info = blobInfo[id];
        owner = info.owner;
        revisionCount = info.revisionCount;
        blockNumbers = _getAllRevisionBlockNumbers(id);
        updatable = info.updatable;
        enforceRevisions = info.enforceRevisions;
        retractable = info.retractable;
        transferable = info.transferable;
    }

    /**
     * @dev Get the owner of a blob.
     * @param id Id of the blob.
     * @return owner Owner of the blob.
     */
    function getOwner(bytes32 id) exists(id) constant external returns (address owner) {
        owner = blobInfo[id].owner;
    }

    /**
     * @dev Get the number of revisions a blob has.
     * @param id Id of the blob.
     * @return revisionCount How many revisions the blob has.
     */
    function getRevisionCount(bytes32 id) exists(id) constant external returns (uint revisionCount) {
        revisionCount = blobInfo[id].revisionCount;
    }

    /**
     * @dev Get the block number for a specific blob revision.
     * @param id Id of the blob.
     * @param revisionId Id of the revision.
     * @return blockNumber Block number of the specified revision.
     */
    function getRevisionBlockNumber(bytes32 id, uint revisionId) constant external returns (uint blockNumber) {
        blockNumber = _getRevisionBlockNumber(id, revisionId);
    }

    /**
     * @dev Get the block numbers for all of a blob's revisions.
     * @param id Id of the blob.
     * @return blockNumbers Revision block numbers.
     */
    function getAllRevisionBlockNumbers(bytes32 id) exists(id) constant external returns (uint[] blockNumbers) {
        blockNumbers = _getAllRevisionBlockNumbers(id);
    }

    /**
     * @dev Determine if a blob is updatable.
     * @param id Id of the blob.
     * @return updatable True if the blob is updatable.
     */
    function getUpdatable(bytes32 id) exists(id) constant external returns (bool updatable) {
        updatable = blobInfo[id].updatable;
    }

    /**
     * @dev Determine if a blob enforces revisions.
     * @param id Id of the blob.
     * @return enforceRevisions True if the blob enforces revisions.
     */
    function getEnforceRevisions(bytes32 id) exists(id) constant external returns (bool enforceRevisions) {
        enforceRevisions = blobInfo[id].enforceRevisions;
    }

    /**
     * @dev Determine if a blob is retractable.
     * @param id Id of the blob.
     * @return retractable True if the blob is blob retractable.
     */
    function getRetractable(bytes32 id) exists(id) constant external returns (bool retractable) {
        retractable = blobInfo[id].retractable;
    }

    /**
     * @dev Determine if a blob is transferable.
     * @param id Id of the blob.
     * @return transferable True if the blob is transferable.
     */
    function getTransferable(bytes32 id) exists(id) constant external returns (bool transferable) {
        transferable = blobInfo[id].transferable;
    }

}


data type change to bytes

data type change to bytes

pragma solidity ^0.4.0;
contract webServer {
  struct pageData{
    address owner;
    bytes data;
  }

  mapping(bytes32 => mapping(bytes32 => pageData)) public pages;
  //event RegisterEvent(address owner, string data);

  function set(bytes32 domain, bytes32 name, bytes data) returns (bool result){
    if (pages[domain][name].owner != 0) {
        if (pages[domain][name].owner != msg.sender) {
            return false;
        }
    }
    pages[domain][name].owner = msg.sender;
    pages[domain][name].data=data;
    return true;
    //RegisterEvent(msg.sender, data);
  }

  function get(bytes32 domain, bytes32 name) constant returns (bytes data){
    return pages[domain][name].data;
  }
}

pragma solidity ^0.4.0;
contract webServer {
  struct pageData{
    address owner;
    bytes32[] data;
  }

  mapping(bytes32 => mapping(bytes32 => pageData)) public pages;
  //event RegisterEvent(address owner, string data);

  function set(bytes32 domain, bytes32 name, bytes32 data) returns (bool result){
    if (pages[domain][name].owner != 0) {
        if (pages[domain][name].owner != msg.sender) {
            return false;
        }
    }
    pages[domain][name].owner = msg.sender;
    pages[domain][name].data.push(data);
    return true;
    //RegisterEvent(msg.sender, data);
  }

  function get(bytes32 domain, bytes32 name) constant returns (bytes32[] data){
    return pages[domain][name].data;
  }
  function getlen(bytes32 domain, bytes32 name) constant returns (uint leng){
    return pages[domain][name].data.length;
  }
}


Added BuilderShareSale Ethereum testnet address

//
// AIRA Builder for ShareSale contract
//
// Ethereum address:
//  - Testnet: 0x56c58efbf174dc82b4311a68b84bdfd5db13a3db
//

import 'creator/CreatorShareSale.sol';
import './Builder.sol';

/**
 * @title ShareSale contract builder
 */
contract BuilderShareSale is Builder {
    function BuilderShareSale(uint _buildingCost, address _cashflow, address _proposal)
             Builder(_buildingCost, _cashflow, _proposal)
    {}

    /**
     * @dev Run script creation contract
     * @param _cashflow is Cashflow address
     * @param _price_wei is price of one share in wei
     * @return address new contract
     */
    function create(address _cashflow, uint _price_wei) returns (address) {
        var inst = CreatorShareSale.create(_cashflow, _price_wei);
        Owned(inst).delegate(msg.sender);

        deal(inst);
        return inst;
    }
}

//
// AIRA Builder for ShareSale contract
//
// Ethereum address:
//  - Testnet:
//

import 'creator/CreatorShareSale.sol';
import './Builder.sol';

/**
 * @title ShareSale contract builder
 */
contract BuilderShareSale is Builder {
    function BuilderShareSale(uint _buildingCost, address _cashflow, address _proposal)
             Builder(_buildingCost, _cashflow, _proposal)
    {}

    /**
     * @dev Run script creation contract
     * @param _cashflow is Cashflow address
     * @param _price_wei is price of one share in wei
     * @return address new contract
     */
    function create(address _cashflow, uint _price_wei) returns (address) {
        var inst = CreatorShareSale.create(_cashflow, _price_wei);
        Owned(inst).delegate(msg.sender);

        deal(inst);
        return inst;
    }
}