summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/graph.cc12
-rw-r--r--src/parsers.cc15
-rw-r--r--src/parsers.h7
-rw-r--r--src/parsers_test.cc4
-rw-r--r--src/string_piece.h51
5 files changed, 77 insertions, 12 deletions
diff --git a/src/graph.cc b/src/graph.cc
index c43cf70..5c37ac0 100644
--- a/src/graph.cc
+++ b/src/graph.cc
@@ -159,18 +159,20 @@ bool Edge::LoadDepFile(State* state, DiskInterface* disk_interface,
}
// Check that this depfile matches our output.
- if (outputs_[0]->file_->path_ != makefile.out_) {
+ StringPiece opath = StringPiece(outputs_[0]->file_->path_);
+ if (opath != makefile.out_) {
*err = "expected makefile to mention '" + outputs_[0]->file_->path_ + "', "
- "got '" + makefile.out_ + "'";
+ "got '" + makefile.out_.AsString() + "'";
return false;
}
// Add all its in-edges.
- for (vector<string>::iterator i = makefile.ins_.begin();
+ for (vector<StringPiece>::iterator i = makefile.ins_.begin();
i != makefile.ins_.end(); ++i) {
- CanonicalizePath(&*i);
+ string path(i->str_, i->len_);
+ CanonicalizePath(&path);
- Node* node = state->GetNode(*i);
+ Node* node = state->GetNode(path);
inputs_.insert(inputs_.end() - order_only_deps_, node);
node->out_edges_.push_back(this);
++implicit_deps_;
diff --git a/src/parsers.cc b/src/parsers.cc
index 849a3e1..567be6b 100644
--- a/src/parsers.cc
+++ b/src/parsers.cc
@@ -148,15 +148,24 @@ bool Tokenizer::ExpectIdent(const char* expected, string* err) {
return true;
}
-bool Tokenizer::ReadIdent(string* out) {
+bool Tokenizer::ReadIdent(StringPiece* out) {
PeekToken();
if (token_.type_ != Token::IDENT)
return false;
- out->assign(token_.pos_, token_.end_ - token_.pos_);
+ out->str_ = token_.pos_;
+ out->len_ = token_.end_ - token_.pos_;
ConsumeToken();
return true;
}
+bool Tokenizer::ReadIdent(string* out) {
+ StringPiece token;
+ if (!ReadIdent(&token))
+ return false;
+ out->assign(token.str_, token.len_);
+ return true;
+}
+
// A note on backslashes in Makefiles, from reading the docs:
// Backslash-newline is the line continuation character.
// Backslash-# escapes a # (otherwise meaningful as a comment start).
@@ -276,7 +285,7 @@ bool MakefileParser::Parse(const string& input, string* err) {
if (!tokenizer_.ExpectToken(Token::COLON, err))
return false;
while (tokenizer_.PeekToken() == Token::IDENT) {
- string in;
+ StringPiece in;
tokenizer_.ReadIdent(&in);
ins_.push_back(in);
}
diff --git a/src/parsers.h b/src/parsers.h
index bdc88d2..6bdca77 100644
--- a/src/parsers.h
+++ b/src/parsers.h
@@ -21,6 +21,8 @@
using namespace std;
+#include "string_piece.h"
+
struct BindingEnv;
/// A single parsed token in an input stream.
@@ -78,6 +80,7 @@ struct Tokenizer {
bool Newline(string* err);
bool ExpectToken(Token::Type expected, string* err);
bool ExpectIdent(const char* expected, string* err);
+ bool ReadIdent(StringPiece* out);
bool ReadIdent(string* out);
bool ReadToNewline(string* text, string* err,
size_t max_length=std::numeric_limits<size_t>::max());
@@ -102,8 +105,8 @@ struct MakefileParser {
bool Parse(const string& input, string* err);
Tokenizer tokenizer_;
- string out_;
- vector<string> ins_;
+ StringPiece out_;
+ vector<StringPiece> ins_;
};
struct EvalString;
diff --git a/src/parsers_test.cc b/src/parsers_test.cc
index 5e2746d..c1c33a2 100644
--- a/src/parsers_test.cc
+++ b/src/parsers_test.cc
@@ -474,7 +474,7 @@ TEST(MakefileParser, Basic) {
"build/ninja.o: ninja.cc ninja.h eval_env.h manifest_parser.h\n",
&err));
ASSERT_EQ("", err);
- EXPECT_EQ("build/ninja.o", parser.out_);
+ EXPECT_EQ("build/ninja.o", parser.out_.AsString());
EXPECT_EQ(4u, parser.ins_.size());
}
@@ -496,6 +496,6 @@ TEST(MakefileParser, Continuation) {
" bar.h baz.h\n",
&err));
ASSERT_EQ("", err);
- EXPECT_EQ("foo.o", parser.out_);
+ EXPECT_EQ("foo.o", parser.out_.AsString());
EXPECT_EQ(2u, parser.ins_.size());
}
diff --git a/src/string_piece.h b/src/string_piece.h
new file mode 100644
index 0000000..0e55afb
--- /dev/null
+++ b/src/string_piece.h
@@ -0,0 +1,51 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef NINJA_STRINGPIECE_H_
+#define NINJA_STRINGPIECE_H_
+
+#include <string>
+
+using namespace std;
+
+#include <string.h>
+
+/// StringPiece represents a slice of a string whose memory is managed
+/// externally. It is useful for reducing the number of std::strings
+/// we need to allocate.
+struct StringPiece {
+ StringPiece() : str_(NULL), len_(0) {}
+
+ /// The constructors intentionally allow for implicit conversions.
+ StringPiece(const string& str) : str_(str.data()), len_(str.size()) {}
+ StringPiece(const char* str) : str_(str), len_(strlen(str)) {}
+
+ bool operator==(const StringPiece& other) const {
+ return len_ == other.len_ && memcmp(str_, other.str_, len_) == 0;
+ }
+ bool operator!=(const StringPiece& other) const {
+ return !(*this == other);
+ }
+
+ /// Convert the slice into a full-fledged std::string, copying the
+ /// data into a new string.
+ string AsString() const {
+ return string(str_, len_);
+ }
+
+ const char* str_;
+ int len_;
+};
+
+#endif // NINJA_BROWSE_H_