Skip to content

Commit 56e96a8

Browse files
committed
Merge pull request #1983 from mgreter/feature/C-API-mem-allocator
Expose mem allocator on C-API
2 parents aa8aa2d + 913150f commit 56e96a8

17 files changed

+108
-399
lines changed

Makefile.conf

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ SOURCES = \
3333
sass_values.cpp \
3434
sass_context.cpp \
3535
sass_functions.cpp \
36-
sass_interface.cpp \
3736
sass2scss.cpp \
3837
source_map.cpp \
3938
to_c.cpp \

docs/api-context.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ char* source_map_file;
8888
char* source_map_root;
8989
```
9090
```C
91-
// Custom functions that can be called from sccs code
91+
// Custom functions that can be called from Sass code
9292
Sass_C_Function_List c_functions;
9393
```
9494
```C
@@ -168,12 +168,12 @@ struct Sass_Compiler* sass_make_data_compiler (struct Sass_Data_Context* data_ct
168168

169169
// Execute the different compilation steps individually
170170
// Usefull if you only want to query the included files
171-
int sass_compiler_parse(struct Sass_Compiler* compiler);
172-
int sass_compiler_execute(struct Sass_Compiler* compiler);
171+
int sass_compiler_parse (struct Sass_Compiler* compiler);
172+
int sass_compiler_execute (struct Sass_Compiler* compiler);
173173

174174
// Release all memory allocated with the compiler
175175
// This does _not_ include any contexts or options
176-
void sass_delete_compiler(struct Sass_Compiler* compiler);
176+
void sass_delete_compiler (struct Sass_Compiler* compiler);
177177

178178
// Release all memory allocated and also ourself
179179
void sass_delete_file_context (struct Sass_File_Context* ctx);

docs/api-doc.md

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,24 +16,14 @@ This will automatically load all other headers too!
1616
#include "sass/context.h"
1717
```
1818

19-
### Deprecated usage
20-
21-
The old API is kept in the source for backward compatibility.
22-
It's deprecated and incompatible with this documentation, use `sass/context.h`!
23-
24-
```C
25-
// deprecated interface
26-
#include "sass/interface.h"
27-
```
28-
2919
## Basic C Example
3020

3121
```C
3222
#include <stdio.h>
3323
#include "sass/context.h"
3424

3525
int main() {
36-
puts(libsass_VERSION());
26+
puts(libsass_version());
3727
return 0;
3828
}
3929
```
@@ -114,6 +104,34 @@ This mirrors very well how `libsass` uses these structures.
114104

115105
Structs can be down-casted to access `context` or `options`!
116106

107+
## Memory handling and life-cycles
108+
109+
We keep memory around for as long as the main [context](api-context.md) object is not destroyed (`sass_delete_context`). LibSass will create copies of most inputs/options beside the main sass code.
110+
You need to allocate and fill that buffer before passing it to LibSass. You may also overtake memory management from libsass for certain return values (i.e. `sass_context_take_output_string`).
111+
112+
```C
113+
// to allocate buffer to be filled
114+
void* sass_alloc_memory(size_t size);
115+
// to allocate a buffer from existing string
116+
char* sass_copy_c_string(const char* str);
117+
// to free overtaken memory when done
118+
void sass_free_memory(void* ptr);
119+
```
120+
121+
## Miscellaneous API functions
122+
123+
```C
124+
// Some convenient string helper function
125+
char* sass_string_unquote (const char* str);
126+
char* sass_string_quote (const char* str, const char quote_mark);
127+
128+
// Resolve a file via the given include paths in the include char* array
129+
char* sass_resolve_file (const char* path, const char* incs[]);
130+
131+
// Get compiled libsass version
132+
const char* libsass_version(void);
133+
```
134+
117135
## Common Pitfalls
118136

119137
**input_path**

docs/api-importer-example.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ Sass_Import_List sass_importer(const char* path, Sass_Importer_Entry cb, struct
1010
// get the cookie from importer descriptor
1111
void* cookie = sass_importer_get_cookie(cb);
1212
Sass_Import_List list = sass_make_import_list(2);
13-
const char* local = "local { color: green; }";
14-
const char* remote = "remote { color: red; }";
15-
list[0] = sass_make_import_entry("/tmp/styles.scss", strdup(local), 0);
16-
list[1] = sass_make_import_entry("http://www.example.com", strdup(remote), 0);
13+
char* local = sass_copy_c_string("local { color: green; }");
14+
char* remote = sass_copy_c_string("remote { color: red; }");
15+
list[0] = sass_make_import_entry("/tmp/styles.scss", local, 0);
16+
list[1] = sass_make_import_entry("http://www.example.com", remote, 0);
1717
return list;
1818
}
1919

@@ -84,7 +84,7 @@ Sass_Import_List importer(const char* path, Sass_Importer_Entry cb, struct Sass_
8484
Sass_Import_List list = sass_make_import_list(1);
8585
const char* message = "some error message";
8686
list[0] = sass_make_import_entry(path, 0, 0);
87-
sass_import_set_error(list[0], strdup(message), 0, 0);
87+
sass_import_set_error(list[0], sass_copy_c_string(message), 0, 0);
8888
return list;
8989
}
9090

include/sass/base.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ enum Sass_Output_Style {
6262
SASS_STYLE_TO_SASS
6363
};
6464

65+
// to allocate buffer to be filled
66+
void* sass_alloc_memory(size_t size);
67+
// to allocate a buffer from existing string
68+
char* sass_copy_c_string(const char* str);
69+
// to free overtaken memory when done
70+
void sass_free_memory(void* ptr);
71+
6572
// Some convenient string helper function
6673
ADDAPI char* ADDCALL sass_string_quote (const char* str, const char quote_mark);
6774
ADDAPI char* ADDCALL sass_string_unquote (const char* str);

include/sass/interface.h

Lines changed: 0 additions & 105 deletions
This file was deleted.

src/context.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ namespace Sass {
289289
const char* contents = resources[idx].contents;
290290
// keep a copy of the path around (for parserstates)
291291
// ToDo: we clean it, but still not very elegant!?
292-
strings.push_back(sass_strdup(inc.abs_path.c_str()));
292+
strings.push_back(sass_copy_c_string(inc.abs_path.c_str()));
293293
// create the initial parser state from resource
294294
ParserState pstate(strings.back(), contents, idx);
295295

@@ -519,7 +519,7 @@ namespace Sass {
519519
}
520520
// create a copy of the resulting buffer string
521521
// this must be freed or taken over by implementor
522-
return sass_strdup(emitted.buffer.c_str());
522+
return sass_copy_c_string(emitted.buffer.c_str());
523523
}
524524

525525
void Context::apply_custom_headers(Block* root, const char* ctx_path, ParserState pstate)
@@ -606,7 +606,7 @@ namespace Sass {
606606

607607
// ToDo: this may be resolved via custom importers
608608
std::string abs_path(rel2abs(entry_path));
609-
char* abs_path_c_str = sass_strdup(abs_path.c_str());
609+
char* abs_path_c_str = sass_copy_c_string(abs_path.c_str());
610610
strings.push_back(abs_path_c_str);
611611

612612
// create entry only for the import stack
@@ -693,7 +693,7 @@ namespace Sass {
693693
if (source_map_file == "") return 0;
694694
char* result = 0;
695695
std::string map = emitter.render_srcmap(*this);
696-
result = sass_strdup(map.c_str());
696+
result = sass_copy_c_string(map.c_str());
697697
return result;
698698
}
699699

src/expand.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ namespace Sass {
197197
{
198198
Expression* mq = m->media_queries()->perform(&eval);
199199
std::string str_mq(mq->to_string(ctx.c_options));
200-
char* str = sass_strdup(str_mq.c_str());
200+
char* str = sass_copy_c_string(str_mq.c_str());
201201
ctx.strings.push_back(str);
202202
Parser p(Parser::from_c_str(str, ctx, mq->pstate()));
203203
mq = p.parse_media_queries();

src/sass.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,50 @@
1111
extern "C" {
1212
using namespace Sass;
1313

14+
// Allocate libsass heap memory
15+
// Don't forget string termination!
16+
void* ADDCALL sass_alloc_memory(size_t size)
17+
{
18+
void* ptr = malloc(size);
19+
if (ptr == NULL)
20+
out_of_memory();
21+
return ptr;
22+
}
23+
24+
char* ADDCALL sass_copy_c_string(const char* str)
25+
{
26+
size_t len = strlen(str) + 1;
27+
char* cpy = (char*) sass_alloc_memory(len);
28+
std::memcpy(cpy, str, len);
29+
return cpy;
30+
}
31+
32+
// Deallocate libsass heap memory
33+
void ADDCALL sass_free_memory(void* ptr)
34+
{
35+
if (ptr) free (ptr);
36+
}
37+
1438
// caller must free the returned memory
1539
char* ADDCALL sass_string_quote (const char *str, const char quote_mark)
1640
{
1741
std::string quoted = quote(str, quote_mark);
18-
return sass_strdup(quoted.c_str());
42+
return sass_copy_c_string(quoted.c_str());
1943
}
2044

2145
// caller must free the returned memory
2246
char* ADDCALL sass_string_unquote (const char *str)
2347
{
2448
std::string unquoted = unquote(str);
25-
return sass_strdup(unquoted.c_str());
49+
return sass_copy_c_string(unquoted.c_str());
2650
}
2751

2852
// Make sure to free the returned value!
2953
// Incs array has to be null terminated!
3054
char* ADDCALL sass_resolve_file (const char* file, const char* paths[])
3155
{
3256
std::string resolved(File::find_file(file, paths));
33-
return sass_strdup(resolved.c_str());
57+
return sass_copy_c_string(resolved.c_str());
3458
}
3559

3660
// Get compiled libsass version

0 commit comments

Comments
 (0)