Removed SkSL::StringFragment in favor of string_view

This CL preserves the "StringFragment" name as an alias for
string_view to reduce the impact. The StringFragment alias
will be removed in a followup CL.

Change-Id: I89209bc626b0be0d0190823b6217f4c83cafe1bc
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/416736
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
This commit is contained in:
Ethan Nicholas 2021-06-10 11:21:59 -04:00 committed by Skia Commit-Bot
parent a1feabd383
commit d2e0960696
44 changed files with 263 additions and 453 deletions

View File

@ -624,6 +624,7 @@ if (skia_compile_processors || skia_compile_sksl_tests) {
"src/core/SkStream.cpp",
"src/core/SkString.cpp",
"src/core/SkStringUtils.cpp",
"src/core/SkStringView.cpp",
"src/core/SkThreadID.cpp",
"src/core/SkUtils.cpp",
"src/core/SkVM.cpp",

View File

@ -30,7 +30,7 @@ bool FuzzSKSL2Pipeline(sk_sp<SkData> bytes) {
using String = SkSL::String;
String declareUniform(const SkSL::VarDeclaration* decl) override {
return decl->var().name();
return String(decl->var().name());
}
void defineFunction(const char* /*decl*/, const char* /*body*/, bool /*isMain*/) override {}

View File

@ -20,6 +20,10 @@
#include <atomic>
#include <string>
namespace skstd {
class string_view;
}
/* Some helper functions for C strings */
static inline bool SkStrStartsWith(const char string[], const char prefixStr[]) {
SkASSERT(string);
@ -122,6 +126,7 @@ public:
SkString(const SkString&);
SkString(SkString&&);
explicit SkString(const std::string&);
explicit SkString(skstd::string_view);
~SkString();
bool isEmpty() const { return 0 == fRec->fLength; }

View File

@ -109,6 +109,15 @@ public:
other.fLength = tempLength;
}
constexpr void remove_prefix(size_type n) {
fData += n;
fLength -= n;
}
constexpr void remove_suffix(size_type n) {
fLength -= n;
}
private:
const_pointer fData;
size_type fLength;
@ -128,4 +137,16 @@ bool operator>=(string_view left, string_view right);
} // namespace skstd
namespace std {
template<> struct hash<skstd::string_view> {
size_t operator()(const skstd::string_view& s) const {
size_t result = 0;
for (auto iter = s.begin(); iter != s.end(); ++iter) {
result = result * 101 + (size_t) *iter;
}
return result;
}
};
} // namespace std
#endif

View File

@ -208,7 +208,7 @@ struct Layout {
if (fInvocations >= 0) {
result += separator() + "invocations = " + to_string(fInvocations);
}
if (fWhen.fLength) {
if (fWhen.length()) {
result += separator() + "when = " + fWhen;
}
if (result.size() > 0) {

View File

@ -22,62 +22,13 @@ namespace SkSL {
class String;
// Represents a (not necessarily null-terminated) slice of a string.
struct StringFragment {
StringFragment()
: fChars("")
, fLength(0) {}
StringFragment(const char* chars)
: fChars(chars)
, fLength(strlen(chars)) {}
StringFragment(const char* chars, size_t length)
: fChars(chars)
, fLength(length) {}
StringFragment(skstd::string_view s)
: fChars(s.data())
, fLength(s.length()) {}
const char* begin() const { return fChars; }
const char* end() const { return fChars + fLength; }
const char* data() const { return fChars; }
size_t size() const { return fLength; }
size_t length() const { return fLength; }
char operator[](size_t idx) const { return fChars[idx]; }
bool startsWith(const char prefix[]) const;
bool endsWith(const char suffix[]) const;
bool operator==(const char* s) const;
bool operator!=(const char* s) const;
bool operator==(StringFragment s) const;
bool operator!=(StringFragment s) const;
bool operator<(StringFragment s) const;
String operator+(const char* s) const;
String operator+(const StringFragment& s) const;
String operator+(const String& s) const;
#ifndef SKSL_STANDALONE
operator SkString() const { return SkString(fChars, fLength); }
#endif
const char* fChars;
size_t fLength;
};
bool operator==(const char* s1, StringFragment s2);
bool operator!=(const char* s1, StringFragment s2);
using StringFragment = skstd::string_view;
class SK_API String : public std::string {
public:
using std::string::string;
explicit String(std::string s) : INHERITED(std::move(s)) {}
String(StringFragment s) : INHERITED(s.fChars, s.fLength) {}
explicit String(skstd::string_view s) : INHERITED(s.data(), s.length()) {}
// TODO(johnstiles): add operator skstd::string_view
@ -85,11 +36,11 @@ public:
void appendf(const char* fmt, ...) SK_PRINTF_LIKE(2, 3);
void vappendf(const char* fmt, va_list va);
bool startsWith(const char prefix[]) const {
return StringFragment(data(), size()).startsWith(prefix);
bool starts_with(const char prefix[]) const {
return StringFragment(data(), size()).starts_with(prefix);
}
bool endsWith(const char suffix[]) const {
return StringFragment(data(), size()).endsWith(suffix);
bool ends_with(const char suffix[]) const {
return StringFragment(data(), size()).ends_with(suffix);
}
bool consumeSuffix(const char suffix[]);
@ -101,20 +52,13 @@ public:
String& operator+=(const char* s);
String& operator+=(const String& s);
String& operator+=(StringFragment s);
bool operator==(const char* s) const;
bool operator!=(const char* s) const;
bool operator==(const String& s) const;
bool operator!=(const String& s) const;
friend String operator+(const char* s1, const String& s2);
friend bool operator==(const char* s1, const String& s2);
friend bool operator!=(const char* s1, const String& s2);
private:
using INHERITED = std::string;
};
String operator+(const char* s1, const String& s2);
bool operator!=(const char* s1, const String& s2);
String operator+(StringFragment left, StringFragment right);
String to_string(double value);
String to_string(int32_t value);
@ -128,16 +72,6 @@ bool stoi(const StringFragment& s, SKSL_INT* value);
} // namespace SkSL
namespace std {
template<> struct hash<SkSL::StringFragment> {
size_t operator()(const SkSL::StringFragment& s) const {
size_t result = 0;
for (size_t i = 0; i < s.fLength; ++i) {
result = result * 101 + (size_t) s.fChars[i];
}
return result;
}
};
template<> struct hash<SkSL::String> {
size_t operator()(const SkSL::String& s) const {
return hash<std::string>{}(s);

View File

@ -223,7 +223,7 @@ SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl,
// Child effects that can be sampled ('shader' or 'colorFilter')
if (varType.isEffectChild()) {
Child c;
c.name = var.name();
c.name = SkString(var.name());
c.type = child_type(varType);
c.index = children.size();
children.push_back(c);
@ -233,7 +233,7 @@ SkRuntimeEffect::Result SkRuntimeEffect::Make(SkString sksl,
// 'uniform' variables
else if (var.modifiers().fFlags & SkSL::Modifiers::kUniform_Flag) {
Uniform uni;
uni.name = var.name();
uni.name = SkString(var.name());
uni.flags = 0;
uni.count = 1;

View File

@ -6,6 +6,7 @@
*/
#include "include/core/SkString.h"
#include "include/core/SkStringView.h"
#include "include/private/SkTPin.h"
#include "include/private/SkTo.h"
#include "src/core/SkSafeMath.h"
@ -294,6 +295,10 @@ SkString::SkString(const std::string& src) {
fRec = Rec::Make(src.c_str(), src.size());
}
SkString::SkString(skstd::string_view src) {
fRec = Rec::Make(src.data(), src.length());
}
SkString::~SkString() {
this->validate();
}

View File

@ -67,7 +67,7 @@ String ASTNode::description() const {
if (this->begin() != this->end()) {
return String(getString()) + " = " + this->begin()->description();
}
return getString();
return String(getString());
case Kind::kExtension:
return "#extension " + getString();
case Kind::kField:
@ -111,7 +111,7 @@ String ASTNode::description() const {
return result;
}
case Kind::kIdentifier:
return getString();
return String(getString());
case Kind::kIndex:
return this->begin()->description() + "[" + (this->begin() + 1)->description() + "]";
case Kind::kIf: {
@ -204,10 +204,10 @@ String ASTNode::description() const {
return "(" + this->begin()->description() + " ? " + (this->begin() + 1)->description() +
" : " + (this->begin() + 2)->description() + ")";
case Kind::kType:
return getString();
return String(getString());
case Kind::kVarDeclaration: {
const VarData& vd = getVarData();
String result = vd.fName;
String result(vd.fName);
auto iter = this->begin();
if (vd.fIsArray) {
result += "[" + (iter++)->description() + "]";

View File

@ -475,6 +475,7 @@ struct ASTNode {
return *reinterpret_cast<const SKSL_FLOAT*>(fData.fBytes);
}
// TODO(ethannicholas): Rename this to getStringView() as part of changing the return type
const StringFragment& getString() const {
SkASSERT(fData.fKind == NodeData::Kind::kStringFragment);
return *reinterpret_cast<const StringFragment*>(fData.fBytes);

View File

@ -409,20 +409,20 @@ ParsedModule Compiler::parseModule(ProgramKind kind, ModuleData data, const Pars
case ProgramElement::Kind::kEnum: {
const Enum& e = element->as<Enum>();
SkASSERT(e.isBuiltin());
intrinsics->insertOrDie(e.typeName(), std::move(element));
intrinsics->insertOrDie(String(e.typeName()), std::move(element));
break;
}
case ProgramElement::Kind::kGlobalVar: {
const GlobalVarDeclaration& global = element->as<GlobalVarDeclaration>();
const Variable& var = global.declaration()->as<VarDeclaration>().var();
SkASSERT(var.isBuiltin());
intrinsics->insertOrDie(var.name(), std::move(element));
intrinsics->insertOrDie(String(var.name()), std::move(element));
break;
}
case ProgramElement::Kind::kInterfaceBlock: {
const Variable& var = element->as<InterfaceBlock>().variable();
SkASSERT(var.isBuiltin());
intrinsics->insertOrDie(var.name(), std::move(element));
intrinsics->insertOrDie(String(var.name()), std::move(element));
break;
}
default:

View File

@ -270,7 +270,7 @@ void IRGenerator::checkVarDeclaration(int offset, const Modifiers& modifiers, co
offset,
"'in uniform' variables only permitted within fragment processors");
}
if (modifiers.fLayout.fWhen.fLength) {
if (modifiers.fLayout.fWhen.length()) {
this->errorReporter().error(offset,
"'when' is only permitted within fragment processors");
}
@ -1061,7 +1061,8 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
}
}
}
const Type* type = old->takeOwnershipOfSymbol(Type::MakeStructType(intf.fOffset, id.fTypeName,
const Type* type = old->takeOwnershipOfSymbol(Type::MakeStructType(intf.fOffset,
String(id.fTypeName),
fields));
int arraySize = 0;
if (id.fIsArray) {
@ -1082,14 +1083,14 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
const Variable* var = old->takeOwnershipOfSymbol(
std::make_unique<Variable>(intf.fOffset,
this->modifiersPool().add(id.fModifiers),
id.fInstanceName.fLength ? id.fInstanceName : id.fTypeName,
id.fInstanceName.length() ? id.fInstanceName : id.fTypeName,
type,
fIsBuiltinCode,
Variable::Storage::kGlobal));
if (foundRTAdjust) {
fRTAdjustInterfaceBlock = var;
}
if (id.fInstanceName.fLength) {
if (id.fInstanceName.length()) {
old->addWithoutOwnership(var);
} else {
for (size_t i = 0; i < fields.size(); i++) {
@ -1098,8 +1099,8 @@ std::unique_ptr<InterfaceBlock> IRGenerator::convertInterfaceBlock(const ASTNode
}
return std::make_unique<InterfaceBlock>(intf.fOffset,
var,
id.fTypeName,
id.fInstanceName,
String(id.fTypeName),
String(id.fInstanceName),
arraySize,
symbols);
}
@ -1334,8 +1335,7 @@ std::unique_ptr<Section> IRGenerator::convertSection(const ASTNode& s) {
}
const ASTNode::SectionData& section = s.getSectionData();
return std::make_unique<Section>(s.fOffset, section.fName, section.fArgument,
section.fText);
return std::make_unique<Section>(s.fOffset, section.fName, section.fArgument, section.fText);
}
std::unique_ptr<Expression> IRGenerator::coerce(std::unique_ptr<Expression> expr,
@ -1526,7 +1526,7 @@ std::unique_ptr<Expression> IRGenerator::convertPrefixExpression(const ASTNode&
// secondary swizzle to put them back into the right order, so in this case we end up with
// 'float4(base.xw, 1, 0).xzyw'.
std::unique_ptr<Expression> IRGenerator::convertSwizzle(std::unique_ptr<Expression> base,
String fields) {
StringFragment fields) {
const int offset = base->fOffset;
const Type& baseType = base->type();
if (!baseType.isVector() && !baseType.isNumber()) {
@ -1623,7 +1623,7 @@ std::unique_ptr<Expression> IRGenerator::convertTypeField(int offset, const Type
}
// ... and if that fails, check the intrinsics, add it to our shared elements
if (!enumElement && !fIsBuiltinCode && fIntrinsics) {
if (const ProgramElement* found = fIntrinsics->findAndInclude(type.name())) {
if (const ProgramElement* found = fIntrinsics->findAndInclude(String(type.name()))) {
fSharedElements->push_back(found);
enumElement = found;
}
@ -1792,7 +1792,7 @@ void IRGenerator::findAndDeclareBuiltinVariables() {
bool visitExpression(const Expression& e) override {
if (e.is<VariableReference>() && e.as<VariableReference>().variable()->isBuiltin()) {
this->addDeclaringElement(e.as<VariableReference>().variable()->name());
this->addDeclaringElement(String(e.as<VariableReference>().variable()->name()));
}
return INHERITED::visitExpression(e);
}

View File

@ -222,7 +222,8 @@ private:
std::unique_ptr<StructDefinition> convertStructDefinition(const ASTNode& expression);
std::unique_ptr<Expression> convertTypeField(int offset, const Type& type,
StringFragment field);
std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base, String fields);
std::unique_ptr<Expression> convertSwizzle(std::unique_ptr<Expression> base,
StringFragment fields);
std::unique_ptr<Expression> convertTernaryExpression(const ASTNode& expression);
std::unique_ptr<Statement> convertVarDeclarationStatement(const ASTNode& s);
std::unique_ptr<Statement> convertWhile(const ASTNode& w);

View File

@ -541,7 +541,7 @@ std::unique_ptr<Statement> Inliner::inlineStatement(int offset,
// regard, but see `InlinerAvoidsVariableNameOverlap` for a counterexample where unique
// names are important.
const String* name = symbolTableForStatement->takeOwnershipOfString(
fMangler.uniqueName(variable.name(), symbolTableForStatement));
fMangler.uniqueName(String(variable.name()), symbolTableForStatement));
auto clonedVar = std::make_unique<Variable>(
offset,
&variable.modifiers(),
@ -640,7 +640,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
// for void-return functions, or in cases that are simple enough that we can just replace
// the function-call node with the result expression.
std::unique_ptr<Expression> noInitialValue;
InlineVariable var = this->makeInlineVariable(function.declaration().name(),
InlineVariable var = this->makeInlineVariable(String(function.declaration().name()),
&function.declaration().returnType(),
symbolTable.get(), Modifiers{},
caller->isBuiltin(), &noInitialValue);
@ -665,7 +665,7 @@ Inliner::InlinedCall Inliner::inlineCall(FunctionCall* call,
continue;
}
}
InlineVariable var = this->makeInlineVariable(param->name(), &arguments[i]->type(),
InlineVariable var = this->makeInlineVariable(String(param->name()), &arguments[i]->type(),
symbolTable.get(), param->modifiers(),
caller->isBuiltin(), &arguments[i]);
inlineStatements.push_back(std::move(var.fVarDecl));

View File

@ -283,19 +283,19 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
SkSL::ProgramKind kind;
const SkSL::String& inputPath = args[1];
if (inputPath.endsWith(".vert")) {
if (inputPath.ends_with(".vert")) {
kind = SkSL::ProgramKind::kVertex;
} else if (inputPath.endsWith(".frag") || inputPath.endsWith(".sksl")) {
} else if (inputPath.ends_with(".frag") || inputPath.ends_with(".sksl")) {
kind = SkSL::ProgramKind::kFragment;
} else if (inputPath.endsWith(".geom")) {
} else if (inputPath.ends_with(".geom")) {
kind = SkSL::ProgramKind::kGeometry;
} else if (inputPath.endsWith(".fp")) {
} else if (inputPath.ends_with(".fp")) {
kind = SkSL::ProgramKind::kFragmentProcessor;
} else if (inputPath.endsWith(".rtb")) {
} else if (inputPath.ends_with(".rtb")) {
kind = SkSL::ProgramKind::kRuntimeBlend;
} else if (inputPath.endsWith(".rtcf")) {
} else if (inputPath.ends_with(".rtcf")) {
kind = SkSL::ProgramKind::kRuntimeColorFilter;
} else if (inputPath.endsWith(".rts")) {
} else if (inputPath.ends_with(".rts")) {
kind = SkSL::ProgramKind::kRuntimeShader;
} else {
printf("input filename must end in '.vert', '.frag', '.geom', '.fp', '.rtb', '.rtcf', "
@ -350,13 +350,13 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
return ResultCode::kSuccess;
};
if (outputPath.endsWith(".spirv")) {
if (outputPath.ends_with(".spirv")) {
return compileProgram(
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toSPIRV(program, out);
});
} else if (outputPath.endsWith(".asm.frag") || outputPath.endsWith(".asm.vert") ||
outputPath.endsWith(".asm.geom")) {
} else if (outputPath.ends_with(".asm.frag") || outputPath.ends_with(".asm.vert") ||
outputPath.ends_with(".asm.geom")) {
return compileProgram(
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
// Compile program to SPIR-V assembly in a string-stream.
@ -376,24 +376,24 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
out.write(disassembly.data(), disassembly.size());
return true;
});
} else if (outputPath.endsWith(".glsl")) {
} else if (outputPath.ends_with(".glsl")) {
return compileProgram(
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toGLSL(program, out);
});
} else if (outputPath.endsWith(".metal")) {
} else if (outputPath.ends_with(".metal")) {
return compileProgram(
[](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toMetal(program, out);
});
} else if (outputPath.endsWith(".h")) {
} else if (outputPath.ends_with(".h")) {
settings.fReplaceSettings = false;
settings.fPermitInvalidStaticTests = true;
return compileProgram(
[&](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toH(program, base_name(inputPath.c_str(), "Gr", ".fp"), out);
});
} else if (outputPath.endsWith(".dsl.cpp")) {
} else if (outputPath.ends_with(".dsl.cpp")) {
settings.fReplaceSettings = false;
settings.fPermitInvalidStaticTests = true;
return compileProgram(
@ -401,14 +401,14 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
return compiler.toDSLCPP(program, base_name(inputPath.c_str(), "Gr", ".fp"),
out);
});
} else if (outputPath.endsWith(".cpp")) {
} else if (outputPath.ends_with(".cpp")) {
settings.fReplaceSettings = false;
settings.fPermitInvalidStaticTests = true;
return compileProgram(
[&](SkSL::Compiler& compiler, SkSL::Program& program, SkSL::OutputStream& out) {
return compiler.toCPP(program, base_name(inputPath.c_str(), "Gr", ".fp"), out);
});
} else if (outputPath.endsWith(".skvm")) {
} else if (outputPath.ends_with(".skvm")) {
return compileProgram(
[](SkSL::Compiler&, SkSL::Program& program, SkSL::OutputStream& out) {
skvm::Builder builder{skvm::Features{}};
@ -420,7 +420,7 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
builder.done().dump(redirect.get());
return true;
});
} else if (outputPath.endsWith(".stage")) {
} else if (outputPath.ends_with(".stage")) {
return compileProgram(
[](SkSL::Compiler&, SkSL::Program& program, SkSL::OutputStream& out) {
class Callbacks : public SkSL::PipelineStage::Callbacks {
@ -433,7 +433,7 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
String declareUniform(const SkSL::VarDeclaration* decl) override {
fOutput += decl->description();
return decl->var().name();
return String(decl->var().name());
}
void defineFunction(const char* decl,
@ -481,7 +481,7 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
out.writeString(GrShaderUtils::PrettyPrint(callbacks.fOutput));
return true;
});
} else if (outputPath.endsWith(".dehydrated.sksl")) {
} else if (outputPath.ends_with(".dehydrated.sksl")) {
SkSL::FileOutputStream out(outputPath);
SkSL::Compiler compiler(caps);
if (!out.isValid()) {
@ -522,7 +522,7 @@ ResultCode processCommand(std::vector<SkSL::String>& args) {
*/
ResultCode processWorklist(const char* worklistPath) {
SkSL::String inputPath(worklistPath);
if (!inputPath.endsWith(".worklist")) {
if (!inputPath.ends_with(".worklist")) {
printf("expected .worklist file, found: %s\n\n", worklistPath);
show_usage();
return ResultCode::kConfigurationError;

View File

@ -14,7 +14,7 @@ String Mangler::uniqueName(String baseName, SymbolTable* symbolTable) {
SkASSERT(symbolTable);
// The inliner runs more than once, so the base name might already have been mangled and have a
// prefix like "_123_x". Let's strip that prefix off to make the generated code easier to read.
if (baseName.startsWith("_")) {
if (baseName.starts_with("_")) {
// Determine if we have a string of digits.
int offset = 1;
while (isdigit(baseName[offset])) {

View File

@ -335,14 +335,14 @@ ASTNode::ID Parser::section() {
if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
return ASTNode::ID::Invalid();
}
StringFragment text;
Token codeStart = this->nextRawToken();
size_t startOffset = codeStart.fOffset;
this->pushback(codeStart);
text.fChars = fText.begin() + startOffset;
int level = 1;
for (;;) {
Token next = this->nextRawToken();
StringFragment text;
Token next;
while (level > 0) {
next = this->nextRawToken();
switch (next.fKind) {
case Token::Kind::TK_LBRACE:
++level;
@ -356,14 +356,10 @@ ASTNode::ID Parser::section() {
default:
break;
}
if (!level) {
text.fLength = next.fOffset - startOffset;
break;
}
}
text = StringFragment(fText.begin() + startOffset, next.fOffset - startOffset);
StringFragment name = this->text(start);
++name.fChars;
--name.fLength;
name.remove_prefix(1);
return this->createNode(start.fOffset, ASTNode::Kind::kSection,
ASTNode::SectionData(name, argument, text));
}
@ -385,7 +381,7 @@ ASTNode::ID Parser::enumDeclaration() {
if (!this->expect(Token::Kind::TK_LBRACE, "'{'")) {
return ASTNode::ID::Invalid();
}
fSymbols.add(Type::MakeEnumType(this->text(name)));
fSymbols.add(Type::MakeEnumType(String(this->text(name))));
ASTNode::ID result = this->createNode(name.fOffset, ASTNode::Kind::kEnum, this->text(name));
if (!this->checkNext(Token::Kind::TK_RBRACE)) {
Token id;
@ -629,7 +625,8 @@ ASTNode::ID Parser::structDeclaration() {
"struct '" + this->text(name) + "' must contain at least one field");
return ASTNode::ID::Invalid();
}
std::unique_ptr<Type> newType = Type::MakeStructType(name.fOffset, this->text(name), fields);
std::unique_ptr<Type> newType = Type::MakeStructType(name.fOffset, String(this->text(name)),
fields);
if (struct_is_too_deeply_nested(*newType, kMaxStructDepth)) {
this->error(name.fOffset, "struct '" + this->text(name) + "' is too deeply nested");
return ASTNode::ID::Invalid();
@ -809,7 +806,6 @@ StringFragment Parser::layoutCode() {
Token start = this->nextRawToken();
this->pushback(start);
StringFragment code;
code.fChars = fText.begin() + start.fOffset;
int level = 1;
bool done = false;
while (!done) {
@ -836,7 +832,7 @@ StringFragment Parser::layoutCode() {
done = true;
}
if (done) {
code.fLength = next.fOffset - start.fOffset;
code = StringFragment(fText.begin() + start.fOffset, next.fOffset - start.fOffset);
this->pushback(std::move(next));
}
}
@ -846,7 +842,7 @@ StringFragment Parser::layoutCode() {
Layout::CType Parser::layoutCType() {
if (this->expect(Token::Kind::TK_EQ, "'='")) {
Token t = this->nextToken();
String text = this->text(t);
String text(this->text(t));
auto found = layoutTokens->find(text);
if (found != layoutTokens->end()) {
switch (found->second) {
@ -885,7 +881,7 @@ Layout Parser::layout() {
}
for (;;) {
Token t = this->nextToken();
String text = this->text(t);
String text(this->text(t));
auto setFlag = [&](Layout::Flag f) {
if (flags & f) {
this->error(t, "layout qualifier '" + text + "' appears more than once");
@ -2021,11 +2017,10 @@ ASTNode::ID Parser::suffix(ASTNode::ID base) {
// Swizzles that start with a constant number, e.g. '.000r', will be tokenized as
// floating point literals, possibly followed by an identifier. Handle that here.
StringFragment field = this->text(next);
SkASSERT(field.fChars[0] == '.');
++field.fChars;
--field.fLength;
for (size_t i = 0; i < field.fLength; ++i) {
if (field.fChars[i] != '0' && field.fChars[i] != '1') {
SkASSERT(field[0] == '.');
field.remove_prefix(1);
for (auto iter = field.begin(); iter != field.end(); ++iter) {
if (*iter != '0' && *iter != '1') {
this->error(next, "invalid swizzle");
return ASTNode::ID::Invalid();
}
@ -2034,7 +2029,7 @@ ASTNode::ID Parser::suffix(ASTNode::ID base) {
// identifiers that directly follow the float
Token id = this->nextRawToken();
if (id.fKind == Token::Kind::TK_IDENTIFIER) {
field.fLength += id.fLength;
field = StringFragment(field.data(), field.length() + id.fLength);
} else {
this->pushback(id);
}

View File

@ -150,7 +150,7 @@ const Symbol* Rehydrator::symbol() {
uint16_t id = this->readU16();
const Type* componentType = this->type();
int8_t count = this->readS8();
String name = componentType->name();
String name(componentType->name());
if (count == Type::kUnsizedArray) {
name += "[]";
} else {
@ -164,7 +164,8 @@ const Symbol* Rehydrator::symbol() {
case kEnumType_Command: {
uint16_t id = this->readU16();
StringFragment name = this->readString();
const Type* result = fSymbolTable->takeOwnershipOfSymbol(Type::MakeEnumType(name));
const Type* result =
fSymbolTable->takeOwnershipOfSymbol(Type::MakeEnumType(String(name)));
this->addSymbol(id, result);
return result;
}
@ -199,7 +200,7 @@ const Symbol* Rehydrator::symbol() {
}
case kStructType_Command: {
uint16_t id = this->readU16();
StringFragment name = this->readString();
String name(this->readString());
uint8_t fieldCount = this->readU8();
std::vector<Type::Field> fields;
fields.reserve(fieldCount);
@ -324,11 +325,12 @@ std::unique_ptr<ProgramElement> Rehydrator::element() {
case Rehydrator::kInterfaceBlock_Command: {
const Symbol* var = this->symbol();
SkASSERT(var && var->is<Variable>());
StringFragment typeName = this->readString();
StringFragment instanceName = this->readString();
String typeName(this->readString());
String instanceName(this->readString());
int arraySize = this->readS8();
return std::make_unique<InterfaceBlock>(/*offset=*/-1, &var->as<Variable>(), typeName,
instanceName, arraySize, nullptr);
return std::make_unique<InterfaceBlock>(/*offset=*/-1, &var->as<Variable>(),
std::move(typeName), std::move(instanceName),
arraySize, nullptr);
}
case Rehydrator::kVarDeclarations_Command: {
std::unique_ptr<Statement> decl = this->statement();
@ -543,7 +545,7 @@ std::unique_ptr<Expression> Rehydrator::expression() {
return PrefixExpression::Make(fContext, op, std::move(operand));
}
case Rehydrator::kSetting_Command: {
StringFragment name = this->readString();
String name(this->readString());
return Setting::Convert(fContext, /*offset=*/-1, name);
}
case Rehydrator::kSwizzle_Command: {

View File

@ -38,15 +38,15 @@ SectionAndParameterHelper::SectionAndParameterHelper(const Program* program, Err
}
case ProgramElement::Kind::kSection: {
const Section& s = p->as<Section>();
const String& name = s.name();
const String& arg = s.argument();
if (IsSupportedSection(name.c_str())) {
if (SectionRequiresArgument(name.c_str()) && !arg.size()) {
StringFragment name = s.name();
StringFragment arg = s.argument();
if (IsSupportedSection(name)) {
if (SectionRequiresArgument(name) && !arg.size()) {
errors.error(s.fOffset,
("section '@" + name +
"' requires one parameter").c_str());
}
if (!SectionAcceptsArgument(name.c_str()) && arg.size()) {
if (!SectionAcceptsArgument(name) && arg.size()) {
errors.error(s.fOffset,
("section '@" + name + "' has no parameters").c_str());
}

View File

@ -39,7 +39,7 @@ class SectionAndParameterHelper {
public:
SectionAndParameterHelper(const Program* program, ErrorReporter& errors);
const Section* getSection(const char* name) {
const Section* getSection(StringFragment name) {
auto found = fSections.find(name);
if (found == fSections.end()) {
return nullptr;
@ -48,7 +48,7 @@ public:
return found->second[0];
}
std::vector<const Section*> getSections(const char* name) {
std::vector<const Section*> getSections(StringFragment name) {
auto found = fSections.find(name);
if (found == fSections.end()) {
return std::vector<const Section*>();
@ -65,40 +65,38 @@ public:
-1 == var.modifiers().fLayout.fBuiltin;
}
static bool IsSupportedSection(const char* name) {
return !strcmp(name, kClassSection) ||
!strcmp(name, kCloneSection) ||
!strcmp(name, kConstructorSection) ||
!strcmp(name, kConstructorCodeSection) ||
!strcmp(name, kConstructorParamsSection) ||
!strcmp(name, kCppSection) ||
!strcmp(name, kCppEndSection) ||
!strcmp(name, kDumpInfoSection) ||
!strcmp(name, kEmitCodeSection) ||
!strcmp(name, kFieldsSection) ||
!strcmp(name, kHeaderSection) ||
!strcmp(name, kHeaderEndSection) ||
!strcmp(name, kInitializersSection) ||
!strcmp(name, kMakeSection) ||
!strcmp(name, kOptimizationFlagsSection) ||
!strcmp(name, kSetDataSection) ||
!strcmp(name, kTestCodeSection);
static bool IsSupportedSection(StringFragment name) {
return name == kClassSection ||
name == kCloneSection ||
name == kConstructorSection ||
name == kConstructorCodeSection ||
name == kConstructorParamsSection ||
name == kCppSection ||
name == kCppEndSection ||
name == kDumpInfoSection ||
name == kEmitCodeSection ||
name == kFieldsSection ||
name == kHeaderSection ||
name == kHeaderEndSection ||
name == kInitializersSection ||
name == kMakeSection ||
name == kOptimizationFlagsSection ||
name == kSetDataSection ||
name == kTestCodeSection;
}
static bool SectionAcceptsArgument(const char* name) {
return !strcmp(name, kSetDataSection) ||
!strcmp(name, kTestCodeSection);
static bool SectionAcceptsArgument(StringFragment name) {
return name == kSetDataSection || name == kTestCodeSection;
}
static bool SectionRequiresArgument(const char* name) {
return !strcmp(name, kSetDataSection) ||
!strcmp(name, kTestCodeSection);
static bool SectionRequiresArgument(StringFragment name) {
return name == kSetDataSection || name == kTestCodeSection;
}
private:
const Program& fProgram;
std::vector<const Variable*> fParameters;
std::unordered_map<String, std::vector<const Section*>> fSections;
std::unordered_map<StringFragment, std::vector<const Section*>> fSections;
};
} // namespace SkSL

View File

@ -49,18 +49,6 @@ void String::vappendf(const char* fmt, va_list args) {
va_end(reuse);
}
bool StringFragment::startsWith(const char prefix[]) const {
return !strncmp(fChars, prefix, strlen(prefix));
}
bool StringFragment::endsWith(const char suffix[]) const {
size_t suffixLength = strlen(suffix);
if (fLength < suffixLength) {
return false;
}
return !strncmp(fChars + fLength - suffixLength, suffix, suffixLength);
}
bool String::consumeSuffix(const char suffix[]) {
size_t suffixLength = strlen(suffix);
if (this->length() < suffixLength) {
@ -87,7 +75,7 @@ String String::operator+(const String& s) const {
String String::operator+(StringFragment s) const {
String result(*this);
result.append(s.fChars, s.fLength);
result.append(s.data(), s.length());
return result;
}
@ -107,98 +95,18 @@ String& String::operator+=(const String& s) {
}
String& String::operator+=(StringFragment s) {
this->append(s.fChars, s.fLength);
this->append(s.data(), s.length());
return *this;
}
bool String::operator==(const String& s) const {
return this->size() == s.size() && !memcmp(c_str(), s.c_str(), this->size());
}
bool String::operator!=(const String& s) const {
return !(*this == s);
}
bool String::operator==(const char* s) const {
return this->size() == strlen(s) && !memcmp(c_str(), s, this->size());
}
bool String::operator!=(const char* s) const {
return !(*this == s);
}
String operator+(const char* s1, const String& s2) {
String result(s1);
result.append(s2);
return result;
}
bool operator==(const char* s1, const String& s2) {
return s2 == s1;
}
bool operator!=(const char* s1, const String& s2) {
return s2 != s1;
}
bool StringFragment::operator==(StringFragment s) const {
if (fLength != s.fLength) {
return false;
}
return !memcmp(fChars, s.fChars, fLength);
}
bool StringFragment::operator!=(StringFragment s) const {
if (fLength != s.fLength) {
return true;
}
return memcmp(fChars, s.fChars, fLength);
}
bool StringFragment::operator==(const char* s) const {
for (size_t i = 0; i < fLength; ++i) {
if (fChars[i] != s[i]) {
return false;
}
}
return 0 == s[fLength];
}
bool StringFragment::operator!=(const char* s) const {
for (size_t i = 0; i < fLength; ++i) {
if (fChars[i] != s[i]) {
return true;
}
}
return 0 != s[fLength];
}
bool StringFragment::operator<(StringFragment other) const {
int comparison = strncmp(fChars, other.fChars, std::min(fLength, other.fLength));
if (comparison) {
return comparison < 0;
}
return fLength < other.fLength;
}
String StringFragment::operator+(const char* other) const {
return String(*this) + other;
}
String StringFragment::operator+(const StringFragment& other) const {
return String(*this) + other;
}
String StringFragment::operator+(const String& other) const {
return String(*this) + other;
}
bool operator==(const char* s1, StringFragment s2) {
return s2 == s1;
}
bool operator!=(const char* s1, StringFragment s2) {
return s2 != s1;
String operator+(StringFragment left, StringFragment right) {
return String(left) + right;
}
String to_string(int32_t value) {

View File

@ -63,7 +63,7 @@ bool CPPCodeGenerator::usesPrecisionModifiers() const {
}
String CPPCodeGenerator::getTypeName(const Type& type) {
return type.name();
return String(type.name());
}
void CPPCodeGenerator::writeBinaryExpression(const BinaryExpression& b,
@ -227,7 +227,7 @@ void CPPCodeGenerator::writeRuntimeValue(const Type& type, const Layout& layout,
void CPPCodeGenerator::writeVarInitializer(const Variable& var, const Expression& value) {
if (is_private(var)) {
this->writeRuntimeValue(var.type(), var.modifiers().fLayout, var.name());
this->writeRuntimeValue(var.type(), var.modifiers().fLayout, String(var.name()));
} else {
this->writeExpression(value, Precedence::kTopLevel);
}
@ -268,11 +268,11 @@ void CPPCodeGenerator::writeVariableReference(const VariableReference& ref) {
const Variable& var = *ref.variable();
if (var.modifiers().fFlags & Modifiers::kUniform_Flag) {
this->write("%s");
String name = var.name();
String name(var.name());
String varCode = String::printf("args.fUniformHandler->getUniformCStr(%sVar)",
HCodeGenerator::FieldName(name.c_str()).c_str());
String code;
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
code = String::printf("%sVar.isValid() ? %s : \"%s\"",
HCodeGenerator::FieldName(name.c_str()).c_str(),
varCode.c_str(),
@ -456,7 +456,7 @@ void CPPCodeGenerator::prepareHelperFunction(const FunctionDeclaration& decl) {
return;
}
String funcName = decl.name();
String funcName(decl.name());
this->addExtraEmitCodeLine(
String::printf("SkString %s_name = fragBuilder->getMangledFunctionName(\"%s\");",
funcName.c_str(),
@ -465,7 +465,7 @@ void CPPCodeGenerator::prepareHelperFunction(const FunctionDeclaration& decl) {
String args = String::printf("const GrShaderVar %s_args[] = { ", funcName.c_str());
const char* separator = "";
for (const Variable* param : decl.parameters()) {
String paramName = param->name();
String paramName(param->name());
args.appendf("%sGrShaderVar(\"%s\", %s)", separator, paramName.c_str(),
glsltype_string(fContext, param->type()));
separator = ", ";
@ -476,7 +476,7 @@ void CPPCodeGenerator::prepareHelperFunction(const FunctionDeclaration& decl) {
}
void CPPCodeGenerator::prototypeHelperFunction(const FunctionDeclaration& decl) {
String funcName = decl.name();
String funcName(decl.name());
this->addExtraEmitCodeLine(String::printf(
"fragBuilder->emitFunctionPrototype(%s, %s_name.c_str(), {%s_args, %zu});",
glsltype_string(fContext, decl.returnType()),
@ -512,7 +512,7 @@ void CPPCodeGenerator::writeFunction(const FunctionDefinition& f) {
}
fOut = oldOut;
String funcName = decl.name();
String funcName(decl.name());
String funcImpl;
if (!fFormatArgs.empty()) {
@ -576,7 +576,7 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
if (!needs_uniform_var(var)) {
return;
}
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
this->writef(" if (%s) {\n ", String(var.modifiers().fLayout.fWhen).c_str());
}
String name(var.name());
@ -594,7 +594,7 @@ void CPPCodeGenerator::addUniform(const Variable& var) {
name.c_str(),
var.type().columns());
}
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
this->write(" }\n");
}
}
@ -946,7 +946,8 @@ void CPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
}
this->writef("%s%s;\n",
indent.c_str(), mapper->setUniform(pdman, uniformName, valueVar).c_str());
indent.c_str(),
mapper->setUniform(String(pdman), uniformName, valueVar).c_str());
if (conditionalUniform) {
// Close the earlier precheck block
@ -1044,7 +1045,7 @@ void CPPCodeGenerator::writeDumpInfo() {
String fieldName = HCodeGenerator::FieldName(String(param->name()).c_str());
String runtimeValue = this->formatRuntimeValue(param->type(),
param->modifiers().fLayout,
param->name(),
String(param->name()),
&argumentList);
formatString.appendf("%s%s=%s",
formatString.empty() ? "" : ", ",
@ -1151,7 +1152,7 @@ void CPPCodeGenerator::writeGetKey() {
}
this->write(";\n");
}
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
this->writef("if (%s) {", String(var.modifiers().fLayout.fWhen).c_str());
}
if (varType == *fContext.fTypes.fHalf4) {
@ -1184,7 +1185,7 @@ void CPPCodeGenerator::writeGetKey() {
SK_ABORT("NOT YET IMPLEMENTED: automatic key handling for %s\n",
varType.displayName().c_str());
}
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
this->write("}");
}
}

View File

@ -546,7 +546,7 @@ void DSLCPPCodeGenerator::writeCppInitialValue(const Variable& var) {
// the variable (which we do need, to fill in the Var's initial value).
std::vector<String> argumentList;
(void) this->formatRuntimeValue(var.type(), var.modifiers().fLayout,
var.name(), &argumentList);
String(var.name()), &argumentList);
this->write(this->getTypeName(var.type()));
this->write("(");
@ -690,7 +690,7 @@ void DSLCPPCodeGenerator::writeAnyConstructor(const AnyConstructor& c,
String DSLCPPCodeGenerator::getTypeName(const Type& type) {
if (fCPPMode) {
return type.name();
return String(type.name());
}
switch (type.typeKind()) {
case Type::TypeKind::kScalar:
@ -711,7 +711,7 @@ String DSLCPPCodeGenerator::getTypeName(const Type& type) {
default:
SK_ABORT("not yet supported: getTypeName of %s", type.displayName().c_str());
return type.name();
return String(type.name());
}
}
@ -741,7 +741,7 @@ String DSLCPPCodeGenerator::getDSLType(const Type& type) {
}
default:
SK_ABORT("not yet supported: getDSLType of %s", type.displayName().c_str());
return type.name();
return String(type.name());
}
}
@ -889,7 +889,7 @@ void DSLCPPCodeGenerator::addUniform(const Variable& var) {
}
const char* varCppName = this->getVariableCppName(var);
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
// In cases where the `when` clause is true, we set up the Var normally.
this->writef(
"Var %s;\n"
@ -906,7 +906,7 @@ void DSLCPPCodeGenerator::addUniform(const Variable& var) {
this->writef("%.*sVar = VarUniformHandle(%s);\n",
(int)var.name().size(), var.name().data(), this->getVariableCppName(var));
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
this->writef(" DeclareGlobal(%s);\n", varCppName);
// In cases where the `when` is false, we declare the Var as a const with a default value.
this->writef("} else {\n"
@ -1068,7 +1068,8 @@ void DSLCPPCodeGenerator::writeSetData(std::vector<const Variable*>& uniforms) {
}
this->writef("%s%s;\n",
indent.c_str(), mapper->setUniform(pdman, uniformName, valueVar).c_str());
indent.c_str(),
mapper->setUniform(String(pdman), uniformName, valueVar).c_str());
if (conditionalUniform) {
// Close the earlier precheck block
@ -1165,7 +1166,7 @@ void DSLCPPCodeGenerator::writeDumpInfo() {
String fieldName = HCodeGenerator::FieldName(String(param->name()).c_str());
String runtimeValue = this->formatRuntimeValue(param->type(),
param->modifiers().fLayout,
param->name(),
String(param->name()),
&argumentList);
formatString.appendf("%s%s=%s",
formatString.empty() ? "" : ", ",
@ -1271,7 +1272,7 @@ void DSLCPPCodeGenerator::writeGetKey() {
}
this->write(";\n");
}
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
this->writef("if (%s) {\n", String(var.modifiers().fLayout.fWhen).c_str());
}
if (varType == *fContext.fTypes.fHalf4) {
@ -1304,7 +1305,7 @@ void DSLCPPCodeGenerator::writeGetKey() {
SK_ABORT("NOT YET IMPLEMENTED: automatic key handling for %s\n",
varType.displayName().c_str());
}
if (var.modifiers().fLayout.fWhen.fLength) {
if (var.modifiers().fLayout.fWhen.length()) {
this->write("}\n");
}
}

View File

@ -24,30 +24,8 @@
namespace SkSL {
void GLSLCodeGenerator::write(const char* s) {
if (s[0] == 0) {
return;
}
if (fAtLineStart) {
for (int i = 0; i < fIndentation; i++) {
fOut->writeText(" ");
}
}
fOut->writeText(s);
fAtLineStart = false;
}
void GLSLCodeGenerator::writeLine(const char* s) {
this->write(s);
this->writeLine();
}
void GLSLCodeGenerator::write(const String& s) {
this->write(s.c_str());
}
void GLSLCodeGenerator::write(StringFragment s) {
if (!s.fLength) {
if (!s.length()) {
return;
}
if (fAtLineStart) {
@ -55,15 +33,12 @@ void GLSLCodeGenerator::write(StringFragment s) {
fOut->writeText(" ");
}
}
fOut->write(s.fChars, s.fLength);
fOut->write(s.data(), s.length());
fAtLineStart = false;
}
void GLSLCodeGenerator::writeLine(const String& s) {
this->writeLine(s.c_str());
}
void GLSLCodeGenerator::writeLine() {
void GLSLCodeGenerator::writeLine(StringFragment s) {
this->write(s);
fOut->writeText(fLineEnding);
fAtLineStart = true;
}
@ -74,13 +49,9 @@ void GLSLCodeGenerator::finishLine() {
}
}
void GLSLCodeGenerator::writeExtension(const String& name) {
this->writeExtension(name, true);
}
void GLSLCodeGenerator::writeExtension(const String& name, bool require) {
void GLSLCodeGenerator::writeExtension(StringFragment name, bool require) {
fExtensions.writeText("#extension ");
fExtensions.write(name.c_str(), name.length());
fExtensions.write(name.data(), name.length());
fExtensions.writeText(require ? " : require\n" : " : enable\n");
}
@ -145,14 +116,14 @@ String GLSLCodeGenerator::getTypeName(const Type& type) {
return "uint";
}
else {
return type.name();
return String(type.name());
}
break;
}
case Type::TypeKind::kEnum:
return "int";
default:
return type.name();
return String(type.name());
}
}

View File

@ -64,17 +64,9 @@ public:
protected:
using Precedence = Operator::Precedence;
void write(const char* s);
void writeLine();
void writeLine(const char* s);
void write(const String& s);
void write(StringFragment s);
void writeLine(const String& s);
void writeLine(StringFragment s = StringFragment());
void finishLine();
@ -88,9 +80,7 @@ protected:
void writeType(const Type& type);
void writeExtension(const String& name);
void writeExtension(const String& name, bool require);
void writeExtension(StringFragment name, bool require = true);
void writeInterfaceBlock(const InterfaceBlock& intf);

View File

@ -41,7 +41,7 @@ String HCodeGenerator::ParameterType(const Context& context, const Type& type,
if (ctype != Layout::CType::kDefault) {
return Layout::CTypeToStr(ctype);
}
return type.name();
return String(type.name());
}
Layout::CType HCodeGenerator::ParameterCType(const Context& context, const Type& type,
@ -122,7 +122,8 @@ void HCodeGenerator::writef(const char* s, ...) {
bool HCodeGenerator::writeSection(const char* name, const char* prefix) {
const Section* s = fSectionAndParameterHelper.getSection(name);
if (s) {
this->writef("%s%.*s", prefix, (int)s->text().length(), s->text().data());
this->writef("%s", prefix);
this->writef("%.*s", (int)s->text().length(), s->text().data());
return true;
}
return false;

View File

@ -38,14 +38,14 @@ const char* MetalCodeGenerator::OperatorName(Operator op) {
class MetalCodeGenerator::GlobalStructVisitor {
public:
virtual ~GlobalStructVisitor() = default;
virtual void visitInterfaceBlock(const InterfaceBlock& block, const String& blockName) = 0;
virtual void visitTexture(const Type& type, const String& name) = 0;
virtual void visitSampler(const Type& type, const String& name) = 0;
virtual void visitInterfaceBlock(const InterfaceBlock& block, StringFragment blockName) = 0;
virtual void visitTexture(const Type& type, StringFragment name) = 0;
virtual void visitSampler(const Type& type, StringFragment name) = 0;
virtual void visitVariable(const Variable& var, const Expression* value) = 0;
};
void MetalCodeGenerator::write(const char* s) {
if (!s[0]) {
void MetalCodeGenerator::write(StringFragment s) {
if (s.empty()) {
return;
}
if (fAtLineStart) {
@ -53,24 +53,12 @@ void MetalCodeGenerator::write(const char* s) {
fOut->writeText(" ");
}
}
fOut->writeText(s);
fOut->writeText(String(s).c_str());
fAtLineStart = false;
}
void MetalCodeGenerator::writeLine(const char* s) {
void MetalCodeGenerator::writeLine(StringFragment s) {
this->write(s);
this->writeLine();
}
void MetalCodeGenerator::write(const String& s) {
this->write(s.c_str());
}
void MetalCodeGenerator::writeLine(const String& s) {
this->writeLine(s.c_str());
}
void MetalCodeGenerator::writeLine() {
fOut->writeText(fLineEnding);
fAtLineStart = true;
}
@ -108,9 +96,9 @@ String MetalCodeGenerator::typeName(const Type& type) {
default:
if (type == *fContext.fTypes.fHalf) {
// FIXME - Currently only supporting floats in MSL to avoid type coercion issues.
return fContext.fTypes.fFloat->name();
return String(fContext.fTypes.fFloat->name());
} else {
return type.name();
return String(type.name());
}
}
}
@ -1872,7 +1860,7 @@ void MetalCodeGenerator::writeVarInitializer(const Variable& var, const Expressi
this->writeExpression(value, Precedence::kTopLevel);
}
void MetalCodeGenerator::writeName(const String& name) {
void MetalCodeGenerator::writeName(StringFragment name) {
if (fReservedWords.find(name) != fReservedWords.end()) {
this->write("_"); // adding underscore before name to avoid conflict with reserved words
}
@ -2207,7 +2195,7 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) {
if (var.type().typeKind() == Type::TypeKind::kSampler) {
// Samplers are represented as a "texture/sampler" duo in the global struct.
visitor->visitTexture(var.type(), var.name());
visitor->visitSampler(var.type(), String(var.name()) + SAMPLER_SUFFIX);
visitor->visitSampler(var.type(), var.name() + SAMPLER_SUFFIX);
continue;
}
@ -2222,7 +2210,7 @@ void MetalCodeGenerator::visitGlobalStruct(GlobalStructVisitor* visitor) {
void MetalCodeGenerator::writeGlobalStruct() {
class : public GlobalStructVisitor {
public:
void visitInterfaceBlock(const InterfaceBlock& block, const String& blockName) override {
void visitInterfaceBlock(const InterfaceBlock& block, StringFragment blockName) override {
this->addElement();
fCodeGen->write(" constant ");
fCodeGen->write(block.typeName());
@ -2230,7 +2218,7 @@ void MetalCodeGenerator::writeGlobalStruct() {
fCodeGen->writeName(blockName);
fCodeGen->write(";\n");
}
void visitTexture(const Type& type, const String& name) override {
void visitTexture(const Type& type, StringFragment name) override {
this->addElement();
fCodeGen->write(" ");
fCodeGen->writeType(type);
@ -2238,7 +2226,7 @@ void MetalCodeGenerator::writeGlobalStruct() {
fCodeGen->writeName(name);
fCodeGen->write(";\n");
}
void visitSampler(const Type&, const String& name) override {
void visitSampler(const Type&, StringFragment name) override {
this->addElement();
fCodeGen->write(" sampler ");
fCodeGen->writeName(name);
@ -2279,16 +2267,16 @@ void MetalCodeGenerator::writeGlobalInit() {
class : public GlobalStructVisitor {
public:
void visitInterfaceBlock(const InterfaceBlock& blockType,
const String& blockName) override {
StringFragment blockName) override {
this->addElement();
fCodeGen->write("&");
fCodeGen->writeName(blockName);
}
void visitTexture(const Type&, const String& name) override {
void visitTexture(const Type&, StringFragment name) override {
this->addElement();
fCodeGen->writeName(name);
}
void visitSampler(const Type&, const String& name) override {
void visitSampler(const Type&, StringFragment name) override {
this->addElement();
fCodeGen->writeName(name);
}

View File

@ -83,15 +83,9 @@ protected:
class GlobalStructVisitor;
void visitGlobalStruct(GlobalStructVisitor* visitor);
void write(const char* s);
void write(StringFragment s);
void writeLine();
void writeLine(const char* s);
void write(const String& s);
void writeLine(const String& s);
void writeLine(StringFragment s = StringFragment());
void finishLine();
@ -149,7 +143,7 @@ protected:
void writeVarInitializer(const Variable& var, const Expression& value);
void writeName(const String& name);
void writeName(StringFragment name);
void writeVarDeclaration(const VarDeclaration& decl);
@ -272,7 +266,7 @@ protected:
int getUniformSet(const Modifiers& m);
std::unordered_set<String> fReservedWords;
std::unordered_set<StringFragment> fReservedWords;
std::unordered_map<const Type::Field*, const InterfaceBlock*> fInterfaceBlockMap;
std::unordered_map<const InterfaceBlock*, String> fInterfaceBlockNameMap;
int fAnonInterfaceCount = 0;

View File

@ -57,10 +57,8 @@ public:
private:
using Precedence = Operator::Precedence;
void write(const char* s);
void writeLine(const char* s = nullptr);
void write(const String& s);
void write(StringFragment s);
void writeLine(StringFragment s = StringFragment());
String typeName(const Type& type);
void writeType(const Type& type);
@ -126,23 +124,14 @@ private:
bool fCastReturnsToHalf = false;
};
void PipelineStageCodeGenerator::write(const char* s) {
fBuffer->writeText(s);
}
void PipelineStageCodeGenerator::writeLine(const char* s) {
if (s) {
fBuffer->writeText(s);
}
fBuffer->writeText("\n");
}
void PipelineStageCodeGenerator::write(const String& s) {
void PipelineStageCodeGenerator::write(StringFragment s) {
fBuffer->write(s.data(), s.length());
}
void PipelineStageCodeGenerator::write(StringFragment s) {
fBuffer->write(s.fChars, s.fLength);
void PipelineStageCodeGenerator::writeLine(StringFragment s) {
fBuffer->write(s.data(), s.length());
fBuffer->writeText("\n");
}
void PipelineStageCodeGenerator::writeFunctionCall(const FunctionCall& c) {
@ -285,7 +274,7 @@ void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
fCastReturnsToHalf = false;
}
String fnName = decl.isMain() ? decl.name()
String fnName = decl.isMain() ? String(decl.name())
: fCallbacks->getMangledName(String(decl.name()).c_str());
// This is similar to decl.description(), but substitutes a mangled name, and handles modifiers
@ -391,7 +380,7 @@ String PipelineStageCodeGenerator::typeName(const Type& type) {
}
auto it = fStructNames.find(&type);
return it != fStructNames.end() ? it->second : type.name();
return it != fStructNames.end() ? it->second : String(type.name());
}
void PipelineStageCodeGenerator::writeType(const Type& type) {

View File

@ -273,9 +273,9 @@ void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, OutputSt
this->writeWord(word1, out);
}
void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputStream& out) {
out.write(string, length);
switch (length % 4) {
void SPIRVCodeGenerator::writeString(StringFragment s, OutputStream& out) {
out.write(s.data(), s.length());
switch (s.length() % 4) {
case 1:
out.write8(0);
[[fallthrough]];
@ -291,24 +291,24 @@ void SPIRVCodeGenerator::writeString(const char* string, size_t length, OutputSt
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, StringFragment string, OutputStream& out) {
this->writeOpCode(opCode, 1 + (string.fLength + 4) / 4, out);
this->writeString(string.fChars, string.fLength, out);
this->writeOpCode(opCode, 1 + (string.length() + 4) / 4, out);
this->writeString(string, out);
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, StringFragment string,
OutputStream& out) {
this->writeOpCode(opCode, 2 + (string.fLength + 4) / 4, out);
this->writeOpCode(opCode, 2 + (string.length() + 4) / 4, out);
this->writeWord(word1, out);
this->writeString(string.fChars, string.fLength, out);
this->writeString(string, out);
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
StringFragment string, OutputStream& out) {
this->writeOpCode(opCode, 3 + (string.fLength + 4) / 4, out);
this->writeOpCode(opCode, 3 + (string.length() + 4) / 4, out);
this->writeWord(word1, out);
this->writeWord(word2, out);
this->writeString(string.fChars, string.fLength, out);
this->writeString(string, out);
}
void SPIRVCodeGenerator::writeInstruction(SpvOp_ opCode, int32_t word1, int32_t word2,
@ -510,7 +510,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& type) {
SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layout) {
const Type& type = this->getActualType(rawType);
String key = type.name();
String key(type.name());
if (type.isStruct() || type.isArray()) {
key += to_string((int)layout.fStd);
#ifdef SK_DEBUG
@ -2065,7 +2065,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
/*invocations=*/-1, /*when=*/"", Layout::CType::kDefault),
/*flags=*/0),
SKSL_RTHEIGHT_NAME, fContext.fTypes.fFloat.get());
StringFragment name("sksl_synthetic_uniforms");
String name("sksl_synthetic_uniforms");
std::unique_ptr<Type> intfStruct = Type::MakeStructType(/*offset=*/-1, name,
fields);
int binding = fProgram.fConfig->fSettings.fRTHeightBinding;
@ -2092,8 +2092,11 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O
intfStruct.get(),
/*builtin=*/false,
Variable::Storage::kGlobal));
InterfaceBlock intf(/*offset=*/-1, intfVar, name,
/*instanceName=*/"", /*arraySize=*/0,
InterfaceBlock intf(/*offset=*/-1,
intfVar,
name,
/*instanceName=*/"",
/*arraySize=*/0,
std::make_shared<SymbolTable>(&fErrors, /*builtin=*/false));
fRTHeightStructId = this->writeInterfaceBlock(intf, false);
@ -3063,7 +3066,8 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a
fRTHeightStorageClass = storageClass;
fields.emplace_back(Modifiers(), StringFragment(SKSL_RTHEIGHT_NAME),
fContext.fTypes.fFloat.get());
rtHeightStructType = Type::MakeStructType(type->fOffset, type->name(), std::move(fields));
rtHeightStructType = Type::MakeStructType(type->fOffset, String(type->name()),
std::move(fields));
type = rtHeightStructType.get();
}
SpvId typeId;
@ -3626,7 +3630,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
this->writeCapabilities(out);
this->writeInstruction(SpvOpExtInstImport, fGLSLExtendedInstructions, "GLSL.std.450", out);
this->writeInstruction(SpvOpMemoryModel, SpvAddressingModelLogical, SpvMemoryModelGLSL450, out);
this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (main->name().fLength + 4) / 4) +
this->writeOpCode(SpvOpEntryPoint, (SpvId) (3 + (main->name().length() + 4) / 4) +
(int32_t) interfaceVars.size(), out);
switch (program.fConfig->fKind) {
case ProgramKind::kVertex:
@ -3643,7 +3647,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
}
SpvId entryPoint = fFunctionMap[main];
this->writeWord(entryPoint, out);
this->writeString(main->name().fChars, main->name().fLength, out);
this->writeString(main->name(), out);
for (int var : interfaceVars) {
this->writeWord(var, out);
}
@ -3658,7 +3662,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream&
}
for (const ProgramElement* e : program.elements()) {
if (e->is<Extension>()) {
this->writeInstruction(SpvOpSourceExtension, e->as<Extension>().name().c_str(), out);
this->writeInstruction(SpvOpSourceExtension, e->as<Extension>().name(), out);
}
}

View File

@ -397,7 +397,7 @@ private:
void writeWord(int32_t word, OutputStream& out);
void writeString(const char* string, size_t length, OutputStream& out);
void writeString(StringFragment s, OutputStream& out);
void writeLabel(SpvId id, OutputStream& out);

View File

@ -1696,7 +1696,7 @@ std::unique_ptr<UniformInfo> Program_GetUniformInfo(const Program& program) {
const GlobalVarDeclaration& decl = e->as<GlobalVarDeclaration>();
const Variable& var = decl.declaration()->as<VarDeclaration>().var();
if (var.modifiers().fFlags & Modifiers::kUniform_Flag) {
gather_uniforms(info.get(), var.type(), var.name());
gather_uniforms(info.get(), var.type(), String(var.name()));
}
}
return info;

View File

@ -19,11 +19,11 @@ class Extension final : public ProgramElement {
public:
static constexpr Kind kProgramElementKind = Kind::kExtension;
Extension(int offset, String name)
Extension(int offset, StringFragment name)
: INHERITED(offset, kProgramElementKind)
, fName(std::move(name)) {}
, fName(name) {}
const String& name() const {
StringFragment name() const {
return fName;
}
@ -36,7 +36,7 @@ public:
}
private:
String fName;
StringFragment fName;
using INHERITED = ProgramElement;
};

View File

@ -319,7 +319,7 @@ FunctionDeclaration::FunctionDeclaration(int offset,
, fReturnType(returnType)
, fBuiltin(builtin)
, fIsMain(name == "main")
, fIntrinsicKind(builtin ? identify_intrinsic(name) : kNotIntrinsic) {}
, fIntrinsicKind(builtin ? identify_intrinsic(String(name)) : kNotIntrinsic) {}
const FunctionDeclaration* FunctionDeclaration::Convert(const Context& context,
SymbolTable& symbols, int offset, const Modifiers* modifiers,
@ -353,10 +353,10 @@ const FunctionDeclaration* FunctionDeclaration::Convert(const Context& context,
String FunctionDeclaration::mangledName() const {
if ((this->isBuiltin() && !this->definition()) || this->isMain()) {
// Builtins without a definition (like `sin` or `sqrt`) must use their real names.
return this->name();
return String(this->name());
}
// GLSL forbids two underscores in a row; add an extra character if necessary to avoid this.
const char* splitter = this->name().endsWith("_") ? "x_" : "_";
const char* splitter = this->name().ends_with("_") ? "x_" : "_";
// Rename function to `funcname_returntypeparamtypes`.
String result = this->name() + splitter + this->returnType().abbreviatedName();
for (const Variable* p : this->parameters()) {

View File

@ -34,8 +34,8 @@ public:
int arraySize, std::shared_ptr<SymbolTable> typeOwner)
: INHERITED(offset, kProgramElementKind)
, fVariable(var)
, fTypeName(std::move(typeName))
, fInstanceName(std::move(instanceName))
, fTypeName(typeName)
, fInstanceName(instanceName)
, fArraySize(arraySize)
, fTypeOwner(std::move(typeOwner)) {}
@ -47,11 +47,11 @@ public:
fVariable = var;
}
const String& typeName() const {
String typeName() const {
return fTypeName;
}
const String& instanceName() const {
String instanceName() const {
return fInstanceName;
}

View File

@ -65,13 +65,13 @@ public:
}
}
const CapsLookupMethod* lookup(const String& name) const {
const CapsLookupMethod* lookup(StringFragment name) const {
auto iter = fMap.find(name);
return (iter != fMap.end()) ? iter->second.get() : nullptr;
}
private:
std::unordered_map<String, std::unique_ptr<CapsLookupMethod>> fMap;
std::unordered_map<StringFragment, std::unique_ptr<CapsLookupMethod>> fMap;
};
static const CapsLookupTable& caps_lookup_table() {
@ -102,7 +102,7 @@ static const CapsLookupTable& caps_lookup_table() {
} // namespace
static const Type* get_type(const Context& context, int offset, const String& name) {
static const Type* get_type(const Context& context, int offset, StringFragment name) {
if (const CapsLookupMethod* caps = caps_lookup_table().lookup(name)) {
return caps->type(context);
}

View File

@ -42,7 +42,7 @@ public:
}
String description() const override {
return this->name();
return String(this->name());
}
bool hasProperty(Property property) const override {

View File

@ -28,7 +28,7 @@ public:
}
String description() const override {
return this->name();
return String(this->name());
}
private:

View File

@ -123,7 +123,7 @@ void SymbolTable::addWithoutOwnership(const Symbol* symbol) {
const Type* SymbolTable::addArrayDimension(const Type* type, int arraySize) {
if (arraySize != 0) {
String baseName = type->name();
String baseName(type->name());
String arrayName = (arraySize != Type::kUnsizedArray)
? String::printf("%s[%d]", baseName.c_str(), arraySize)
: String::printf("%s[]", baseName.c_str());

View File

@ -205,15 +205,15 @@ const Type* Type::clone(SymbolTable* symbolTable) const {
// This type actually needs to be cloned into the destination SymbolTable.
switch (this->typeKind()) {
case TypeKind::kArray:
return symbolTable->add(Type::MakeArrayType(this->name(), this->componentType(),
return symbolTable->add(Type::MakeArrayType(String(this->name()), this->componentType(),
this->columns()));
case TypeKind::kStruct:
return symbolTable->add(Type::MakeStructType(this->fOffset, this->name(),
return symbolTable->add(Type::MakeStructType(this->fOffset, String(this->name()),
this->fields()));
case TypeKind::kEnum:
return symbolTable->add(Type::MakeEnumType(this->name()));
return symbolTable->add(Type::MakeEnumType(String(this->name())));
default:
SkDEBUGFAILF("don't know how to clone type '%s'", this->description().c_str());

View File

@ -136,7 +136,7 @@ public:
}
String displayName() const {
return this->scalarTypeForLiteral().name();
return String(this->scalarTypeForLiteral().name());
}
String description() const override {
@ -144,7 +144,7 @@ public:
}
bool isPrivate() const {
return this->name().startsWith("$");
return this->name().starts_with("$");
}
bool operator==(const Type& other) const {

View File

@ -35,7 +35,7 @@ public:
}
String description() const override {
return this->name();
return String(this->name());
}
private:

View File

@ -36,7 +36,7 @@ bool VariableReference::isConstantOrUniform() const {
}
String VariableReference::description() const {
return this->variable()->name();
return String(this->variable()->name());
}
void VariableReference::setRefKind(RefKind refKind) {

View File

@ -333,7 +333,7 @@ void ParticlesSlide::draw(SkCanvas* canvas) {
float* vals = data + uni.fSlot;
// Skip over builtin uniforms, to reduce clutter
if (uni.fName == "dt" || uni.fName.startsWith("effect.")) {
if (uni.fName == "dt" || uni.fName.starts_with("effect.")) {
continue;
}