sassc 2.3.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +5 -0
  4. data/ext/libsass/VERSION +1 -1
  5. data/ext/libsass/include/sass/context.h +3 -0
  6. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  7. data/ext/libsass/src/ast.cpp +117 -117
  8. data/ext/libsass/src/ast.hpp +160 -162
  9. data/ext/libsass/src/ast_def_macros.hpp +10 -10
  10. data/ext/libsass/src/ast_fwd_decl.cpp +2 -2
  11. data/ext/libsass/src/ast_fwd_decl.hpp +61 -52
  12. data/ext/libsass/src/ast_helpers.hpp +5 -5
  13. data/ext/libsass/src/ast_sel_cmp.cpp +18 -18
  14. data/ext/libsass/src/ast_sel_super.cpp +52 -52
  15. data/ext/libsass/src/ast_sel_unify.cpp +16 -16
  16. data/ext/libsass/src/ast_sel_weave.cpp +62 -62
  17. data/ext/libsass/src/ast_selectors.cpp +87 -77
  18. data/ext/libsass/src/ast_selectors.hpp +72 -62
  19. data/ext/libsass/src/ast_supports.cpp +35 -35
  20. data/ext/libsass/src/ast_supports.hpp +29 -29
  21. data/ext/libsass/src/ast_values.cpp +58 -58
  22. data/ext/libsass/src/ast_values.hpp +75 -75
  23. data/ext/libsass/src/backtrace.cpp +9 -9
  24. data/ext/libsass/src/backtrace.hpp +5 -5
  25. data/ext/libsass/src/base64vlq.cpp +2 -2
  26. data/ext/libsass/src/base64vlq.hpp +1 -1
  27. data/ext/libsass/src/bind.cpp +17 -17
  28. data/ext/libsass/src/bind.hpp +1 -1
  29. data/ext/libsass/src/c2ast.cpp +3 -3
  30. data/ext/libsass/src/c2ast.hpp +1 -1
  31. data/ext/libsass/src/check_nesting.cpp +36 -36
  32. data/ext/libsass/src/check_nesting.hpp +2 -2
  33. data/ext/libsass/src/color_maps.cpp +5 -5
  34. data/ext/libsass/src/color_maps.hpp +1 -1
  35. data/ext/libsass/src/context.cpp +63 -60
  36. data/ext/libsass/src/context.hpp +33 -33
  37. data/ext/libsass/src/cssize.cpp +30 -29
  38. data/ext/libsass/src/cssize.hpp +13 -13
  39. data/ext/libsass/src/dart_helpers.hpp +5 -5
  40. data/ext/libsass/src/debugger.hpp +127 -128
  41. data/ext/libsass/src/emitter.cpp +12 -12
  42. data/ext/libsass/src/emitter.hpp +10 -10
  43. data/ext/libsass/src/environment.cpp +27 -27
  44. data/ext/libsass/src/environment.hpp +24 -24
  45. data/ext/libsass/src/error_handling.cpp +42 -42
  46. data/ext/libsass/src/error_handling.hpp +38 -50
  47. data/ext/libsass/src/eval.cpp +138 -132
  48. data/ext/libsass/src/eval.hpp +17 -17
  49. data/ext/libsass/src/eval_selectors.cpp +3 -3
  50. data/ext/libsass/src/expand.cpp +70 -64
  51. data/ext/libsass/src/expand.hpp +12 -12
  52. data/ext/libsass/src/extender.cpp +55 -53
  53. data/ext/libsass/src/extender.hpp +14 -14
  54. data/ext/libsass/src/file.cpp +66 -58
  55. data/ext/libsass/src/file.hpp +23 -25
  56. data/ext/libsass/src/fn_colors.cpp +9 -9
  57. data/ext/libsass/src/fn_lists.cpp +18 -18
  58. data/ext/libsass/src/fn_maps.cpp +3 -3
  59. data/ext/libsass/src/fn_miscs.cpp +15 -15
  60. data/ext/libsass/src/fn_numbers.cpp +7 -7
  61. data/ext/libsass/src/fn_selectors.cpp +8 -8
  62. data/ext/libsass/src/fn_strings.cpp +34 -22
  63. data/ext/libsass/src/fn_utils.cpp +29 -26
  64. data/ext/libsass/src/fn_utils.hpp +10 -10
  65. data/ext/libsass/src/inspect.cpp +35 -34
  66. data/ext/libsass/src/inspect.hpp +21 -21
  67. data/ext/libsass/src/lexer.cpp +3 -1
  68. data/ext/libsass/src/listize.cpp +2 -2
  69. data/ext/libsass/src/mapping.hpp +1 -0
  70. data/ext/libsass/src/memory.hpp +12 -0
  71. data/ext/libsass/src/memory/allocator.cpp +48 -0
  72. data/ext/libsass/src/memory/allocator.hpp +138 -0
  73. data/ext/libsass/src/memory/config.hpp +20 -0
  74. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  75. data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
  76. data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +18 -6
  77. data/ext/libsass/src/operation.hpp +44 -44
  78. data/ext/libsass/src/operators.cpp +18 -18
  79. data/ext/libsass/src/operators.hpp +11 -11
  80. data/ext/libsass/src/ordered_map.hpp +18 -18
  81. data/ext/libsass/src/output.cpp +16 -16
  82. data/ext/libsass/src/output.hpp +5 -5
  83. data/ext/libsass/src/parser.cpp +327 -345
  84. data/ext/libsass/src/parser.hpp +77 -87
  85. data/ext/libsass/src/parser_selectors.cpp +6 -6
  86. data/ext/libsass/src/permutate.hpp +39 -15
  87. data/ext/libsass/src/plugins.cpp +7 -7
  88. data/ext/libsass/src/plugins.hpp +8 -8
  89. data/ext/libsass/src/position.cpp +7 -26
  90. data/ext/libsass/src/position.hpp +44 -21
  91. data/ext/libsass/src/remove_placeholders.cpp +4 -4
  92. data/ext/libsass/src/remove_placeholders.hpp +3 -3
  93. data/ext/libsass/src/sass.cpp +16 -15
  94. data/ext/libsass/src/sass.hpp +9 -5
  95. data/ext/libsass/src/sass_context.cpp +52 -34
  96. data/ext/libsass/src/sass_values.cpp +8 -10
  97. data/ext/libsass/src/settings.hpp +19 -0
  98. data/ext/libsass/src/source.cpp +69 -0
  99. data/ext/libsass/src/source.hpp +95 -0
  100. data/ext/libsass/src/source_data.hpp +32 -0
  101. data/ext/libsass/src/source_map.cpp +22 -18
  102. data/ext/libsass/src/source_map.hpp +12 -9
  103. data/ext/libsass/src/units.cpp +19 -19
  104. data/ext/libsass/src/units.hpp +8 -8
  105. data/ext/libsass/src/utf8_string.cpp +9 -10
  106. data/ext/libsass/src/utf8_string.hpp +7 -6
  107. data/ext/libsass/src/util.cpp +38 -38
  108. data/ext/libsass/src/util.hpp +18 -18
  109. data/ext/libsass/src/util_string.cpp +13 -13
  110. data/ext/libsass/src/util_string.hpp +9 -8
  111. data/ext/libsass/src/values.cpp +12 -12
  112. data/lib/sassc/native.rb +3 -5
  113. data/lib/sassc/version.rb +1 -1
  114. data/test/native_test.rb +4 -4
  115. metadata +14 -5
  116. data/lib/sassc/native/lib_c.rb +0 -21
