Skip to content

Commit 02a7ed5

Browse files
committed
Expose sass operations on C-API
Adds new value converter functions.
1 parent 31002ec commit 02a7ed5

File tree

8 files changed

+216
-0
lines changed

8 files changed

+216
-0
lines changed

Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ SOURCES = \
193193
to_value.cpp \
194194
units.cpp \
195195
utf8_string.cpp \
196+
values.cpp \
196197
util.cpp
197198

198199
CSOURCES = cencode.c

Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ libsass_la_SOURCES = \
8080
to_value.cpp to_value.hpp \
8181
units.cpp units.hpp \
8282
utf8_string.cpp utf8_string.hpp \
83+
values.cpp values.hpp \
8384
util.cpp util.hpp
8485

8586
libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 0:9:0

sass_values.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include <cstdlib>
88
#include <cstring>
99
#include "util.hpp"
10+
#include "eval.hpp"
11+
#include "values.hpp"
1012
#include "sass_values.h"
1113

1214
extern "C" {
@@ -351,4 +353,65 @@ extern "C" {
351353

352354
}
353355

356+
union Sass_Value* ADDCALL sass_value_stringify (const union Sass_Value* v, bool compressed, int precision)
357+
{
358+
Memory_Manager<AST_Node> mem;
359+
Value* val = sass_value_to_ast_node(mem, v);
360+
string str(val->to_string(compressed, precision));
361+
return sass_make_qstring(str.c_str());
362+
}
363+
364+
union Sass_Value* ADDCALL sass_value_op (enum Sass_OP op, const union Sass_Value* a, const union Sass_Value* b)
365+
{
366+
367+
Sass::Value* rv = 0;
368+
Memory_Manager<AST_Node> mem;
369+
Value* lhs = sass_value_to_ast_node(mem, a);
370+
Value* rhs = sass_value_to_ast_node(mem, b);
371+
372+
// see if it's a relational expression
373+
switch(op) {
374+
case Sass_OP::EQ: return sass_make_boolean(Eval::eq(lhs, rhs));
375+
case Sass_OP::NEQ: return sass_make_boolean(!Eval::eq(lhs, rhs));
376+
case Sass_OP::GT: return sass_make_boolean(!Eval::lt(lhs, rhs) && !Eval::eq(lhs, rhs));
377+
case Sass_OP::GTE: return sass_make_boolean(!Eval::lt(lhs, rhs));
378+
case Sass_OP::LT: return sass_make_boolean(Eval::lt(lhs, rhs));
379+
case Sass_OP::LTE: return sass_make_boolean(Eval::lt(lhs, rhs) || Eval::eq(lhs, rhs));
380+
default: break;
381+
}
382+
383+
if (sass_value_is_number(a) && sass_value_is_number(b)) {
384+
const Number* l_n = dynamic_cast<const Number*>(lhs);
385+
const Number* r_n = dynamic_cast<const Number*>(rhs);
386+
rv = Eval::op_numbers(mem, op, *l_n, *r_n);
387+
}
388+
else if (sass_value_is_number(a) && sass_value_is_color(a)) {
389+
const Number* l_n = dynamic_cast<const Number*>(lhs);
390+
const Color* r_c = dynamic_cast<const Color*>(rhs);
391+
rv = Eval::op_number_color(mem, op, *l_n, *r_c);
392+
}
393+
else if (sass_value_is_color(a) && sass_value_is_number(b)) {
394+
const Color* l_c = dynamic_cast<const Color*>(lhs);
395+
const Number* r_n = dynamic_cast<const Number*>(rhs);
396+
rv = Eval::op_color_number(mem, op, *l_c, *r_n);
397+
}
398+
else if (sass_value_is_color(a) && sass_value_is_color(b)) {
399+
const Color* l_c = dynamic_cast<const Color*>(lhs);
400+
const Color* r_c = dynamic_cast<const Color*>(rhs);
401+
rv = Eval::op_colors(mem, op, *l_c, *r_c);
402+
}
403+
else /* convert other stuff to string and apply operation */ {
404+
Value* l_v = dynamic_cast<Value*>(lhs);
405+
Value* r_v = dynamic_cast<Value*>(rhs);
406+
rv = Eval::op_strings(mem, op, *l_v, *r_v);
407+
}
408+
409+
// ToDo: maybe we should should return null value?
410+
if (!rv) return sass_make_error("invalid return value");
411+
412+
// convert result back to ast node
413+
return ast_node_to_sass_value(rv);
414+
415+
}
416+
354417
}

