Skip to content
This repository was archived by the owner on Oct 24, 2025. It is now read-only.
31 changes: 27 additions & 4 deletions file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@
#include <sys/stat.h>
#include "file.hpp"
#include "context.hpp"
#include "utf8_string.hpp"
#include "sass2scss/sass2scss.h"

#ifdef _WIN32
#include <windows.h>
#endif

namespace Sass {
namespace File {
using namespace std;
Expand Down Expand Up @@ -222,12 +227,25 @@ namespace Sass {
char* read_file(string path)
{
struct stat st;

#ifdef _WIN32
BYTE* pBuffer;
DWORD dwBytes;
// windows unicode filepaths are encoded in utf16
const wchar_t* wpath = UTF_8::convert_to_utf16(path).c_str();
HANDLE hFile = CreateFileW(wpath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (hFile == INVALID_HANDLE_VALUE) return 0;
DWORD dwFileLength = GetFileSize(hFile, NULL);
if (dwFileLength == INVALID_FILE_SIZE) return 0;
pBuffer = new BYTE[dwFileLength + 1];
ReadFile(hFile, pBuffer, dwFileLength, &dwBytes, NULL);
pBuffer[dwFileLength] = '\0';
CloseHandle(hFile);
// just convert from unsigned char*
char* contents = (char*) pBuffer;
#else
if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0;
ifstream file(path.c_str(), ios::in | ios::binary | ios::ate);
string extension;
if (path.length() > 5) {
extension = path.substr(path.length() - 5, 5);
}
char* contents = 0;
if (file.is_open()) {
size_t size = file.tellg();
Expand All @@ -237,6 +255,11 @@ namespace Sass {
contents[size] = '\0';
file.close();
}
#endif
string extension;
if (path.length() > 5) {
extension = path.substr(path.length() - 5, 5);
}
for(size_t i=0; i<extension.size();++i)
extension[i] = tolower(extension[i]);
if (extension == ".sass" && contents != 0) {
Expand Down
208 changes: 132 additions & 76 deletions functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include "eval.hpp"
#include "util.hpp"
#include "utf8_string.hpp"
#include "utf8.h"

#include <cstdlib>
#include <cmath>
Expand Down Expand Up @@ -696,110 +697,165 @@ namespace Sass {
Signature str_length_sig = "str-length($string)";
BUILT_IN(str_length)
{
String_Constant* s = ARG("$string", String_Constant);
string str = s->value();
size_t length_of_s = str.size();
size_t i = 0;

if (s->is_quoted()) {
++i;
--length_of_s;
}
size_t len;
try {
String_Constant* s = ARG("$string", String_Constant);
string str = s->value();
size_t length_of_s = str.size();
size_t i = 0;

if (s->is_quoted()) {
++i;
--length_of_s;
}

size_t len = UTF_8::code_point_count(str, i, length_of_s);
len = UTF_8::code_point_count(str, i, length_of_s);

}
catch (utf8::invalid_code_point) {
string msg("utf8::invalid_code_point");
error(msg, path, position, backtrace);
}
catch (utf8::not_enough_room) {
string msg("utf8::not_enough_room");
error(msg, path, position, backtrace);
}
catch (utf8::invalid_utf8) {
string msg("utf8::invalid_utf8");
error(msg, path, position, backtrace);
}
return new (ctx.mem) Number(path, position, len);
}

Signature str_insert_sig = "str-insert($string, $insert, $index)";
BUILT_IN(str_insert)
{
String_Constant* s = ARG("$string", String_Constant);
string str = s->value();
char quotemark = s->quote_mark();
str = unquote(str);
String_Constant* i = ARG("$insert", String_Constant);
string ins = i->value();
ins = unquote(ins);
Number* ind = ARG("$index", Number);
double index = ind->value();
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::code_point_offset_to_byte_offset(str, 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::code_point_offset_to_byte_offset(str, index), ins);
string str;
try {
String_Constant* s = ARG("$string", String_Constant);
str = s->value();
char quotemark = s->quote_mark();
str = unquote(str);
String_Constant* i = ARG("$insert", String_Constant);
string ins = i->value();
ins = unquote(ins);
Number* ind = ARG("$index", Number);
double index = ind->value();
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, 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, index), ins);
}
else {
// negative and past string length
str = ins + str;
}

if (quotemark) {
str = quote(str, quotemark);
}
}
else {
// negative and past string length
str = ins + str;
catch (utf8::invalid_code_point) {
string msg("utf8::invalid_code_point");
error(msg, path, position, backtrace);
}

if (quotemark) {
str = quote(str, quotemark);
catch (utf8::not_enough_room) {
string msg("utf8::not_enough_room");
error(msg, path, position, backtrace);
}
catch (utf8::invalid_utf8) {
string msg("utf8::invalid_utf8");
error(msg, path, position, backtrace);
}

return new (ctx.mem) String_Constant(path, position, str);

}

Signature str_index_sig = "str-index($string, $substring)";
BUILT_IN(str_index)
{
String_Constant* s = ARG("$string", String_Constant);
String_Constant* t = ARG("$substring", String_Constant);
string str = s->value();
str = unquote(str);
string substr = t->value();
substr = unquote(substr);

size_t c_index = str.find(substr);
if(c_index == string::npos) {
return new (ctx.mem) Null(path, position);
size_t index;
try {
String_Constant* s = ARG("$string", String_Constant);
String_Constant* t = ARG("$substring", String_Constant);
string str = s->value();
str = unquote(str);
string substr = t->value();
substr = unquote(substr);

size_t c_index = str.find(substr);
if(c_index == string::npos) {
return new (ctx.mem) Null(path, position);
}
index = UTF_8::code_point_count(str, 0, c_index) + 1;
}
size_t index = UTF_8::code_point_count(str, 0, c_index + 1);

catch (utf8::invalid_code_point) {
string msg("utf8::invalid_code_point");
error(msg, path, position, backtrace);
}
catch (utf8::not_enough_room) {
string msg("utf8::not_enough_room");
error(msg, path, position, backtrace);
}
catch (utf8::invalid_utf8) {
string msg("utf8::invalid_utf8");
error(msg, path, position, backtrace);
}
// return something even even we had an error
return new (ctx.mem) Number(path, position, index);
}

Signature str_slice_sig = "str-slice($string, $start-at, $end-at:-1)";
BUILT_IN(str_slice)
{
String_Constant* s = ARG("$string", String_Constant);
Number* n = ARG("$start-at", Number);
Number* m = ARG("$end-at", Number);

string str = s->value();
char quotemark = s->quote_mark();
str = unquote(str);

// normalize into 0-based indices
size_t start = UTF_8::code_point_offset_to_byte_offset(str, UTF_8::normalize_index(n->value(), UTF_8::code_point_count(str)));
size_t end = UTF_8::code_point_offset_to_byte_offset(str, UTF_8::normalize_index(m->value(), UTF_8::code_point_count(str)));

string newstr;
if(start - end == 0) {
newstr = str.substr(start, end - start);
} else {
newstr = str.substr(start, end - start + UTF_8::length_of_code_point_at(str, end));
try {
String_Constant* s = ARG("$string", String_Constant);
Number* n = ARG("$start-at", Number);
Number* m = ARG("$end-at", Number);

string str = s->value();
char quotemark = s->quote_mark();
str = unquote(str);

// normalize into 0-based indices
size_t start = UTF_8::offset_at_position(str, UTF_8::normalize_index(n->value(), UTF_8::code_point_count(str)));
size_t end = UTF_8::offset_at_position(str, UTF_8::normalize_index(m->value(), UTF_8::code_point_count(str)));

if(start - end == 0) {
newstr = str.substr(start, end - start);
} else {
newstr = str.substr(start, end - start + UTF_8::code_point_size_at_offset(str, end));
}
if(quotemark) {
newstr = quote(newstr, quotemark);
}
}
if(quotemark) {
newstr = quote(newstr, quotemark);
catch (utf8::invalid_code_point) {
string msg("utf8::invalid_code_point");
error(msg, path, position, backtrace);
}
catch (utf8::not_enough_room) {
string msg("utf8::not_enough_room");
error(msg, path, position, backtrace);
}
catch (utf8::invalid_utf8) {
string msg("utf8::invalid_utf8");
error(msg, path, position, backtrace);
}

return new (ctx.mem) String_Constant(path, position, newstr);

}

Signature to_upper_case_sig = "to-upper-case($string)";
Expand Down
2 changes: 1 addition & 1 deletion sass2scss
Submodule sass2scss updated 2 files
+23 −11 README.md
+1 −1 sass2scss.cpp
34 changes: 34 additions & 0 deletions utf8.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2006 Nemanja Trifunovic

/*
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:

The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/


#ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731
#define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731

#include "utf8/checked.h"
#include "utf8/unchecked.h"

#endif // header guard
Loading