Skip to content

Commit

Permalink
Move string functions to own compile unit
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Mar 17, 2018
1 parent 37cfb4c commit ac4e48b
Show file tree
Hide file tree
Showing 8 changed files with 303 additions and 263 deletions.
1 change: 1 addition & 0 deletions Makefile.conf
Expand Up @@ -13,6 +13,7 @@ SOURCES = \
fn_utils.cpp \
fn_colors.cpp \
fn_numbers.cpp \
fn_strings.cpp \
fn_selectors.cpp \
functions.cpp \
color_maps.cpp \
Expand Down
1 change: 1 addition & 0 deletions src/context.cpp
Expand Up @@ -32,6 +32,7 @@
#include "fn_utils.hpp"
#include "fn_colors.hpp"
#include "fn_numbers.hpp"
#include "fn_strings.hpp"
#include "fn_selectors.hpp"

namespace Sass {
Expand Down
258 changes: 258 additions & 0 deletions src/fn_strings.cpp
@@ -0,0 +1,258 @@
#include "ast.hpp"
#include "fn_utils.hpp"
#include "fn_strings.hpp"

namespace Sass {

namespace Functions {

void handle_utf8_error (const ParserState& pstate, Backtraces traces)
{
try {
throw;
}
catch (utf8::invalid_code_point) {
std::string msg("utf8::invalid_code_point");
error(msg, pstate, traces);
}
catch (utf8::not_enough_room) {
std::string msg("utf8::not_enough_room");
error(msg, pstate, traces);
}
catch (utf8::invalid_utf8) {
std::string msg("utf8::invalid_utf8");
error(msg, pstate, traces);
}
catch (...) { throw; }
}

///////////////////
// STRING FUNCTIONS
///////////////////

Signature unquote_sig = "unquote($string)";
BUILT_IN(sass_unquote)
{
AST_Node_Obj arg = env["$string"];
if (String_Quoted_Ptr string_quoted = Cast<String_Quoted>(arg)) {
String_Constant_Ptr result = SASS_MEMORY_NEW(String_Constant, pstate, string_quoted->value());
// remember if the string was quoted (color tokens)
result->is_delayed(true); // delay colors
return result;
}
else if (String_Constant_Ptr str = Cast<String_Constant>(arg)) {
return str;
}
else if (Value_Ptr ex = Cast<Value>(arg)) {
Sass_Output_Style oldstyle = ctx.c_options.output_style;
ctx.c_options.output_style = SASS_STYLE_NESTED;
std::string val(arg->to_string(ctx.c_options));
val = Cast<Null>(arg) ? "null" : val;
ctx.c_options.output_style = oldstyle;

deprecated_function("Passing " + val + ", a non-string value, to unquote()", pstate);
return ex;
}
throw std::runtime_error("Invalid Data Type for unquote");
}

Signature quote_sig = "quote($string)";
BUILT_IN(sass_quote)
{
AST_Node_Obj arg = env["$string"];
// only set quote mark to true if already a string
if (String_Quoted_Ptr qstr = Cast<String_Quoted>(arg)) {
qstr->quote_mark('*');
return qstr;
}
// all other nodes must be converted to a string node
std::string str(quote(arg->to_string(ctx.c_options), String_Constant::double_quote()));
String_Quoted_Ptr result = SASS_MEMORY_NEW(String_Quoted, pstate, str);
result->quote_mark('*');
return result;
}


Signature str_length_sig = "str-length($string)";
BUILT_IN(str_length)
{
size_t len = std::string::npos;
try {
String_Constant_Ptr s = ARG("$string", String_Constant);
len = UTF_8::code_point_count(s->value(), 0, s->value().size());

}
// handle any invalid utf8 errors
// other errors will be re-thrown
catch (...) { handle_utf8_error(pstate, traces); }
// return something even if we had an error (-1)
return SASS_MEMORY_NEW(Number, pstate, (double)len);
}

Signature str_insert_sig = "str-insert($string, $insert, $index)";
BUILT_IN(str_insert)
{
std::string str;
try {
String_Constant_Ptr s = ARG("$string", String_Constant);
str = s->value();
str = unquote(str);
String_Constant_Ptr i = ARG("$insert", String_Constant);
std::string ins = i->value();
ins = unquote(ins);
double index = ARGVAL("$index");
size_t len = UTF_8::code_point_count(str, 0, str.size());

if (index > 0 && index <= len) {
// positive and within string length
str.insert(UTF_8::offset_at_position(str, static_cast<size_t>(index) - 1), ins);
}
else if (index > len) {
// positive and past string length
str += ins;
}
else if (index == 0) {
str = ins + str;
}
else if (std::abs(index) <= len) {
// negative and within string length
index += len + 1;
str.insert(UTF_8::offset_at_position(str, static_cast<size_t>(index)), ins);
}
else {
// negative and past string length
str = ins + str;
}

if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
if (ss->quote_mark()) str = quote(str);
}
}
// handle any invalid utf8 errors
// other errors will be re-thrown
catch (...) { handle_utf8_error(pstate, traces); }
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
}

Signature str_index_sig = "str-index($string, $substring)";
BUILT_IN(str_index)
{
size_t index = std::string::npos;
try {
String_Constant_Ptr s = ARG("$string", String_Constant);
String_Constant_Ptr t = ARG("$substring", String_Constant);
std::string str = s->value();
str = unquote(str);
std::string substr = t->value();
substr = unquote(substr);

size_t c_index = str.find(substr);
if(c_index == std::string::npos) {
return SASS_MEMORY_NEW(Null, pstate);
}
index = UTF_8::code_point_count(str, 0, c_index) + 1;
}
// handle any invalid utf8 errors
// other errors will be re-thrown
catch (...) { handle_utf8_error(pstate, traces); }
// return something even if we had an error (-1)
return SASS_MEMORY_NEW(Number, pstate, (double)index);
}

Signature str_slice_sig = "str-slice($string, $start-at, $end-at:-1)";
BUILT_IN(str_slice)
{
std::string newstr;
try {
String_Constant_Ptr s = ARG("$string", String_Constant);
double start_at = ARGVAL("$start-at");
double end_at = ARGVAL("$end-at");
String_Quoted_Ptr ss = Cast<String_Quoted>(s);

std::string str = unquote(s->value());

size_t size = utf8::distance(str.begin(), str.end());

if (!Cast<Number>(env["$end-at"])) {
end_at = -1;
}

if (end_at == 0 || (end_at + size) < 0) {
if (ss && ss->quote_mark()) newstr = quote("");
return SASS_MEMORY_NEW(String_Quoted, pstate, newstr);
}

if (end_at < 0) {
end_at += size + 1;
if (end_at == 0) end_at = 1;
}
if (end_at > size) { end_at = (double)size; }
if (start_at < 0) {
start_at += size + 1;
if (start_at < 0) start_at = 0;
}
else if (start_at == 0) { ++ start_at; }

if (start_at <= end_at)
{
std::string::iterator start = str.begin();
utf8::advance(start, start_at - 1, str.end());
std::string::iterator end = start;
utf8::advance(end, end_at - start_at + 1, str.end());
newstr = std::string(start, end);
}
if (ss) {
if(ss->quote_mark()) newstr = quote(newstr);
}
}
// handle any invalid utf8 errors
// other errors will be re-thrown
catch (...) { handle_utf8_error(pstate, traces); }
return SASS_MEMORY_NEW(String_Quoted, pstate, newstr);
}

Signature to_upper_case_sig = "to-upper-case($string)";
BUILT_IN(to_upper_case)
{
String_Constant_Ptr s = ARG("$string", String_Constant);
std::string str = s->value();

for (size_t i = 0, L = str.length(); i < L; ++i) {
if (Sass::Util::isAscii(str[i])) {
str[i] = std::toupper(str[i]);
}
}

if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
cpy->value(str);
return cpy;
} else {
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
}
}

Signature to_lower_case_sig = "to-lower-case($string)";
BUILT_IN(to_lower_case)
{
String_Constant_Ptr s = ARG("$string", String_Constant);
std::string str = s->value();

for (size_t i = 0, L = str.length(); i < L; ++i) {
if (Sass::Util::isAscii(str[i])) {
str[i] = std::tolower(str[i]);
}
}

if (String_Quoted_Ptr ss = Cast<String_Quoted>(s)) {
String_Quoted_Ptr cpy = SASS_MEMORY_COPY(ss);
cpy->value(str);
return cpy;
} else {
return SASS_MEMORY_NEW(String_Quoted, pstate, str);
}
}

}

}
34 changes: 34 additions & 0 deletions src/fn_strings.hpp
@@ -0,0 +1,34 @@
#ifndef SASS_FN_STRINGS_H
#define SASS_FN_STRINGS_H

#include "fn_utils.hpp"

namespace Sass {

namespace Functions {

extern Signature unquote_sig;
extern Signature quote_sig;
extern Signature str_length_sig;
extern Signature str_insert_sig;
extern Signature str_index_sig;
extern Signature str_slice_sig;
extern Signature to_upper_case_sig;
extern Signature to_lower_case_sig;
extern Signature length_sig;

BUILT_IN(sass_unquote);
BUILT_IN(sass_quote);
BUILT_IN(str_length);
BUILT_IN(str_insert);
BUILT_IN(str_index);
BUILT_IN(str_slice);
BUILT_IN(to_upper_case);
BUILT_IN(to_lower_case);
BUILT_IN(length);

}

}

#endif

0 comments on commit ac4e48b

Please sign in to comment.