sass_values.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,12 @@ ADDAPI void ADDCALL sass_delete_value (union Sass_Value* val);
127127
// Make a deep cloned copy of the given sass value
128128
ADDAPI union Sass_Value* ADDCALL sass_clone_value (const union Sass_Value* val);
129129

130+
// Stringify a Sass_Values and also return the result as a Sass_Value (of type STRING)
131+
ADDAPI union Sass_Value* ADDCALL sass_value_stringify (const union Sass_Value* a, bool compressed, int precision);
132+
133+
// Execute an operation for two Sass_Values and return the result as a Sass_Value too
134+
ADDAPI union Sass_Value* ADDCALL sass_value_op (enum Sass_OP op, const union Sass_Value* a, const union Sass_Value* b);
135+
130136

131137
#ifdef __cplusplus
132138
} // __cplusplus defined.

values.cpp

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#include "sass.h"
2+
#include "values.hpp"
3+
4+
#include <stdint.h>
5+
6+
namespace Sass {
7+
using namespace std;
8+
9+
// convert value from C++ side to C-API
10+
union Sass_Value* ast_node_to_sass_value (const Expression* val)
11+
{
12+
if (val->concrete_type() == Expression::NUMBER)
13+
{
14+
const Number* res = dynamic_cast<const Number*>(val);
15+
return sass_make_number(res->value(), res->unit().c_str());
16+
}
17+
else if (val->concrete_type() == Expression::COLOR)
18+
{
19+
const Color* col = dynamic_cast<const Color*>(val);
20+
return sass_make_color(col->r(), col->g(), col->b(), col->a());
21+
}
22+
else if (val->concrete_type() == Expression::LIST)
23+
{
24+
const List* l = dynamic_cast<const List*>(val);
25+
union Sass_Value* list = sass_make_list(l->size(), l->separator());
26+
for (size_t i = 0, L = l->length(); i < L; ++i) {
27+
auto val = ast_node_to_sass_value((*l)[i]);
28+
sass_list_set_value(list, i, val);
29+
}
30+
return list;
31+
}
32+
else if (val->concrete_type() == Expression::MAP)
33+
{
34+
const Map* m = dynamic_cast<const Map*>(val);
35+
union Sass_Value* map = sass_make_map(m->length());
36+
size_t i = 0; for (auto key : m->keys()) {
37+
sass_map_set_key(map, i, ast_node_to_sass_value(key));
38+
sass_map_set_value(map, i, ast_node_to_sass_value(m->at(key)));
39+
++ i;
40+
}
41+
return map;
42+
}
43+
else if (val->concrete_type() == Expression::NULL_VAL)
44+
{
45+
return sass_make_null();
46+
}
47+
else if (val->concrete_type() == Expression::BOOLEAN)
48+
{
49+
const Boolean* res = dynamic_cast<const Boolean*>(val);
50+
return sass_make_boolean(res->value());
51+
}
52+
else if (val->concrete_type() == Expression::STRING)
53+
{
54+
if (const String_Quoted* qstr = dynamic_cast<const String_Quoted*>(val))
55+
{
56+
return sass_make_qstring(qstr->value().c_str());
57+
}
58+
else if (const String_Constant* cstr = dynamic_cast<const String_Constant*>(val))
59+
{
60+
return sass_make_string(cstr->value().c_str());
61+
}
62+
}
63+
return sass_make_error("unknown sass value type");
64+
}
65+
66+
// convert value from C-API to C++ side
67+
Value* sass_value_to_ast_node (Memory_Manager<AST_Node>& mem, const union Sass_Value* val)
68+
{
69+
switch (sass_value_get_tag(val)) {
70+
case SASS_NUMBER:
71+
return new (mem) Number(ParserState("[C-VALUE]"),
72+
sass_number_get_value(val),
73+
sass_number_get_unit(val));
74+
break;
75+
case SASS_BOOLEAN:
76+
return new (mem) Boolean(ParserState("[C-VALUE]"),
77+
sass_boolean_get_value(val));
78+
break;
79+
case SASS_COLOR:
80+
return new (mem) Color(ParserState("[C-VALUE]"),
81+
sass_color_get_r(val),
82+
sass_color_get_g(val),
83+
sass_color_get_b(val),
84+
sass_color_get_a(val));
85+
break;
86+
case SASS_STRING:
87+
return new (mem) String_Quoted(ParserState("[C-VALUE]"),
88+
sass_string_get_value(val));
89+
break;
90+
case SASS_LIST: {
91+
List* l = new (mem) List(ParserState("[C-VALUE]"),
92+
sass_list_get_length(val),
93+
sass_list_get_separator(val));
94+
for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) {
95+
*l << sass_value_to_ast_node(mem, sass_list_get_value(val, i));
96+
}
97+
return l;
98+
}
99+
break;
100+
case SASS_MAP: {
101+
Map* m = new (mem) Map(ParserState("[C-VALUE]"));
102+
for (size_t i = 0, L = sass_map_get_length(val); i < L; ++i) {
103+
*m << std::make_pair(
104+
sass_value_to_ast_node(mem, sass_map_get_key(val, i)),
105+
sass_value_to_ast_node(mem, sass_map_get_value(val, i)));
106+
}
107+
return m;
108+
}
109+
break;
110+
case SASS_NULL:
111+
return new (mem) Null(ParserState("[C-VALUE]"));
112+
break;
113+
case SASS_ERROR:
114+
return new (mem) Custom_Error(ParserState("[C-VALUE]"),
115+
sass_error_get_message(val));
116+
break;
117+
case SASS_WARNING:
118+
return new (mem) Custom_Warning(ParserState("[C-VALUE]"),
119+
sass_warning_get_message(val));
120+
break;
121+
}
122+
return 0;
123+
}
124+
125+
}