@@ -20,24 +20,24 @@ namespace Sass {
20
20
 
21
21
  // statements
22
22
  virtual void operator()(Block*);
23
- virtual void operator()(Ruleset*);
23
+ virtual void operator()(StyleRule*);
24
24
  virtual void operator()(Bubble*);
25
- virtual void operator()(Supports_Block*);
26
- virtual void operator()(At_Root_Block*);
27
- virtual void operator()(Directive*);
25
+ virtual void operator()(SupportsRule*);
26
+ virtual void operator()(AtRootRule*);
27
+ virtual void operator()(AtRule*);
28
28
  virtual void operator()(Keyframe_Rule*);
29
29
  virtual void operator()(Declaration*);
30
30
  virtual void operator()(Assignment*);
31
31
  virtual void operator()(Import*);
32
32
  virtual void operator()(Import_Stub*);
33
- virtual void operator()(Warning*);
34
- virtual void operator()(Error*);
35
- virtual void operator()(Debug*);
33
+ virtual void operator()(WarningRule*);
34
+ virtual void operator()(ErrorRule*);
35
+ virtual void operator()(DebugRule*);
36
36
  virtual void operator()(Comment*);
37
37
  virtual void operator()(If*);
38
- virtual void operator()(For*);
39
- virtual void operator()(Each*);
40
- virtual void operator()(While*);
38
+ virtual void operator()(ForRule*);
39
+ virtual void operator()(EachRule*);
40
+ virtual void operator()(WhileRule*);
41
41
  virtual void operator()(Return*);
42
42
  virtual void operator()(ExtendRule*);
43
43
  virtual void operator()(Definition*);
@@ -62,9 +62,9 @@ namespace Sass {
62
62
  virtual void operator()(String_Quoted*);
63
63
  virtual void operator()(Custom_Error*);
64
64
  virtual void operator()(Custom_Warning*);
65
- virtual void operator()(Supports_Operator*);
66
- virtual void operator()(Supports_Negation*);
67
- virtual void operator()(Supports_Declaration*);
65
+ virtual void operator()(SupportsOperation*);
66
+ virtual void operator()(SupportsNegation*);
67
+ virtual void operator()(SupportsDeclaration*);
68
68
  virtual void operator()(Supports_Interpolation*);
69
69
  virtual void operator()(MediaRule*);
70
70
  virtual void operator()(CssMediaRule*);
@@ -81,19 +81,19 @@ namespace Sass {
81
81
  virtual void operator()(Arguments*);
82
82
  // selectors
83
83
  virtual void operator()(Selector_Schema*);
84
- virtual void operator()(Placeholder_Selector*);
85
- virtual void operator()(Type_Selector*);
86
- virtual void operator()(Class_Selector*);
87
- virtual void operator()(Id_Selector*);
88
- virtual void operator()(Attribute_Selector*);
89
- virtual void operator()(Pseudo_Selector*);
84
+ virtual void operator()(PlaceholderSelector*);
85
+ virtual void operator()(TypeSelector*);
86
+ virtual void operator()(ClassSelector*);
87
+ virtual void operator()(IDSelector*);
88
+ virtual void operator()(AttributeSelector*);
89
+ virtual void operator()(PseudoSelector*);
90
90
  virtual void operator()(SelectorComponent*);
91
91
  virtual void operator()(SelectorCombinator*);
92
92
  virtual void operator()(CompoundSelector*);
93
93
  virtual void operator()(ComplexSelector*);
94
94
  virtual void operator()(SelectorList*);
95
- virtual std::string lbracket(List*);
96
- virtual std::string rbracket(List*);
95
+ virtual sass::string lbracket(List*);
96
+ virtual sass::string rbracket(List*);
97
97
 
98
98
  };
99
99
 
@@ -93,7 +93,9 @@ namespace Sass {
93
93
  const char* re_linebreak(const char* src)
94
94
  {
95
95
  // end of file or unix linefeed return here
96
- if (*src == 0 || *src == '\n' || *src == '\f') return src + 1;
96
+ if (*src == 0) return src;
97
+ // end of file or unix linefeed return here
98
+ if (*src == '\n' || *src == '\f') return src + 1;
97
99
  // a carriage return may optionally be followed by a linefeed
98
100
  if (*src == '\r') return *(src + 1) == '\n' ? src + 2 : src + 1;
99
101
  // no linefeed
@@ -36,7 +36,7 @@ namespace Sass {
36
36
 
37
37
  Expression* Listize::operator()(CompoundSelector* sel)
38
38
  {
39
- std::string str;
39
+ sass::string str;
40
40
  for (size_t i = 0, L = sel->length(); i < L; ++i) {
41
41
  Expression* e = (*sel)[i]->perform(this);
42
42
  if (e) str += e->to_string();
@@ -54,7 +54,7 @@ namespace Sass {
54
54
  for (auto component : sel->elements()) {
55
55
  if (CompoundSelectorObj compound = Cast<CompoundSelector>(component)) {
56
56
  if (!compound->empty()) {
57
- Expression_Obj hh = compound->perform(this);
57
+ ExpressionObj hh = compound->perform(this);
58
58
  if (hh) l->append(hh);
59
59
  }
60
60
  }
@@ -2,6 +2,7 @@
2
2
  #define SASS_MAPPING_H
3
3
 
4
4
  #include "position.hpp"
5
+ #include "backtrace.hpp"
5
6
 
6
7
  namespace Sass {
7
8
 
@@ -0,0 +1,12 @@
1
+ #ifndef SASS_MEMORY_H
2
+ #define SASS_MEMORY_H
3
+
4
+ #include "settings.hpp"
5
+
6
+ // Include memory headers
7
+ #include "memory/config.hpp"
8
+ #include "memory/allocator.hpp"
9
+ #include "memory/shared_ptr.hpp"
10
+ #include "memory/memory_pool.hpp"
11
+
12
+ #endif
@@ -0,0 +1,48 @@
1
+ #include "../sass.hpp"
2
+ #include "allocator.hpp"
3
+ #include "memory_pool.hpp"
4
+
5
+ #if defined (_MSC_VER) // Visual studio
6
+ #define thread_local __declspec( thread )
7
+ #elif defined (__GCC__) // GCC
8
+ #define thread_local __thread
9
+ #endif
10
+
11
+ namespace Sass {
12
+
13
+ #ifdef SASS_CUSTOM_ALLOCATOR
14
+
15
+ // Only use PODs for thread_local
16
+ // Objects get unpredictable init order
17
+ static thread_local MemoryPool* pool;
18
+ static thread_local size_t allocations;
19
+
20
+ void* allocateMem(size_t size)
21
+ {
22
+ if (pool == nullptr) {
23
+ pool = new MemoryPool();
24
+ }
25
+ allocations++;
26
+ return pool->allocate(size);
27
+ }
28
+
29
+ void deallocateMem(void* ptr, size_t size)
30
+ {
31
+
32
+ // It seems thread_local variable might be discharged!?
33
+ // But the destructors of e.g. static strings is still
34
+ // called, although their memory was discharged too.
35
+ // Fine with me as long as address sanitizer is happy.
36
+ if (pool == nullptr || allocations == 0) { return; }
37
+
38
+ pool->deallocate(ptr);
39
+ if (--allocations == 0) {
40
+ delete pool;
41
+ pool = nullptr;
42
+ }
43
+
44
+ }
45
+
46
+ #endif
47
+
48
+ }
@@ -0,0 +1,138 @@
1
+ #ifndef SASS_ALLOCATOR_H
2
+ #define SASS_ALLOCATOR_H
3
+
4
+ #include "config.hpp"
5
+ #include "../settings.hpp"
6
+ #include "../MurmurHash2.hpp"
7
+
8
+ #include <vector>
9
+ #include <limits>
10
+ #include <iostream>
11
+ #include <algorithm>
12
+ #include <functional>
13
+
14
+ namespace Sass {
15
+
16
+ #ifndef SASS_CUSTOM_ALLOCATOR
17
+
18
+ template <typename T> using Allocator = std::allocator<T>;
19
+
20
+ #else
21
+
22
+ void* allocateMem(size_t size);
23
+
24
+ void deallocateMem(void* ptr, size_t size = 1);
25
+
26
+ template<typename T>
27
+ class Allocator
28
+ {
29
+ public:
30
+
31
+ // Allocator traits
32
+ typedef T type;
33
+ typedef type value_type;
34
+ typedef value_type* pointer;
35
+ typedef value_type const* const_pointer;
36
+ typedef value_type& reference;
37
+ typedef value_type const& const_reference;
38
+ typedef std::size_t size_type;
39
+ typedef std::ptrdiff_t difference_type;
40
+
41
+ template<typename U>
42
+ struct rebind
43
+ {
44
+ typedef Allocator<U> other;
45
+ };
46
+
47
+ // Constructor
48
+ Allocator(void) {}
49
+
50
+ // Copy Constructor
51
+ template<typename U>
52
+ Allocator(Allocator<U> const&)
53
+ {}
54
+
55
+ // allocate but don't initialize count of elements of type T
56
+ pointer allocate(size_type count, const_pointer /* hint */ = 0)
57
+ {
58
+ return (pointer)(Sass::allocateMem(count * sizeof(T)));
59
+ }
60
+
61
+ // deallocate storage ptr of deleted elements
62
+ void deallocate(pointer ptr, size_type count)
63
+ {
64
+ Sass::deallocateMem(ptr, count);
65
+ }
66
+
67
+ // return maximum number of elements that can be allocated
68
+ size_type max_size() const throw()
69
+ {
70
+ return std::numeric_limits<size_type>::max() / sizeof(T);
71
+ }
72
+
73
+ // Address of object
74
+ type* address(type& obj) const { return &obj; }
75
+ type const* address(type const& obj) const { return &obj; }
76
+
77
+ // Construct object
78
+ void construct(type* ptr, type const& ref) const
79
+ {
80
+ // In-place copy construct
81
+ new(ptr) type(ref);
82
+ }
83
+
84
+ // Destroy object
85
+ void destroy(type* ptr) const
86
+ {
87
+ // Call destructor
88
+ ptr->~type();
89
+ }
90
+
91
+ };
92
+
93
+ template<typename T, typename U>
94
+ bool operator==(Allocator<T> const& left,
95
+ Allocator<U> const& right)
96
+ {
97
+ return true;
98
+ }
99
+
100
+ template<typename T, typename U>
101
+ bool operator!=(Allocator<T> const& left,
102
+ Allocator<U> const& right)
103
+ {
104
+ return !(left == right);
105
+ }
106
+
107
+ #endif
108
+
109
+ namespace sass {
110
+ template <typename T> using vector = std::vector<T, Sass::Allocator<T>>;
111
+ using string = std::basic_string<char, std::char_traits<char>, Sass::Allocator<char>>;
112
+ using sstream = std::basic_stringstream<char, std::char_traits<char>, Sass::Allocator<char>>;
113
+ using ostream = std::basic_ostringstream<char, std::char_traits<char>, Sass::Allocator<char>>;
114
+ using istream = std::basic_istringstream<char, std::char_traits<char>, Sass::Allocator<char>>;
115
+ }
116
+
117
+ }
118
+
119
+ #ifdef SASS_CUSTOM_ALLOCATOR
120
+
121
+ namespace std {
122
+ // Only GCC seems to need this specialization!?
123
+ template <> struct hash<Sass::sass::string> {
124
+ public:
125
+ inline size_t operator()(
126
+ const Sass::sass::string& name) const
127
+ {
128
+ return MurmurHash2(
129
+ (void*)name.c_str(),
130
+ (int)name.size(),
131
+ 0x73617373);
132
+ }
133
+ };
134
+ }
135
+
136
+ #endif
137
+
138
+ #endif
@@ -0,0 +1,20 @@
1
+ #ifndef SASS_MEMORY_CONFIG_H
2
+ #define SASS_MEMORY_CONFIG_H
3
+
4
+ // Define memory alignment requirements
5
+ #define SASS_MEM_ALIGN sizeof(unsigned int)
6
+
7
+ // Minimal alignment for memory fragments. Must be a multiple
8
+ // of `SASS_MEM_ALIGN` and should not be too big (maybe 1 or 2)
9
+ #define SassAllocatorHeadSize sizeof(unsigned int)
10
+
11
+ // The number of bytes we use for our book-keeping before every
12
+ // memory fragment. Needed to know to which bucket we belongs on
13
+ // deallocations, or if it should go directly to the `free` call.
14
+ #define SassAllocatorBookSize sizeof(unsigned int)
15
+
16
+ // Bytes reserve for book-keeping on the arenas
17
+ // Currently unused and for later optimization
18
+ #define SassAllocatorArenaHeadSize 0
19
+
20
+ #endif
@@ -0,0 +1,186 @@
1
+ #ifndef SASS_MEMORY_POOL_H
2
+ #define SASS_MEMORY_POOL_H
3
+
4
+ #include <stdlib.h>
5
+ #include <iostream>
6
+ #include <algorithm>
7
+ #include <climits>
8
+ #include <vector>
9
+
10
+ namespace Sass {
11
+
12
+ // SIMPLE MEMORY-POOL ALLOCATOR WITH FREE-LIST ON TOP
13
+
14
+ // This is a memory pool allocator with a free list on top.
15
+ // We only allocate memory arenas from the system in specific
16
+ // sizes (`SassAllocatorArenaSize`). Users claim memory slices
17
+ // of certain sizes from the pool. If the allocation is too big
18
+ // to fit into our buckets, we use regular malloc/free instead.
19
+
20
+ // When the systems starts, we allocate the first arena and then
21
+ // start to give out addresses to memory slices. During that
22
+ // we steadily increase `offset` until the current arena is full.
23
+ // Once that happens we allocate a new arena and continue.
24
+ // https://en.wikipedia.org/wiki/Memory_pool
25
+
26
+ // Fragments that get deallocated are not really freed, we put
27
+ // them on our free-list. For every bucket we have a pointer to
28
+ // the first item for reuse. That item itself holds a pointer to
29
+ // the previously free item (regular free-list implementation).
30
+ // https://en.wikipedia.org/wiki/Free_list
31
+
32
+ // On allocation calls we first check if there is any suitable
33
+ // item on the free-list. If there is we pop it from the stack
34
+ // and return it to the caller. Otherwise we have to take out
35
+ // a new slice from the current `arena` and increase `offset`.
36
+
37
+ // Note that this is not thread safe. This is on purpose as we
38
+ // want to use the memory pool in a thread local usage. In order
39
+ // to get this thread safe you need to only allocate one pool
40
+ // per thread. This can be achieved by using thread local PODs.
41
+ // Simply create a pool on the first allocation and dispose
42
+ // it once all allocations have been returned. E.g. by using:
43
+ // static thread_local size_t allocations;
44
+ // static thread_local MemoryPool* pool;
45
+
46
+ class MemoryPool {
47
+
48
+ // Current arena we fill up
49
+ char* arena;
50
+
51
+ // Position into the arena
52
+ size_t offset = std::string::npos;
53
+
54
+ // A list of full arenas
55
+ std::vector<void*> arenas;
56
+
57
+ // One pointer for every bucket (zero init)
58
+ #ifdef _MSC_VER
59
+ #pragma warning (suppress:4351)
60
+ #endif
61
+ void* freeList[SassAllocatorBuckets]{};
62
+
63
+ // Increase the address until it sits on a
64
+ // memory aligned address (maybe use `aligned`).
65
+ inline static size_t alignMemAddr(size_t addr) {
66
+ return (addr + SASS_MEM_ALIGN - 1) & ~(SASS_MEM_ALIGN - 1);
67
+ }
68
+
69
+ public:
70
+
71
+ // Default ctor
72
+ MemoryPool() :
73
+ // Wait for first allocation
74
+ arena(nullptr),
75
+ // Set to maximum value in order to
76
+ // make an allocation on the first run
77
+ offset(std::string::npos)
78
+ {
79
+ }
80
+
81
+ // Destructor
82
+ ~MemoryPool() {
83
+ // Delete full arenas
84
+ for (auto area : arenas) {
85
+ free(area);
86
+ }
87
+ // Delete current arena
88
+ free(arena);
89
+
90
+ }
91
+
92
+ // Allocate a slice of the memory pool
93
+ void* allocate(size_t size)
94
+ {
95
+
96
+ // Increase size so its memory is aligned
97
+ size = alignMemAddr(
98
+ // Make sure we have enough space for us to
99
+ // create the pointer to the free list later
100
+ std::max(sizeof(void*), size)
101
+ // and the size needed for our book-keeping
102
+ + SassAllocatorBookSize);
103
+
104
+ // Size must be multiple of alignment
105
+ // So we can derive bucket index from it
106
+ size_t bucket = size / SASS_MEM_ALIGN;
107
+
108
+ // Everything bigger is allocated via malloc
109
+ // Malloc is optimized for exactly this case
110
+ if (bucket >= SassAllocatorBuckets) {
111
+ char* buffer = (char*)malloc(size);
112
+ if (buffer == nullptr) {
113
+ throw std::bad_alloc();
114
+ }
115
+ // Mark it for deallocation via free
116
+ ((unsigned int*)buffer)[0] = UINT_MAX;
117
+ // Return pointer after our book-keeping space
118
+ return (void*)(buffer + SassAllocatorBookSize);
119
+ }
120
+ // Use custom allocator
121
+ else {
122
+ // Get item from free list
123
+ void*& free = freeList[bucket];
124
+ // Do we have a free item?
125
+ if (free != nullptr) {
126
+ // Copy pointer to return
127
+ void* ptr = free;
128
+ // Update free list pointer
129
+ free = ((void**)ptr)[0];
130
+ // Return popped item
131
+ return ptr;
132
+ }
133
+ }
134
+
135
+ // Make sure we have enough space in the arena
136
+ if (!arena || offset > SassAllocatorArenaSize - size) {
137
+ if (arena) arenas.emplace_back(arena);
138
+ arena = (char*)malloc(SassAllocatorArenaSize);
139
+ if (arena == nullptr) throw std::bad_alloc();
140
+ offset = SassAllocatorArenaHeadSize;
141
+ }
142
+
143
+ // Get pointer into the arena
144
+ char* buffer = arena + offset;
145
+ // Consume object size
146
+ offset += size;
147
+
148
+ // Set the bucket index for this slice
149
+ ((unsigned int*)buffer)[0] = (unsigned int)bucket;
150
+
151
+ // Return pointer after our book-keeping space
152
+ return (void*)(buffer + SassAllocatorBookSize);
153
+
154
+ }
155
+ // EO allocate
156
+
157
+ void deallocate(void* ptr)
158
+ {
159
+
160
+ // Rewind buffer from pointer
161
+ char* buffer = (char*)ptr -
162
+ SassAllocatorBookSize;
163
+
164
+ // Get the bucket index stored in the header
165
+ unsigned int bucket = ((unsigned int*)buffer)[0];
166
+
167
+ // Check allocation method
168
+ if (bucket != UINT_MAX) {
169
+ // Let memory point to previous item in free list
170
+ ((void**)ptr)[0] = freeList[bucket];
171
+ // Free list now points to our memory
172
+ freeList[bucket] = (void*)ptr;
173
+ }
174
+ else {
175
+ // Release memory
176
+ free(buffer);
177
+ }
178
+
179
+ }
180
+ // EO deallocate
181
+
182
+ };
183
+
184
+ }
185
+
186
+ #endif