Perf: Use container pointer rather than copy. (#4)

* feat: add benchmark and profiling.

* chore: update readme

* fix: fix compile headers error and fix cmake.

* perf: use container pointer rather than copy.

Signed-off-by: stonex <1479765922@qq.com>
diff --git a/cvaluate/StagePlanner.cpp b/cvaluate/StagePlanner.cpp
index 31e4fe2..baf1a26 100644
--- a/cvaluate/StagePlanner.cpp
+++ b/cvaluate/StagePlanner.cpp
@@ -49,18 +49,25 @@
         {OperatorSymbol::SEPARATE, SeparatorStage},
     };
 
+    const static std::vector<TokenKind> kPrefixKind = {TokenKind::PREFIX};
+    const static std::vector<TokenKind> kModifierKind = {TokenKind::MODIFIER};
+    const static std::vector<TokenKind> kComparatorKind = {TokenKind::COMPARATOR};
+    const static std::vector<TokenKind> kLogicalopKind = {TokenKind::LOGICALOP};
+    const static std::vector<TokenKind> kTernaryKind = {TokenKind::TERNARY};
+    const static std::vector<TokenKind> kSeparatorKind = {TokenKind::SEPARATOR};
+
     Precedent planFunctions = PlanFunctions;
-    PrecedencePlanner planPrefix(kPrefixSymbols, {TokenKind::PREFIX}, nullptr, planFunctions);
-    PrecedencePlanner planExponential(kExponentialSymbolsS, {TokenKind::MODIFIER}, planFunctions, nullptr);
-    PrecedencePlanner planMultiplicative(kMultiplicativeSymbols, {TokenKind::MODIFIER}, planExponential, nullptr);
-    PrecedencePlanner planAdditive(kAdditiveSymbols, {TokenKind::MODIFIER}, planMultiplicative, nullptr);
-    PrecedencePlanner planShift(kBitwiseShiftSymbols, {TokenKind::MODIFIER}, planAdditive, nullptr);
-    PrecedencePlanner planBitwise(kBitwiseSymbols, {TokenKind::MODIFIER}, planShift, nullptr);
-    PrecedencePlanner planComparator(kComparatorSymbols, {TokenKind::COMPARATOR}, planBitwise, nullptr);
-    PrecedencePlanner planLogicalAnd({{"&&", OperatorSymbol::AND}}, {TokenKind::LOGICALOP}, planComparator, nullptr);
-    PrecedencePlanner planLogicalOr({{"||", OperatorSymbol::OR}}, {TokenKind::LOGICALOP}, planLogicalAnd, nullptr);
-    PrecedencePlanner planTernary(kTernarySymbols, {TokenKind::TERNARY}, planLogicalOr, nullptr);
-    PrecedencePlanner planSeparator(kSeparatorSymbols, {TokenKind::SEPARATOR}, planTernary, nullptr);
+    PrecedencePlanner planPrefix(&kPrefixSymbols, &kPrefixKind, nullptr, planFunctions);
+    PrecedencePlanner planExponential(&kExponentialSymbolsS, &kModifierKind, planFunctions, nullptr);
+    PrecedencePlanner planMultiplicative(&kMultiplicativeSymbols, &kModifierKind, planExponential, nullptr);
+    PrecedencePlanner planAdditive(&kAdditiveSymbols, &kModifierKind, planMultiplicative, nullptr);
+    PrecedencePlanner planShift(&kBitwiseShiftSymbols, &kModifierKind, planAdditive, nullptr);
+    PrecedencePlanner planBitwise(&kBitwiseSymbols, &kModifierKind, planShift, nullptr);
+    PrecedencePlanner planComparator(&kComparatorSymbols, &kComparatorKind, planBitwise, nullptr);
+    PrecedencePlanner planLogicalAnd(&kLogicalAndSymbols, &kLogicalopKind, planComparator, nullptr);
+    PrecedencePlanner planLogicalOr(&kLogicalOrSymbols, &kLogicalopKind, planLogicalAnd, nullptr);
+    PrecedencePlanner planTernary(&kTernarySymbols, &kTernaryKind, planLogicalOr, nullptr);
+    PrecedencePlanner planSeparator(&kSeparatorSymbols, &kSeparatorKind, planTernary, nullptr);
 
     /*
         Creates a `evaluationStageList` object which represents an execution plan (or tree)
@@ -68,7 +75,7 @@
         The three stages of evaluation can be thought of as parsing strings to tokens, then tokens to a stage list, then evaluation with parameters.
     */
     std::shared_ptr<EvaluationStage> PlanStages(std::vector<ExpressionToken>& tokens) {
-        auto stream = TokenStream(tokens);
+        TokenStream stream(tokens);
 
         auto stage = PlanTokens(stream);
 
@@ -133,8 +140,8 @@
         Most stages use the same logic
     */
     std::shared_ptr<EvaluationStage> PrecedencePlanner::PlanPrecedenceLevel(TokenStream& stream,
-            StringOperatorSymbolMap valid_symbols, std::vector<TokenKind> valid_kinds,
-            Precedent right_precedent, Precedent left_precedent) {
+            const StringOperatorSymbolMap* valid_symbols, const std::vector<TokenKind>* valid_kinds,
+            Precedent& right_precedent, Precedent& left_precedent) {
         ExpressionToken token;
         OperatorSymbol symbol = OperatorSymbol::VALUE;
         std::shared_ptr<EvaluationStage> right_stage = nullptr;
@@ -149,18 +156,18 @@
         while (stream.HasNext()) {
             token = *stream.Next();
 
-            if (valid_kinds.size() > 0) {
+            if (valid_kinds->size() > 0) {
                 key_found = false;
 
-                auto find_key = std::find(valid_kinds.begin(), valid_kinds.end(), token.Kind);
-                key_found = (find_key != valid_kinds.end());
+                auto find_key = std::find(valid_kinds->begin(), valid_kinds->end(), token.Kind);
+                key_found = (find_key != valid_kinds->end());
 
                 if (!key_found) {
                     break;
                 }
             }
 
-            if (!valid_symbols.empty()) {
+            if (!valid_symbols->empty()) {
                 auto data = GetTokenValueData(token.Value);
                 if (!IsString(data)) {
                     break;
@@ -168,10 +175,10 @@
 
                 auto token_string = data.get<std::string>();
 
-                if (valid_symbols.find(token_string) == valid_symbols.end()) {
+                if (valid_symbols->find(token_string) == valid_symbols->end()) {
                     break;
                 } else {
-                    symbol = valid_symbols[token_string];
+                    symbol = valid_symbols->at(token_string);
                 }
             }
 
diff --git a/include/cvaluate/OperatorSymbol.h b/include/cvaluate/OperatorSymbol.h
index 8597e21..114b14f 100644
--- a/include/cvaluate/OperatorSymbol.h
+++ b/include/cvaluate/OperatorSymbol.h
@@ -156,5 +156,13 @@
         {",", OperatorSymbol::SEPARATE}
     };
 
+    const StringOperatorSymbolMap kLogicalAndSymbols = {
+        {"&&", OperatorSymbol::AND}
+    };
+
+    const StringOperatorSymbolMap kLogicalOrSymbols = {
+        {"||", OperatorSymbol::OR}
+    };
+
 } // Cvaluate
 #endif
\ No newline at end of file
diff --git a/include/cvaluate/StagePlanner.h b/include/cvaluate/StagePlanner.h
index a79a82f..c53fae5 100644
--- a/include/cvaluate/StagePlanner.h
+++ b/include/cvaluate/StagePlanner.h
@@ -30,12 +30,12 @@
 
     class PrecedencePlanner {
         public:
-            StringOperatorSymbolMap valid_symbols;
-            std::vector<TokenKind> valid_kinds;
+            const StringOperatorSymbolMap* valid_symbols = nullptr;
+            const std::vector<TokenKind>* valid_kinds = nullptr;
             Precedent next;
             Precedent next_right;
 
-            PrecedencePlanner(StringOperatorSymbolMap valid_symbols, std::vector<TokenKind> valid_kinds,
+            PrecedencePlanner(const StringOperatorSymbolMap* valid_symbols, const std::vector<TokenKind>* valid_kinds,
                             Precedent next, Precedent next_right) {
                 this->valid_symbols = valid_symbols;
                 this->valid_kinds = valid_kinds;
@@ -43,31 +43,36 @@
                 this->next_right = next_right;
             };
 
+            PrecedencePlanner(PrecedencePlanner const& other) {
+                this->valid_symbols = other.valid_symbols;
+                this->valid_kinds = other.valid_kinds;
+                this->next = other.next;
+                this->next_right = other.next_right;
+            };
+
             std::shared_ptr<EvaluationStage> PlanPrecedenceLevel(TokenStream& stream,
-                StringOperatorSymbolMap vlaid_symbols, std::vector<TokenKind> valid_kinds,
-                Precedent right_precedent, Precedent left_precedent);
+                const StringOperatorSymbolMap* vlaid_symbols, const std::vector<TokenKind>* valid_kinds,
+                Precedent& right_precedent, Precedent& left_precedent);
 
             std::shared_ptr<EvaluationStage> operator()(TokenStream& stream) {
                 Precedent generated = nullptr;
-                Precedent nextRight = nullptr;
+                Precedent* nextRight = &this->next_right;
 
                 generated = [&] (TokenStream& stream) -> std::shared_ptr<EvaluationStage> {
                     return PlanPrecedenceLevel(
                         stream,
                         this->valid_symbols,
                         this->valid_kinds,
-                        nextRight,
+                        *nextRight,
                         this->next
                     );
                 };
 
                 // left precence > current, right precence >= current
-                if (this->next_right != nullptr) {
-                    nextRight = this->next_right;
-                } else {
-                    nextRight = generated;
-                }
-                
+                if (this->next_right == nullptr) {
+                    nextRight = &generated;
+                }                
+
                 return generated(stream);
             }
     };
diff --git a/include/cvaluate/TokenStream.h b/include/cvaluate/TokenStream.h
index 5f88228..e1e4b1e 100644
--- a/include/cvaluate/TokenStream.h
+++ b/include/cvaluate/TokenStream.h
@@ -22,10 +22,10 @@
 namespace Cvaluate {
     class TokenStream {
         private:
-            std::vector<ExpressionToken> tokens;
+            std::vector<ExpressionToken>& tokens;
             std::vector<ExpressionToken>::iterator index;
         public:
-            TokenStream(std::vector<ExpressionToken> _tokens) : tokens(_tokens) {
+            TokenStream(std::vector<ExpressionToken>& _tokens) : tokens(_tokens) {
                 this->index = tokens.begin();
             };