OSDN Git Service

[Refactor] エゴのパース関数をstd::stringベースで再実装
authoriks <iks3@users.noreply.github.com>
Thu, 22 Apr 2021 11:09:17 +0000 (20:09 +0900)
committeriks <iks3@users.noreply.github.com>
Sat, 24 Apr 2021 09:32:36 +0000 (18:32 +0900)
src/info-reader/ego-reader.cpp
src/info-reader/ego-reader.h

index ad35cd0..920514c 100644 (file)
@@ -3,6 +3,7 @@
 #include "main/angband-headers.h"
 #include "object-enchant/object-ego.h"
 #include "object-enchant/tr-types.h"
+#include "parse-error-types.h"
 #include "util/bit-flags-calculator.h"
 #include "util/string-processor.h"
 #include "view/display-messages.h"
@@ -16,7 +17,7 @@
  * @param what 参照元の文字列ポインタ
  * @return エラーがあった場合1、エラーがない場合0を返す
  */
-static bool grab_one_ego_item_flag(ego_item_type *e_ptr, concptr what)
+static bool grab_one_ego_item_flag(ego_item_type *e_ptr, std::string_view what)
 {
     if (k_info_flags.find(what) != k_info_flags.end()) {
         add_flag(e_ptr->flags, k_info_flags[what]);
@@ -30,7 +31,7 @@ static bool grab_one_ego_item_flag(ego_item_type *e_ptr, concptr what)
     return 1;
 }
 
-static bool grab_ego_generate_flags(ego_generate_type &xtra, concptr what)
+static bool grab_ego_generate_flags(ego_generate_type &xtra, std::string_view what)
 {
     if (k_info_flags.find(what) != k_info_flags.end()) {
         xtra.tr_flags.push_back(k_info_flags[what]);
@@ -57,128 +58,104 @@ static bool grab_ego_generate_flags(ego_generate_type &xtra, concptr what)
 errr parse_e_info(char *buf, angband_header *head)
 {
     static ego_item_type *e_ptr = NULL;
+    auto line = std::string(buf);
+    auto tok = str_split(line, ':', false);
+
     error_idx = 0;
-    char *s, *t;
-    if (buf[0] == 'N') {
-        s = angband_strchr(buf + 2, ':');
-        if (!s)
-            return 1;
 
-        *s++ = '\0';
-#ifdef JP
-        if (!*s)
-            return 1;
-#endif
-        int i = atoi(buf + 2);
+    if (tok[0] == "N") {
+        // N:index:name_ja
+        if (tok[1].size() == 0)
+            return PARSE_ERROR_GENERIC;
+
+        auto i = std::stoi(tok[1]);
         if (i < error_idx)
-            return 4;
+            return PARSE_ERROR_NON_SEQUENTIAL_RECORDS;
         if (i >= head->info_num)
-            return 2;
+            return PARSE_ERROR_OUT_OF_BOUNDS;
 
         error_idx = i;
         e_ptr = &e_info[i];
 #ifdef JP
-        e_ptr->name = std::string(s);
-#endif
-    } else if (!e_ptr) {
-        return 3;
-    }
-#ifdef JP
-    /* 英語名を読むルーチンを追加 */
-    /* 'E' から始まる行は英語名 */
-    else if (buf[0] == 'E') {
-        /* nothing to do */
-    }
-#else
-    else if (buf[0] == 'E') {
-        s = buf + 2;
-        e_ptr->name = std::string(s);
-    }
+        e_ptr->name = tok[2];
 #endif
-    else if (buf[0] == 'X') {
-        int slot, rating;
-        if (2 != sscanf(buf + 2, "%d:%d", &slot, &rating))
-            return 1;
-
-        e_ptr->slot = (INVENTORY_IDX)slot;
-        e_ptr->rating = (PRICE)rating;
-    } else if (buf[0] == 'W') {
-        int level, rarity, pad2;
-        long cost;
-
-        if (4 != sscanf(buf + 2, "%d:%d:%d:%ld", &level, &rarity, &pad2, &cost))
+    } else if (!e_ptr)
+        return PARSE_ERROR_MISSING_RECORD_HEADER;
+    else if (tok[0] == "E") {
+        // E:name_en
+#ifndef JP
+        if (tok[1].size() == 0)
             return 1;
-
-        e_ptr->level = level;
-        e_ptr->rarity = (RARITY)rarity;
-        e_ptr->cost = cost;
-    } else if (buf[0] == 'C') {
-        int th, td, ta, pval;
-
-        if (4 != sscanf(buf + 2, "%d:%d:%d:%d", &th, &td, &ta, &pval))
-            return 1;
-
-        e_ptr->max_to_h = (HIT_PROB)th;
-        e_ptr->max_to_d = (HIT_POINT)td;
-        e_ptr->max_to_a = (ARMOUR_CLASS)ta;
-        e_ptr->max_pval = (PARAMETER_VALUE)pval;
-    } else if (buf[0] == 'U') {
-        byte n;
-        n = grab_one_activation_flag(buf + 2);
-        if (n > 0) {
-            e_ptr->act_idx = n;
-        } else {
-            return 5;
-        }
-    } else if (buf[0] == 'F') {
-        for (s = buf + 2; *s;) {
-            /* loop */
-            for (t = s; *t && (*t != ' ') && (*t != '|'); ++t)
-                ;
-
-            if (*t) {
-                *t++ = '\0';
-                while ((*t == ' ') || (*t == '|'))
-                    t++;
-            }
-
-            if (0 != grab_one_ego_item_flag(e_ptr, s))
-                return 5;
-
-            s = t;
+        e_ptr->name = tok[1];
+#endif
+    }
+    else if (tok[0] == "X") {
+        // X:slot:rating
+        if (tok.size() < 3)
+            return PARSE_ERROR_TOO_FEW_ARGUMENTS;
+        e_ptr->slot = (INVENTORY_IDX)std::stoi(tok[1]);
+        e_ptr->rating = (PRICE)std::stoi(tok[2]);
+    } else if (tok[0] == "W") {
+        // W:level:ratiry:xtra:cost
+        // xtra is not used
+        if (tok.size() < 5)
+            return PARSE_ERROR_TOO_FEW_ARGUMENTS;
+        e_ptr->level = (DEPTH)std::stoi(tok[1]);
+        e_ptr->rarity = (RARITY)std::stoi(tok[2]);
+        e_ptr->cost = (PRICE)std::stoi(tok[4]);
+    } else if (tok[0] == "C") {
+        // Creation bonuses (random plus)
+        // C:to_hit:to_dam:to_ac:pval
+        if (tok.size() < 5)
+            return PARSE_ERROR_TOO_FEW_ARGUMENTS;
+        e_ptr->max_to_h = (HIT_PROB)std::stoi(tok[1]);
+        e_ptr->max_to_d = (HIT_POINT)std::stoi(tok[2]);
+        e_ptr->max_to_a = (ARMOUR_CLASS)std::stoi(tok[3]);
+        e_ptr->max_pval = (PARAMETER_VALUE)std::stoi(tok[4]);
+    } else if (tok[0] == "U") {
+        // U:activation_flag
+        if (tok.size() < 2 || tok[1].size() == 0)
+            return PARSE_ERROR_TOO_FEW_ARGUMENTS;
+        auto n = grab_one_activation_flag(tok[1].c_str());
+        if (n <= 0)
+            return PARSE_ERROR_INVALID_FLAG;
+        e_ptr->act_idx = (IDX)n;
+    } else if (tok[0] == "F") {
+        // F:flags
+        if (tok.size() < 2 || tok[1].size() == 0)
+            return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
+
+        const auto& flags = str_split(tok[1], '|', true);
+        for (const auto& f : flags) {
+            if (f.size() == 0)
+                continue;
+            if (0 != grab_one_ego_item_flag(e_ptr, f))
+                return PARSE_ERROR_INVALID_FLAG;
         }
-    } else if (buf[0] == 'G') {
-        ego_generate_type xtra;
-
-        s = angband_strstr(buf + 2, ":");
-        if (!s)
-            return 1;
+    } else if (tok[0] == "G") {
+        // G:mul/dev:flags
+        if (tok.size() < 3)
+            return PARSE_ERROR_UNDEFINED_TERRAIN_TAG;
 
-        *s++ = '\0';
+        auto prob = str_split(tok[1], '/');
+        if (prob.size() != 2 || tok[1].size() == 0 || tok[2].size() == 0)
+            return PARSE_ERROR_TOO_FEW_ARGUMENTS;
 
-        if (2 != sscanf(buf + 2, "%d/%d", &xtra.mul, &xtra.dev))
-            return 1;
-
-        for (; *s;) {
-            for (t = s; *t && (*t != ' ') && (*t != '|'); ++t)
-                ;
-
-            if (*t) {
-                *t++ = '\0';
-                while ((*t == ' ') || (*t == '|'))
-                    t++;
-            }
-
-            if (grab_ego_generate_flags(xtra, s))
-                return 5;
-
-            s = t;
+        ego_generate_type xtra;
+        xtra.mul = std::stoi(prob[0]);
+        xtra.dev = std::stoi(prob[1]);
+
+        const auto& flags = str_split(tok[2], '|', true);
+        for (const auto& f : flags) {
+            if (f.size() == 0)
+                continue;
+            if (grab_ego_generate_flags(xtra, f))
+                return PARSE_ERROR_INVALID_FLAG;
         }
 
         e_ptr->xtra_flags.push_back(std::move(xtra));
-    } else {
-        return 6;
-    }
+    } else
+        return PARSE_ERROR_UNDEFINED_DIRECTIVE;
 
-    return 0;
+    return PARSE_ERROR_NONE;
 }
index d518fb4..9d33353 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "system/angband.h"
+#include "parse-error-types.h"
 #include "info-reader/info-reader-util.h"
 
 errr parse_e_info(char *buf, angband_header *head);