Commit 885b0e50 by Aaron Leung

Trying out different node structure and allocation strategy.

parent 8452dd3c
#include <cstring>
#include "node_impl.hpp"
namespace Sass {
// ------------------------------------------------------------------------
// Token method implementations
// ------------------------------------------------------------------------
inline size_t Token::length() const
{ return end - begin; }
inline string Token::to_string() const
{ return string(begin, end - begin); }
inline Token::operator bool()
{ return begin && end && begin >= end; }
// Need Token::make(...) because tokens are union members, and hence they
// can't have user-implemented default and copy constructors.
inline Token Token::make()
{
Token t;
t.begin = 0;
t.end = 0;
return t;
}
inline Token Token::make(const char* s)
{
Token t;
t.begin = s;
t.end = s + std::strlen(s);
return t;
}
inline Token Token::make(const char* b, const char* e)
{
Token t;
t.begin = b;
t.end = e;
return t;
}
string Token::unquote() const
{
string result;
const char* p = begin;
if (*begin == '\'' || *begin == '"') {
++p;
while (p < end) {
if (*p == '\\') {
switch (*(++p)) {
case 'n': result += '\n'; break;
case 't': result += '\t'; break;
case 'b': result += '\b'; break;
case 'r': result += '\r'; break;
case 'f': result += '\f'; break;
case 'v': result += '\v'; break;
case 'a': result += '\a'; break;
case '\\': result += '\\'; break;
default: result += *p; break;
}
}
else if (p == end - 1) {
return result;
}
else {
result += *p;
}
++p;
}
return result;
}
else {
while (p < end) {
result += *(p++);
}
return result;
}
}
void Token::unquote_to_stream(std::stringstream& buf) const
{
const char* p = begin;
if (*begin == '\'' || *begin == '"') {
++p;
while (p < end) {
if (*p == '\\') {
switch (*(++p)) {
case 'n': buf << '\n'; break;
case 't': buf << '\t'; break;
case 'b': buf << '\b'; break;
case 'r': buf << '\r'; break;
case 'f': buf << '\f'; break;
case 'v': buf << '\v'; break;
case 'a': buf << '\a'; break;
case '\\': buf << '\\'; break;
default: buf << *p; break;
}
}
else if (p == end - 1) {
return;
}
else {
buf << *p;
}
++p;
}
return;
}
else {
while (p < end) {
buf << *(p++);
}
return;
}
}
bool Token::operator<(const Token& rhs) const
{
const char* first1 = begin;
const char* last1 = end;
const char* first2 = rhs.begin;
const char* last2 = rhs.end;
while (first1!=last1)
{
if (first2==last2 || *first2<*first1) return false;
else if (*first1<*first2) return true;
first1++; first2++;
}
return (first2!=last2);
}
bool Token::operator==(const Token& rhs) const
{
if (length() != rhs.length()) return false;
if ((begin[0] == '"' || begin[0] == '\'') &&
(rhs.begin[0] == '"' || rhs.begin[0] == '\''))
{ return unquote() == rhs.unquote(); }
const char* p = begin;
const char* q = rhs.begin;
for (; p < end; ++p, ++q) if (*p != *q) return false;
return true;
}
// ------------------------------------------------------------------------
// Node_Impl method implementations
// ------------------------------------------------------------------------
inline bool Node_Impl::is_numeric()
{ return type >= number && type <= numeric_color; }
inline size_t Node_Impl::size()
{ return children.size(); }
inline Node& Node_Impl::at(size_t i)
{ return children.at(i); }
inline Node& Node_Impl::back()
{ return children.back(); }
inline void Node_Impl::push_back(const Node& n)
{ children.push_back(n); }
inline Node& Node_Impl::pop_back()
{ children.pop_back(); }
inline bool Node_Impl::boolean_value()
{ return value.boolean; }
inline double Node_Impl::numeric_value()
{
switch (type)
{
case number:
case numeric_percentage:
return value.numeric;
case numeric_dimension:
return value.dimension.numeric_value;
default:
break;
// throw an exception?
}
return 0;
}
inline string Node_Impl::unit()
{
switch (type)
{
case numeric_percentage: {
return "\"%\"";
} break;
case numeric_dimension: {
string result("\"");
result += value.dimension.unit.to_string();
result += "\"";
return result;
} break;
default: break;
}
return "\"\"";
}
}
\ No newline at end of file
#include <vector>
#include <sstream>
#ifndef SASS_NODE_TYPE_INCLUDED
#include "node_type.hpp"
#endif
#ifndef SASS_NODE_INCLUDED
#include "node_pimpl.hpp"
#endif
namespace Sass {
using namespace std;
struct Token {
const char* begin;
const char* end;
// Need Token::make(...) because tokens are union members, and hence they
// can't have user-implemented default and copy constructors.
static Token make();
static Token make(const char* s);
static Token make(const char* b, const char* e);
size_t length() const;
string to_string() const;
string unquote() const;
void unquote_to_stream(std::stringstream& buf) const;
bool operator<(const Token& rhs) const;
bool operator==(const Token& rhs) const;
operator bool();
};
struct Dimension {
double numeric_value;
Token unit;
};
struct Node_Impl {
union {
bool boolean;
double numeric;
Token token;
Dimension dimension;
} value;
vector<Node> children;
string* file_name;
size_t line_number;
Node_Type type;
bool has_children;
bool has_statements;
bool has_blocks;
bool has_expansions;
bool has_backref;
bool from_variable;
bool eval_me;
bool is_unquoted;
bool is_numeric();
size_t size();
Node& at(size_t i);
Node& back();
Node& pop_back();
void push_back(const Node& n);
bool boolean_value();
double numeric_value();
string unit();
};
}
\ No newline at end of file
#ifndef SASS_NODE_INCLUDED
#include "node_pimpl.hpp"
#endif
#include "node_impl.hpp"
namespace Sass {
using namespace std;
inline Node_Type Node::type() { return ip_->type; }
inline bool Node::has_children() { return ip_->has_children; }
inline bool Node::has_statements() { return ip_->has_statements; }
inline bool Node::has_blocks() { return ip_->has_blocks; }
inline bool Node::has_expansions() { return ip_->has_expansions; }
inline bool Node::has_backref() { return ip_->has_backref; }
inline bool Node::from_variable() { return ip_->from_variable; }
inline bool Node::eval_me() { return ip_->eval_me; }
inline bool Node::is_unquoted() { return ip_->is_unquoted; }
inline bool Node::is_numeric() { return ip_->is_numeric(); }
inline size_t Node::line_number() { return ip_->line_number; }
inline bool Node::has_children() { return ip_->has_children; }
inline bool Node::has_statements() { return ip_->has_statements; }
inline bool Node::has_blocks() { return ip_->has_blocks; }
inline bool Node::has_expansions() { return ip_->has_expansions; }
inline bool Node::has_backref() { return ip_->has_backref; }
inline bool Node::from_variable() { return ip_->from_variable; }
inline bool Node::eval_me() { return ip_->eval_me; }
inline bool Node::is_unquoted() { return ip_->is_unquoted; }
inline bool Node::is_numeric() { return ip_->is_numeric(); }
inline string Node::file_name() const { return *(ip_->file_name); }
inline size_t Node::line_number() const { return ip_->line_number; }
inline size_t Node::size() const { return ip_->size(); }
inline Node& Node::at(size_t i) const { return ip_->at(i); }
inline Node& Node::operator[](size_t i) const { return at(i); }
inline Node& Node::pop_back() { return ip_->pop_back(); }
inline Node& Node::push_back(Node n)
{
ip_->push_back(n);
return *this;
}
inline Node& Node::operator<<(Node n) { return push_back(n); }
inline Node& Node::operator+=(Node n)
{
for (size_t i = 0, L = n.size(); i < L; ++i) push_back(n[i]);
return *this;
}
inline bool Node::boolean_value() { return ip_->boolean_value(); }
inline double Node::numeric_value() { return ip_->numeric_value(); }
}
\ No newline at end of file
#define SASS_NODE_INCLUDED
#include <string>
#ifndef SASS_NODE_TYPE_INCLUDED
#include "node_type.hpp"
#endif
namespace Sass {
using namespace std;
class Node_Impl; // forward declaration
class Node {
......@@ -9,6 +17,8 @@ namespace Sass {
Node_Impl* ip_;
public:
Node_Type type();
bool has_children();
bool has_statements();
bool has_blocks();
......@@ -21,11 +31,16 @@ namespace Sass {
string file_name() const;
size_t line_number() const;
size_t size() const;
Node& at(size_t i) const;
Node& operator[](size_t i) const;
Node& pop_back();
Node& push_back(Node n);
Node& operator<<(Node n);
Node& operator+=(Node n);
Node_Impl& at(size_t i) const;
Node_Impl& operator[](size_t i) const;
Node_Impl& push_back(Node n);
Node_Impl& operator<<(Node n);
double numeric_value();
bool boolean_value();
};
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment