sassc 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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