values.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#ifndef SASS_VALUES_H
2+
#define SASS_VALUES_H
3+
4+
#include "ast.hpp"
5+
6+
namespace Sass {
7+
8+
union Sass_Value* ast_node_to_sass_value (const Expression* val);
9+
Value* sass_value_to_ast_node (Memory_Manager<AST_Node>& mem, const union Sass_Value* val);
10+
11+
}
12+
#endif

win/libsass.filters

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@
132132
<ClCompile Include="..\util.cpp">
133133
<Filter>Source Files</Filter>
134134
</ClCompile>
135+
<ClCompile Include="..\values.cpp">
136+
<Filter>Source Files</Filter>
137+
</ClCompile>
135138
<ClCompile Include="..\cencode.c">
136139
<Filter>Source Files</Filter>
137140
</ClCompile>
@@ -305,6 +308,9 @@
305308
<ClInclude Include="..\util.hpp">
306309
<Filter>Header Files</Filter>
307310
</ClInclude>
311+
<ClInclude Include="..\values.hpp">
312+
<Filter>Header Files</Filter>
313+
</ClInclude>
308314
<ClInclude Include="..\json.hpp">
309315
<Filter>Header Files</Filter>
310316
</ClInclude>

win/libsass.vcxproj

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
<ClCompile Include="..\units.cpp" />
204204
<ClCompile Include="..\utf8_string.cpp" />
205205
<ClCompile Include="..\util.cpp" />
206+
<ClCompile Include="..\values.cpp" />
206207
<ClCompile Include="..\sassc\sassc.c" />
207208
</ItemGroup>
208209
<ItemGroup>
@@ -262,6 +263,7 @@
262263
<ClInclude Include="..\utf8\unchecked.h" />
263264
<ClInclude Include="..\utf8_string.hpp" />
264265
<ClInclude Include="..\util.hpp" />
266+
<ClInclude Include="..\values.hpp" />
265267
</ItemGroup>
266268
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
267269
<ImportGroup Label="ExtensionTargets">

0 commit comments

Comments
 (0)