summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Longbons <b.r.longbons@gmail.com>2014-03-30 23:14:12 -0700
committerBen Longbons <b.r.longbons@gmail.com>2014-03-31 10:18:49 -0700
commit1a651243bb2c8e18baa9aac30ac52a62185074e7 (patch)
treedd2c0bfc448faef129fb64edec9f64d2ab12bfe5
parent769e8ac9c17779a15492d7fcfc1931c014670c2d (diff)
downloadtmwa-1a651243bb2c8e18baa9aac30ac52a62185074e7.tar.gz
tmwa-1a651243bb2c8e18baa9aac30ac52a62185074e7.tar.bz2
tmwa-1a651243bb2c8e18baa9aac30ac52a62185074e7.tar.xz
tmwa-1a651243bb2c8e18baa9aac30ac52a62185074e7.zip
Be stricter about most arrays
-rw-r--r--src/admin/ladmin.cpp18
-rw-r--r--src/char/char.cpp44
-rw-r--r--src/char/char.hpp4
-rw-r--r--src/char/int_party.cpp1
-rw-r--r--src/char/int_storage.cpp4
-rw-r--r--src/char/inter.cpp6
-rw-r--r--src/generic/const_array.cpp3
-rw-r--r--src/generic/const_array.hpp132
-rw-r--r--src/generic/enum.hpp39
-rw-r--r--src/generic/intern-pool.hpp1
-rw-r--r--src/generic/matrix.hpp6
-rw-r--r--src/io/cxxstdio.hpp1
-rw-r--r--src/login/login.cpp34
-rw-r--r--src/map/atcommand.hpp2
-rw-r--r--src/map/battle.cpp44
-rw-r--r--src/map/battle.hpp2
-rw-r--r--src/map/clif.cpp6
-rw-r--r--src/map/clif.hpp2
-rw-r--r--src/map/intif.cpp1
-rw-r--r--src/map/intif.hpp2
-rw-r--r--src/map/magic-expr-eval.hpp4
-rw-r--r--src/map/magic-expr.cpp174
-rw-r--r--src/map/magic-expr.hpp8
-rw-r--r--src/map/magic-stmt.cpp54
-rw-r--r--src/map/magic-v2.cpp6
-rw-r--r--src/map/map.cpp31
-rw-r--r--src/map/map.hpp22
-rw-r--r--src/map/mapflag.cpp64
-rw-r--r--src/map/mob.cpp30
-rw-r--r--src/map/npc.cpp18
-rw-r--r--src/map/npc.hpp8
-rw-r--r--src/map/pc.cpp21
-rw-r--r--src/map/script.cpp40
-rw-r--r--src/map/script.hpp4
-rw-r--r--src/map/skill-pools.cpp2
-rw-r--r--src/map/skill.cpp16
-rw-r--r--src/map/skill.hpp15
-rw-r--r--src/map/tmw.hpp2
-rw-r--r--src/map/trade.cpp8
-rw-r--r--src/mmo/core.cpp2
-rw-r--r--src/mmo/core.hpp4
-rw-r--r--src/mmo/dumb_ptr.hpp2
-rw-r--r--src/mmo/extract.hpp2
-rw-r--r--src/mmo/mmo.hpp29
-rw-r--r--src/mmo/utils.hpp1
-rw-r--r--src/range/slice.cpp1
-rw-r--r--src/range/slice.hpp74
-rw-r--r--src/range/slice.tcc216
-rw-r--r--src/range/slice_test.cpp89
-rw-r--r--src/strings/base.hpp2
-rw-r--r--src/strings/pair.hpp4
51 files changed, 802 insertions, 503 deletions
diff --git a/src/admin/ladmin.cpp b/src/admin/ladmin.cpp
index f889b19..b56fd65 100644
--- a/src/admin/ladmin.cpp
+++ b/src/admin/ladmin.cpp
@@ -2840,34 +2840,36 @@ void term_func(void)
//------------------------
// Main function of ladmin
//------------------------
-int do_init(int argc, ZString *argv)
+int do_init(Slice<ZString> argv)
{
+ ZString argv0 = argv.pop_front();
bool loaded_config_yet = false;
- for (int i = 1; i < argc; ++i)
+ while (argv)
{
- if (argv[i].startswith('-'))
+ ZString argvi = argv.pop_front();
+ if (argvi.startswith('-'))
{
- if (argv[i] == "--help")
+ if (argvi == "--help")
{
PRINTF("Usage: %s [--help] [--version] [files...]\n",
- argv[0]);
+ argv0);
exit(0);
}
- else if (argv[i] == "--version")
+ else if (argvi == "--version")
{
PRINTF("%s\n", CURRENT_VERSION_STRING);
exit(0);
}
else
{
- FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ FPRINTF(stderr, "Unknown argument: %s\n", argvi);
runflag = false;
}
}
else
{
loaded_config_yet = true;
- runflag &= load_config_file(argv[i], admin_confs);
+ runflag &= load_config_file(argvi, admin_confs);
}
}
diff --git a/src/char/char.cpp b/src/char/char.cpp
index b74df46..91ff2e2 100644
--- a/src/char/char.cpp
+++ b/src/char/char.cpp
@@ -46,11 +46,11 @@
#include "../poison.hpp"
static
-struct mmo_map_server server[MAX_MAP_SERVERS];
+Array<struct mmo_map_server, MAX_MAP_SERVERS> server;
static
-Session *server_session[MAX_MAP_SERVERS];
+Array<Session *, MAX_MAP_SERVERS> server_session;
static
-int server_freezeflag[MAX_MAP_SERVERS]; // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+Array<int, MAX_MAP_SERVERS> server_freezeflag; // Map-server anti-freeze system. Counter. 5 ok, 4...0 freezed
static
int anti_freeze_enable = 0;
static
@@ -313,6 +313,7 @@ AString mmo_char_tostr(struct CharPair *cp)
}
str_p += '\t';
+ assert (p->global_reg_num < GLOBAL_REG_NUM);
for (int i = 0; i < p->global_reg_num; i++)
if (p->global_reg[i].str)
str_p += STRPRINTF("%s,%d ",
@@ -411,14 +412,14 @@ bool extract(XString str, CharPair *cp)
if (inventory.size() > MAX_INVENTORY)
return false;
- std::copy(inventory.begin(), inventory.end(), p->inventory);
+ std::copy(inventory.begin(), inventory.end(), p->inventory.begin());
// number of inventory items is not saved - it just detects nameid 0
// cart was here - no longer supported
for (struct skill_loader& sk : skills)
{
- if (sk.id > MAX_SKILL)
+ if (sk.id >= MAX_SKILL)
return false;
p->skill[sk.id].lv = sk.level;
p->skill[sk.id].flags = sk.flags;
@@ -426,7 +427,7 @@ bool extract(XString str, CharPair *cp)
if (vars.size() > GLOBAL_REG_NUM)
return false;
- std::copy(vars.begin(), vars.end(), p->global_reg);
+ std::copy(vars.begin(), vars.end(), p->global_reg.begin());
p->global_reg_num = vars.size();
return true;
@@ -964,8 +965,10 @@ int mmo_char_send006b(Session *s, struct char_session_data *sd)
}
static
-int set_account_reg2(int acc, int num, struct global_reg *reg)
+int set_account_reg2(int acc, Slice<global_reg> reg)
{
+ size_t num = reg.size();
+ assert (num < ACCOUNT_REG2_NUM);
int c = 0;
for (CharPair& cd : char_keys)
{
@@ -1309,7 +1312,7 @@ void parse_tologin(Session *ls)
if (RFIFOREST(ls) < 4 || RFIFOREST(ls) < RFIFOW(ls, 2))
return;
{
- struct global_reg reg[ACCOUNT_REG2_NUM];
+ Array<struct global_reg, ACCOUNT_REG2_NUM> reg;
int j, p, acc;
acc = RFIFOL(ls, 4);
for (p = 8, j = 0;
@@ -1319,7 +1322,7 @@ void parse_tologin(Session *ls)
reg[j].str = stringish<VarName>(RFIFO_STRING<32>(ls, p));
reg[j].value = RFIFOL(ls, p + 32);
}
- set_account_reg2(acc, j, reg);
+ set_account_reg2(acc, Slice<struct global_reg>(reg.begin(), j));
size_t len = RFIFOW(ls, 2);
uint8_t buf[len];
@@ -1980,7 +1983,7 @@ void parse_frommap(Session *ms)
if (RFIFOREST(ms) < 4 || RFIFOREST(ms) < RFIFOW(ms, 2))
return;
{
- struct global_reg reg[ACCOUNT_REG2_NUM];
+ Array<struct global_reg, ACCOUNT_REG2_NUM> reg;
int p, j;
int acc = RFIFOL(ms, 4);
for (p = 8, j = 0;
@@ -1990,7 +1993,7 @@ void parse_frommap(Session *ms)
reg[j].str = stringish<VarName>(RFIFO_STRING<32>(ms, p));
reg[j].value = RFIFOL(ms, p + 32);
}
- set_account_reg2(acc, j, reg);
+ set_account_reg2(acc, Slice<struct global_reg>(reg.begin(), j));
// loginサーバーへ送る
if (login_session)
{
@@ -2831,34 +2834,37 @@ bool char_confs(XString key, ZString value)
return sum;
}
-int do_init(int argc, ZString *argv)
+int do_init(Slice<ZString> argv)
{
+ ZString argv0 = argv.pop_front();
+
bool loaded_config_yet = false;
- for (int i = 1; i < argc; ++i)
+ while (argv)
{
- if (argv[i].startswith('-'))
+ ZString argvi = argv.pop_front();
+ if (argvi.startswith('-'))
{
- if (argv[i] == "--help")
+ if (argvi == "--help")
{
PRINTF("Usage: %s [--help] [--version] [files...]\n",
- argv[0]);
+ argv0);
exit(0);
}
- else if (argv[i] == "--version")
+ else if (argvi == "--version")
{
PRINTF("%s\n", CURRENT_VERSION_STRING);
exit(0);
}
else
{
- FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ FPRINTF(stderr, "Unknown argument: %s\n", argvi);
runflag = false;
}
}
else
{
loaded_config_yet = true;
- runflag &= load_config_file(argv[i], char_confs);
+ runflag &= load_config_file(argvi, char_confs);
}
}
diff --git a/src/char/char.hpp b/src/char/char.hpp
index 377b1c6..f765b39 100644
--- a/src/char/char.hpp
+++ b/src/char/char.hpp
@@ -3,8 +3,6 @@
# include "../strings/fwd.hpp"
-# include "../generic/const_array.hpp"
-
# include "../mmo/ip.hpp"
# include "../mmo/mmo.hpp"
@@ -17,7 +15,7 @@ struct mmo_map_server
IP4Address ip;
short port;
int users;
- MapName maps[MAX_MAP_PER_SERVER];
+ Array<MapName, MAX_MAP_PER_SERVER> maps;
};
const CharPair *search_character(CharName character_name);
diff --git a/src/char/int_party.cpp b/src/char/int_party.cpp
index c0bedde..864972d 100644
--- a/src/char/int_party.cpp
+++ b/src/char/int_party.cpp
@@ -381,6 +381,7 @@ void mapif_party_leaved(int party_id, int account_id, CharName name)
static
void mapif_party_membermoved(struct party *p, int idx)
{
+ assert (idx < MAX_PARTY);
unsigned char buf[29];
WBUFW(buf, 0) = 0x3825;
diff --git a/src/char/int_storage.cpp b/src/char/int_storage.cpp
index 0794c8f..d2782b4 100644
--- a/src/char/int_storage.cpp
+++ b/src/char/int_storage.cpp
@@ -83,8 +83,10 @@ bool extract(XString str, struct storage *p)
if (storage_items.size() > MAX_STORAGE)
return false;
- std::copy(storage_items.begin(), storage_items.end(), p->storage_);
+ std::copy(storage_items.begin(), storage_items.end(), p->storage_.begin());
+ if (p->storage_amount != storage_items.size())
+ PRINTF("WARNING: storage desync for %d\n", p->account_id);
return true;
}
diff --git a/src/char/inter.cpp b/src/char/inter.cpp
index c287844..0c41c86 100644
--- a/src/char/inter.cpp
+++ b/src/char/inter.cpp
@@ -35,7 +35,7 @@ AString accreg_txt = "save/accreg.txt";
struct accreg
{
int account_id, reg_num;
- struct global_reg reg[ACCOUNT_REG_NUM];
+ Array<struct global_reg, ACCOUNT_REG_NUM> reg;
};
static
Map<int, struct accreg> accreg_db;
@@ -63,6 +63,7 @@ int inter_recv_packet_length[] =
static
AString inter_accreg_tostr(struct accreg *reg)
{
+ assert(reg->reg_num < ACCOUNT_REG_NUM);
MString str;
str += STRPRINTF("%d\t", reg->account_id);
for (int j = 0; j < reg->reg_num; j++)
@@ -85,7 +86,7 @@ bool extract(XString str, struct accreg *reg)
if (vars.size() > ACCOUNT_REG_NUM)
return false;
- std::copy(vars.begin(), vars.end(), reg->reg);
+ std::copy(vars.begin(), vars.end(), reg->reg.begin());
reg->reg_num = vars.size();
return true;
}
@@ -263,6 +264,7 @@ void mapif_account_reg_reply(Session *s, int account_id)
}
else
{
+ assert (reg->reg_num < ACCOUNT_REG_NUM);
int j, p;
for (j = 0, p = 8; j < reg->reg_num; j++, p += 36)
{
diff --git a/src/generic/const_array.cpp b/src/generic/const_array.cpp
deleted file mode 100644
index 0c09333..0000000
--- a/src/generic/const_array.cpp
+++ /dev/null
@@ -1,3 +0,0 @@
-#include "const_array.hpp"
-
-#include "../poison.hpp"
diff --git a/src/generic/const_array.hpp b/src/generic/const_array.hpp
deleted file mode 100644
index 1c70f5d..0000000
--- a/src/generic/const_array.hpp
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef TMWA_GENERIC_CONST_ARRAY_HPP
-#define TMWA_GENERIC_CONST_ARRAY_HPP
-// const_array.hpp - just a pointer-to-const and a length
-//
-// Copyright © 2011-2012 Ben Longbons <b.r.longbons@gmail.com>
-//
-// This file is part of The Mana World (Athena server)
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-# include "../sanity.hpp"
-
-# include <cstring>
-
-# include <iterator>
-# include <ostream>
-# include <vector>
-
-# ifdef WORKAROUND_GCC46_COMPILER
-// constexpr is buggy with templates in this version
-// Is this still needed now that const_string is removed?
-# define constexpr /* nothing */
-# endif
-
-// TODO see if I ever actually use this, and not the subclass
-template<class T>
-class const_array
-{
- const T *d;
- size_t n;
-public:
- typedef const T *iterator;
- typedef std::reverse_iterator<iterator> reverse_iterator;
-
- constexpr
- const_array(std::nullptr_t)
- : d(nullptr), n(0)
- {}
-
- constexpr
- const_array(const T *p, size_t z)
- : d(p), n(z)
- {}
-
- constexpr
- const_array(const T *b, const T *e)
- : d(b), n(e - b)
- {}
-
- const_array(std::initializer_list<T> list)
- : d(list.begin()), n(list.size())
- {}
-
- // Implicit conversion from std::vector
- const_array(const std::vector<T>& v)
- : d(v.data()), n(v.size())
- {}
-
- // but disallow conversion from a temporary
- const_array(std::vector<T>&&) = delete;
-
- // Oops. see src/warnings.hpp
- constexpr
- const T *data() const { return d; }
- constexpr
- size_t size() const { return n; }
- constexpr
- bool empty() const { return not n; }
- constexpr explicit
- operator bool() const { return n; }
-
- constexpr
- std::pair<const_array, const_array> cut(size_t o) const
- {
- return {const_array(d, o), const_array(d + o, n - o)};
- }
-
- constexpr
- const_array first(size_t o) const
- {
- return cut(o).first;
- }
-
- constexpr
- const_array last(size_t l) const
- {
- return cut(size() - l).second;
- }
-
- constexpr
- const_array after(size_t o) const
- {
- return cut(o).second;
- }
-
- constexpr
- iterator begin() const { return d; }
- constexpr
- iterator end() const { return d + n; }
- constexpr
- reverse_iterator rbegin() const { return reverse_iterator(end()); }
- constexpr
- reverse_iterator rend() const { return reverse_iterator(begin()); }
-
- constexpr
- const T& front() const { return *begin(); }
- constexpr
- const T& back() const { return *rbegin(); }
-
- // This probably shouldn't be used, but I'm adding it for porting.
- T& operator[](size_t i)
- {
- return const_cast<T&>(d[i]);
- }
-};
-
-# ifdef WORKAROUND_GCC46_COMPILER
-# undef constexpr
-# endif
-
-#endif // TMWA_GENERIC_CONST_ARRAY_HPP
diff --git a/src/generic/enum.hpp b/src/generic/enum.hpp
index 6f29981..29e5c36 100644
--- a/src/generic/enum.hpp
+++ b/src/generic/enum.hpp
@@ -3,6 +3,8 @@
# include "../sanity.hpp"
+# include <cassert>
+
# include <type_traits>
# include "../compat/iter.hpp"
@@ -10,17 +12,27 @@
template<class T, class E, E max>
struct earray
{
+ constexpr static
+ size_t size()
+ {
+ return static_cast<size_t>(max);
+ }
+
// no ctor/dtor and one public member variable for easy initialization
- T _data[size_t(max)];
+ T _data[size()];
T& operator[](E v)
{
- return _data[size_t(v)];
+ auto i = static_cast<size_t>(v);
+ assert (i < size());
+ return _data[i];
}
const T& operator[](E v) const
{
- return _data[size_t(v)];
+ auto i = static_cast<size_t>(v);
+ assert (i < size());
+ return _data[i];
}
T *begin()
@@ -30,7 +42,7 @@ struct earray
T *end()
{
- return _data + size_t(max);
+ return _data + size();
}
const T *begin() const
@@ -40,7 +52,7 @@ struct earray
const T *end() const
{
- return _data + size_t(max);
+ return _data + size();
}
friend bool operator == (const earray& l, const earray& r)
@@ -54,23 +66,30 @@ struct earray
}
};
-template<class T, class E>
+template<class T, class E, E max>
class eptr
{
+ constexpr static
+ size_t size()
+ {
+ return static_cast<size_t>(max);
+ }
+
T *_data;
public:
eptr(std::nullptr_t=nullptr)
: _data(nullptr)
{}
- template<E max>
eptr(earray<T, E, max>& arr)
: _data(arr._data)
{}
- T& operator [](E v)
+ T& operator [](E v) const
{
- return _data[size_t(v)];
+ auto i = static_cast<size_t>(v);
+ assert (i < size());
+ return _data[i];
}
explicit operator bool()
@@ -109,6 +128,8 @@ struct remove_enum<E, true>
};
+// This really should just go in a namespace
+// that's how I use it anyway ...
# define ENUM_BITWISE_OPERATORS(E) \
inline \
E operator & (E l, E r) \
diff --git a/src/generic/intern-pool.hpp b/src/generic/intern-pool.hpp
index 69f20ef..f9c1e8f 100644
--- a/src/generic/intern-pool.hpp
+++ b/src/generic/intern-pool.hpp
@@ -29,6 +29,7 @@ public:
ZString outtern(size_t sz) const
{
+ assert (sz < names.size());
return names[sz];
}
diff --git a/src/generic/matrix.hpp b/src/generic/matrix.hpp
index 3530ba7..b337249 100644
--- a/src/generic/matrix.hpp
+++ b/src/generic/matrix.hpp
@@ -3,6 +3,8 @@
# include "../sanity.hpp"
+# include <cassert>
+
# include "../compat/memory.hpp"
template<class T>
@@ -34,10 +36,14 @@ public:
T& ref(size_t x, size_t y)
{
+ assert (x < _xs);
+ assert (y < _ys);
return _data[x + y * _xs];
}
const T& ref(size_t x, size_t y) const
{
+ assert (x < _xs);
+ assert (y < _ys);
return _data[x + y * _xs];
}
diff --git a/src/io/cxxstdio.hpp b/src/io/cxxstdio.hpp
index 9edeebb..66419df 100644
--- a/src/io/cxxstdio.hpp
+++ b/src/io/cxxstdio.hpp
@@ -26,7 +26,6 @@
# include "../compat/cast.hpp"
-# include "../generic/const_array.hpp"
# include "../generic/enum.hpp"
# include "fwd.hpp"
diff --git a/src/login/login.cpp b/src/login/login.cpp
index c9b285f..ddc3d89 100644
--- a/src/login/login.cpp
+++ b/src/login/login.cpp
@@ -114,11 +114,11 @@ static
int display_parse_fromchar = 0; // 0: no, 1: yes (without packet 0x2714), 2: all packets
static
-struct mmo_char_server server[MAX_SERVERS];
+Array<struct mmo_char_server, MAX_SERVERS> server;
static
-Session *server_session[MAX_SERVERS];
+Array<Session *, MAX_SERVERS> server_session;
static
-int server_freezeflag[MAX_SERVERS]; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
+Array<int, MAX_SERVERS> server_freezeflag; // Char-server anti-freeze system. Counter. 5 ok, 4...0 freezed
static
int anti_freeze_enable = 0;
static
@@ -158,13 +158,14 @@ void SessionDeleter::operator()(SessionData *)
#pragma GCC diagnostic pop
constexpr int AUTH_FIFO_SIZE = 256;
-struct
+struct AuthFifo
{
int account_id, login_id1, login_id2;
IP4Address ip;
SEX sex;
int delflag;
-} auth_fifo[AUTH_FIFO_SIZE];
+};
+Array<AuthFifo, AUTH_FIFO_SIZE> auth_fifo;
static
int auth_fifo_pos = 0;
@@ -184,7 +185,7 @@ struct AuthData
IP4Address last_ip; // save of last IP of connection
VString<254> memo; // a memo field
int account_reg2_num;
- struct global_reg account_reg2[ACCOUNT_REG2_NUM];
+ Array<struct global_reg, ACCOUNT_REG2_NUM> account_reg2;
};
static
std::vector<AuthData> auth_data;
@@ -447,6 +448,7 @@ AString mmo_auth_tostr(const AuthData *p)
p->memo,
p->ban_until_time);
+ assert (p->account_reg2_num < ACCOUNT_REG2_NUM);
for (int i = 0; i < p->account_reg2_num; i++)
if (p->account_reg2[i].str)
str += STRPRINTF("%s,%d ",
@@ -522,7 +524,7 @@ bool extract(XString line, AuthData *ad)
if (vars.size() > ACCOUNT_REG2_NUM)
return false;
- std::copy(vars.begin(), vars.end(), ad->account_reg2);
+ std::copy(vars.begin(), vars.end(), ad->account_reg2.begin());
ad->account_reg2_num = vars.size();
return true;
@@ -3827,34 +3829,36 @@ bool login_confs(XString key, ZString value)
//------------------------------
// Main function of login-server
//------------------------------
-int do_init(int argc, ZString *argv)
+int do_init(Slice<ZString> argv)
{
+ ZString argv0 = argv.pop_front();
bool loaded_config_yet = false;
- for (int i = 1; i < argc; ++i)
+ while (argv)
{
- if (argv[i].startswith('-'))
+ ZString argvi = argv.pop_front();
+ if (argvi.startswith('-'))
{
- if (argv[i] == "--help")
+ if (argvi == "--help")
{
PRINTF("Usage: %s [--help] [--version] [files...]\n",
- argv[0]);
+ argv0);
exit(0);
}
- else if (argv[i] == "--version")
+ else if (argvi == "--version")
{
PRINTF("%s\n", CURRENT_VERSION_STRING);
exit(0);
}
else
{
- FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ FPRINTF(stderr, "Unknown argument: %s\n", argvi);
runflag = false;
}
}
else
{
loaded_config_yet = true;
- runflag &= load_config_file(argv[i], login_confs);
+ runflag &= load_config_file(argvi, login_confs);
}
}
diff --git a/src/map/atcommand.hpp b/src/map/atcommand.hpp
index 16d1efc..45759a6 100644
--- a/src/map/atcommand.hpp
+++ b/src/map/atcommand.hpp
@@ -3,8 +3,6 @@
# include "../strings/fwd.hpp"
-# include "../generic/const_array.hpp"
-
# include "map.hpp"
bool is_atcommand(Session *s, dumb_ptr<map_session_data> sd,
diff --git a/src/map/battle.cpp b/src/map/battle.cpp
index 7e563b8..49a0538 100644
--- a/src/map/battle.cpp
+++ b/src/map/battle.cpp
@@ -166,7 +166,7 @@ int battle_get_max_hp(dumb_ptr<block_list> bl)
int battle_get_str(dumb_ptr<block_list> bl)
{
int str = 0;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
sc_data = battle_get_sc_data(bl);
@@ -189,7 +189,7 @@ int battle_get_str(dumb_ptr<block_list> bl)
int battle_get_agi(dumb_ptr<block_list> bl)
{
int agi = 0;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
sc_data = battle_get_sc_data(bl);
@@ -211,7 +211,7 @@ int battle_get_agi(dumb_ptr<block_list> bl)
int battle_get_vit(dumb_ptr<block_list> bl)
{
int vit = 0;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
sc_data = battle_get_sc_data(bl);
@@ -233,7 +233,7 @@ int battle_get_vit(dumb_ptr<block_list> bl)
int battle_get_int(dumb_ptr<block_list> bl)
{
int int_ = 0;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
sc_data = battle_get_sc_data(bl);
@@ -255,7 +255,7 @@ int battle_get_int(dumb_ptr<block_list> bl)
int battle_get_dex(dumb_ptr<block_list> bl)
{
int dex = 0;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
sc_data = battle_get_sc_data(bl);
@@ -277,7 +277,7 @@ int battle_get_dex(dumb_ptr<block_list> bl)
int battle_get_luk(dumb_ptr<block_list> bl)
{
int luk = 0;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
sc_data = battle_get_sc_data(bl);
@@ -300,7 +300,7 @@ static
int battle_get_flee(dumb_ptr<block_list> bl)
{
int flee = 1;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_retr(1, bl);
sc_data = battle_get_sc_data(bl);
@@ -329,7 +329,7 @@ static
int battle_get_hit(dumb_ptr<block_list> bl)
{
int hit = 1;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_retr(1, bl);
sc_data = battle_get_sc_data(bl);
@@ -357,7 +357,7 @@ static
int battle_get_flee2(dumb_ptr<block_list> bl)
{
int flee2 = 1;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_retr(1, bl);
sc_data = battle_get_sc_data(bl);
@@ -389,7 +389,7 @@ static
int battle_get_critical(dumb_ptr<block_list> bl)
{
int critical = 1;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_retr(1, bl);
sc_data = battle_get_sc_data(bl);
@@ -415,7 +415,7 @@ int battle_get_critical(dumb_ptr<block_list> bl)
static
int battle_get_baseatk(dumb_ptr<block_list> bl)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int batk = 1;
nullpo_retr(1, bl);
@@ -442,7 +442,7 @@ int battle_get_baseatk(dumb_ptr<block_list> bl)
static
int battle_get_atk(dumb_ptr<block_list> bl)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int atk = 0;
nullpo_ret(bl);
@@ -518,7 +518,7 @@ int battle_get_atk_2(dumb_ptr<block_list> bl)
static
int battle_get_matk1(dumb_ptr<block_list> bl)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
sc_data = battle_get_sc_data(bl);
if (bl->bl_type == BL::MOB)
@@ -563,7 +563,7 @@ int battle_get_matk2(dumb_ptr<block_list> bl)
*/
int battle_get_def(dumb_ptr<block_list> bl)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int def = 0;
nullpo_ret(bl);
@@ -599,7 +599,7 @@ int battle_get_def(dumb_ptr<block_list> bl)
*/
int battle_get_mdef(dumb_ptr<block_list> bl)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int mdef = 0;
nullpo_ret(bl);
@@ -634,7 +634,7 @@ int battle_get_mdef(dumb_ptr<block_list> bl)
*/
int battle_get_def2(dumb_ptr<block_list> bl)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int def2 = 1;
nullpo_retr(1, bl);
@@ -715,7 +715,7 @@ interval_t battle_get_adelay(dumb_ptr<block_list> bl)
return bl->is_player()->aspd * 2;
else
{
- eptr<struct status_change, StatusChange> sc_data = battle_get_sc_data(bl);
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data = battle_get_sc_data(bl);
interval_t adelay = std::chrono::seconds(4);
int aspd_rate = 100;
if (bl->bl_type == BL::MOB)
@@ -743,7 +743,7 @@ interval_t battle_get_amotion(dumb_ptr<block_list> bl)
return bl->is_player()->amotion;
else
{
- eptr<struct status_change, StatusChange> sc_data = battle_get_sc_data(bl);
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data = battle_get_sc_data(bl);
interval_t amotion = std::chrono::seconds(2);
int aspd_rate = 100;
if (bl->bl_type == BL::MOB)
@@ -846,7 +846,7 @@ int battle_get_stat(SP stat_id, dumb_ptr<block_list> bl)
}
// StatusChange系の所得
-eptr<struct status_change, StatusChange> battle_get_sc_data(dumb_ptr<block_list> bl)
+eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> battle_get_sc_data(dumb_ptr<block_list> bl)
{
nullpo_retr(nullptr, bl);
@@ -1064,7 +1064,7 @@ struct Damage battle_calc_mob_weapon_attack(dumb_ptr<block_list> src,
BF flag;
int ac_flag = 0;
ATK dmg_lv = ATK::ZERO;
- eptr<struct status_change, StatusChange> sc_data, t_sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data, t_sc_data;
nullpo_retr(wd, src);
nullpo_retr(wd, target);
@@ -1337,7 +1337,7 @@ struct Damage battle_calc_pc_weapon_attack(dumb_ptr<block_list> src,
int div_;
BF flag;
ATK dmg_lv = ATK::ZERO;
- eptr<struct status_change, StatusChange> sc_data, t_sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data, t_sc_data;
int atkmax_ = 0, atkmin_ = 0; //二刀流用
int watk, watk_;
bool da = false;
@@ -1959,7 +1959,7 @@ ATK battle_weapon_attack(dumb_ptr<block_list> src, dumb_ptr<block_list> target,
tick_t tick)
{
dumb_ptr<map_session_data> sd = NULL;
- eptr<struct status_change, StatusChange> t_sc_data = battle_get_sc_data(target);
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> t_sc_data = battle_get_sc_data(target);
struct Damage wd;
nullpo_retr(ATK::ZERO, src);
diff --git a/src/map/battle.hpp b/src/map/battle.hpp
index fd452e8..5c62785 100644
--- a/src/map/battle.hpp
+++ b/src/map/battle.hpp
@@ -78,7 +78,7 @@ Race battle_get_race(dumb_ptr<block_list> bl);
MobMode battle_get_mode(dumb_ptr<block_list> bl);
int battle_get_stat(SP stat_id, dumb_ptr<block_list> bl);
-eptr<struct status_change, StatusChange> battle_get_sc_data(dumb_ptr<block_list> bl);
+eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> battle_get_sc_data(dumb_ptr<block_list> bl);
short *battle_get_sc_count(dumb_ptr<block_list> bl);
Opt1 *battle_get_opt1(dumb_ptr<block_list> bl);
Opt2 *battle_get_opt2(dumb_ptr<block_list> bl);
diff --git a/src/map/clif.cpp b/src/map/clif.cpp
index a5b02cd..3290013 100644
--- a/src/map/clif.cpp
+++ b/src/map/clif.cpp
@@ -2021,7 +2021,7 @@ int clif_misceffect(dumb_ptr<block_list> bl, int type)
int clif_changeoption(dumb_ptr<block_list> bl)
{
uint8_t buf[32];
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
@@ -2435,7 +2435,7 @@ int clif_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst,
int div, DamageType type, int damage2)
{
unsigned char buf[256];
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(src);
nullpo_ret(dst);
@@ -2800,7 +2800,7 @@ int clif_skill_damage(dumb_ptr<block_list> src, dumb_ptr<block_list> dst,
int div, SkillID skill_id, int skill_lv, int type)
{
unsigned char buf[64];
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(src);
nullpo_ret(dst);
diff --git a/src/map/clif.hpp b/src/map/clif.hpp
index c346f7d..571f68e 100644
--- a/src/map/clif.hpp
+++ b/src/map/clif.hpp
@@ -7,8 +7,6 @@
# include "../strings/fwd.hpp"
-# include "../generic/const_array.hpp"
-
# include "../mmo/ip.hpp"
# include "../mmo/timer.t.hpp"
diff --git a/src/map/intif.cpp b/src/map/intif.cpp
index 7f7be73..b2b95fe 100644
--- a/src/map/intif.cpp
+++ b/src/map/intif.cpp
@@ -104,6 +104,7 @@ void intif_saveaccountreg(dumb_ptr<map_session_data> sd)
int j, p;
nullpo_retv(sd);
+ assert (sd->status.account_reg_num < ACCOUNT_REG_NUM);
WFIFOW(char_session, 0) = 0x3004;
WFIFOL(char_session, 4) = sd->bl_id;
diff --git a/src/map/intif.hpp b/src/map/intif.hpp
index ac2740c..7028ed9 100644
--- a/src/map/intif.hpp
+++ b/src/map/intif.hpp
@@ -3,8 +3,6 @@
# include "../strings/fwd.hpp"
-# include "../generic/const_array.hpp"
-
# include "map.hpp"
int intif_parse(Session *);
diff --git a/src/map/magic-expr-eval.hpp b/src/map/magic-expr-eval.hpp
index 0783dc8..4de2f81 100644
--- a/src/map/magic-expr-eval.hpp
+++ b/src/map/magic-expr-eval.hpp
@@ -1,6 +1,8 @@
#ifndef TMWA_MAP_MAGIC_EXPR_EVAL_HPP
#define TMWA_MAP_MAGIC_EXPR_EVAL_HPP
+# include "../range/slice.hpp"
+
# include "../strings/zstring.hpp"
# include "magic-interpreter.hpp"
@@ -8,7 +10,7 @@
/* Helper definitions for dealing with functions and operations */
int magic_signature_check(ZString opname, ZString funname, ZString signature,
- int args_nr, val_t *args, int line, int column);
+ Slice<val_t> args, int line, int column);
void magic_area_rect(map_local **m, int *x, int *y, int *width, int *height,
area_t& area);
diff --git a/src/map/magic-expr.cpp b/src/map/magic-expr.cpp
index 1be1b0b..1881afc 100644
--- a/src/map/magic-expr.cpp
+++ b/src/map/magic-expr.cpp
@@ -261,7 +261,7 @@ void make_spell(val_t *v)
}
static
-int fun_add(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_add(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARG_TYPE(0) == TYPE::INT && ARG_TYPE(1) == TYPE::INT)
{
@@ -296,21 +296,21 @@ int fun_add(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_sub(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_sub(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) - ARGINT(1);
return 0;
}
static
-int fun_mul(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_mul(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) * ARGINT(1);
return 0;
}
static
-int fun_div(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_div(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (!ARGINT(1))
return 1; /* division by zero */
@@ -319,7 +319,7 @@ int fun_div(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_mod(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_mod(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (!ARGINT(1))
return 1; /* division by zero */
@@ -328,35 +328,35 @@ int fun_mod(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_or(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_or(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) || ARGINT(1);
return 0;
}
static
-int fun_and(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_and(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) && ARGINT(1);
return 0;
}
static
-int fun_not(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_not(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = !ARGINT(0);
return 0;
}
static
-int fun_neg(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_neg(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ~ARGINT(0);
return 0;
}
static
-int fun_gte(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_gte(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING)
{
@@ -374,7 +374,7 @@ int fun_gte(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_lt(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
+int fun_lt(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args)
{
fun_gte(env, result, args);
RESULTINT = !RESULTINT;
@@ -382,7 +382,7 @@ int fun_lt(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
}
static
-int fun_gt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_gt(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING)
{
@@ -400,7 +400,7 @@ int fun_gt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_lte(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
+int fun_lte(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args)
{
fun_gt(env, result, args);
RESULTINT = !RESULTINT;
@@ -408,7 +408,7 @@ int fun_lte(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
}
static
-int fun_eq(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_eq(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARG_TYPE(0) == TYPE::STRING || ARG_TYPE(1) == TYPE::STRING)
{
@@ -440,7 +440,7 @@ int fun_eq(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_ne(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
+int fun_ne(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args)
{
fun_eq(env, result, args);
RESULTINT = !RESULTINT;
@@ -448,56 +448,56 @@ int fun_ne(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
}
static
-int fun_bitand(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_bitand(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) & ARGINT(1);
return 0;
}
static
-int fun_bitor(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_bitor(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) | ARGINT(1);
return 0;
}
static
-int fun_bitxor(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_bitxor(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) ^ ARGINT(1);
return 0;
}
static
-int fun_bitshl(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_bitshl(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) << ARGINT(1);
return 0;
}
static
-int fun_bitshr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_bitshr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGINT(0) >> ARGINT(1);
return 0;
}
static
-int fun_max(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_max(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = max(ARGINT(0), ARGINT(1));
return 0;
}
static
-int fun_min(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_min(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = min(ARGINT(0), ARGINT(1));
return 0;
}
static
-int fun_if_then_else(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_if_then_else(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARGINT(0))
magic_copy_var(result, &args[1]);
@@ -606,7 +606,7 @@ int magic_location_in_area(map_local *m, int x, int y, dumb_ptr<area_t> area)
}
static
-int fun_is_in(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_is_in(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = magic_location_in_area(ARGLOCATION(0).m,
ARGLOCATION(0).x,
@@ -615,7 +615,7 @@ int fun_is_in(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_skill(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_skill(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ENTITY_TYPE(0) != BL::PC
// don't convert to enum until after the range check
@@ -633,18 +633,18 @@ int fun_skill(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_his_shroud(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_his_shroud(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->state.shroud_active);
return 0;
}
-#define BATTLE_GETTER(name) \
-static \
-int fun_get_##name(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) \
-{ \
- RESULTINT = battle_get_##name(ARGENTITY(0)); \
- return 0; \
+#define BATTLE_GETTER(name) \
+static \
+int fun_get_##name(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) \
+{ \
+ RESULTINT = battle_get_##name(ARGENTITY(0)); \
+ return 0; \
}
BATTLE_GETTER(str)
@@ -659,28 +659,28 @@ BATTLE_GETTER(mdef)
BATTLE_GETTER(def)
BATTLE_GETTER(max_hp)
static
-int fun_get_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_get_dir(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTDIR = battle_get_dir(ARGENTITY(0));
return 0;
}
-#define MMO_GETTER(name) \
-static \
-int fun_get_##name(dumb_ptr<env_t>, val_t *result, const_array<val_t> args) \
-{ \
- if (ENTITY_TYPE(0) == BL::PC) \
- RESULTINT = ARGPC(0)->status.name; \
- else \
- RESULTINT = 0; \
- return 0; \
+#define MMO_GETTER(name) \
+static \
+int fun_get_##name(dumb_ptr<env_t>, val_t *result, Slice<val_t> args) \
+{ \
+ if (ENTITY_TYPE(0) == BL::PC) \
+ RESULTINT = ARGPC(0)->status.name; \
+ else \
+ RESULTINT = 0; \
+ return 0; \
}
MMO_GETTER(sp)
MMO_GETTER(max_sp)
static
-int fun_name_of(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_name_of(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARG_TYPE(0) == TYPE::ENTITY)
{
@@ -702,7 +702,7 @@ int fun_name_of(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
/* [Freeyorp] I'm putting this one in as name_of seems to have issues with summoned or spawned mobs. */
static
-int fun_mob_id(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_mob_id(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ENTITY_TYPE(0) != BL::MOB)
return 1;
@@ -727,14 +727,14 @@ void COPY_LOCATION(location_t& dest, block_list& src)
}
static
-int fun_location(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_location(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
COPY_LOCATION(RESULTLOCATION, *(ARGENTITY(0)));
return 0;
}
static
-int fun_random(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_random(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
int delta = ARGINT(0);
if (delta < 0)
@@ -752,7 +752,7 @@ int fun_random(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_random_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_random_dir(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARGINT(0))
RESULTDIR = random_::choice({DIR::S, DIR::SW, DIR::W, DIR::NW, DIR::N, DIR::NE, DIR::E, DIR::SE});
@@ -762,14 +762,14 @@ int fun_random_dir(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_hash_entity(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_hash_entity(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARGENTITY(0)->bl_id;
return 0;
}
int // ret -1: not a string, ret 1: no such item, ret 0: OK
-magic_find_item(const_array<val_t> args, int index, struct item *item_, int *stackable)
+magic_find_item(Slice<val_t> args, int index, struct item *item_, int *stackable)
{
struct item_data *item_data;
int must_add_sequentially;
@@ -801,7 +801,7 @@ magic_find_item(const_array<val_t> args, int index, struct item *item_, int *sta
}
static
-int fun_count_item(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_count_item(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
int stackable;
@@ -817,7 +817,7 @@ int fun_count_item(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_is_equipped(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_is_equipped(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
dumb_ptr<map_session_data> chr = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
int stackable;
@@ -843,28 +843,28 @@ int fun_is_equipped(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_is_married(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_is_married(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->status.partner_id);
return 0;
}
static
-int fun_is_dead(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_is_dead(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = (ENTITY_TYPE(0) == BL::PC && pc_isdead(ARGPC(0)));
return 0;
}
static
-int fun_is_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_is_pc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = (ENTITY_TYPE(0) == BL::PC);
return 0;
}
static
-int fun_partner(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_partner(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ENTITY_TYPE(0) == BL::PC && ARGPC(0)->status.partner_id)
{
@@ -877,7 +877,7 @@ int fun_partner(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_awayfrom(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_awayfrom(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
location_t *loc = &ARGLOCATION(0);
int dx = dirx[ARGDIR(1)];
@@ -896,14 +896,14 @@ int fun_awayfrom(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_failed(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_failed(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = ARG_TYPE(0) == TYPE::FAIL;
return 0;
}
static
-int fun_npc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_npc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
NpcName name = stringish<NpcName>(ARGSTR(0));
RESULTENTITY = npc_name2id(name);
@@ -911,7 +911,7 @@ int fun_npc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_pc(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
CharName name = stringish<CharName>(ARGSTR(0));
RESULTENTITY = map_nick2sd(name);
@@ -919,7 +919,7 @@ int fun_pc(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_distance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_distance(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARGLOCATION(0).m != ARGLOCATION(1).m)
RESULTINT = 0x7fffffff;
@@ -930,7 +930,7 @@ int fun_distance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_rdistance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_rdistance(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ARGLOCATION(0).m != ARGLOCATION(1).m)
RESULTINT = 0x7fffffff;
@@ -944,7 +944,7 @@ int fun_rdistance(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_anchor(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
+int fun_anchor(dumb_ptr<env_t> env, val_t *result, Slice<val_t> args)
{
dumb_ptr<teleport_anchor_t> anchor = magic_find_anchor(ARGSTR(0));
@@ -964,7 +964,7 @@ int fun_anchor(dumb_ptr<env_t> env, val_t *result, const_array<val_t> args)
}
static
-int fun_line_of_sight(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_line_of_sight(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
block_list e1, e2;
@@ -1020,14 +1020,14 @@ void magic_random_location(location_t *dest, dumb_ptr<area_t> area)
}
static
-int fun_pick_location(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_pick_location(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
magic_random_location(&result->v.v_location, ARGAREA(0));
return 0;
}
static
-int fun_read_script_int(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_read_script_int(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
dumb_ptr<block_list> subject_p = ARGENTITY(0);
VarName var_name = stringish<VarName>(ARGSTR(1));
@@ -1041,7 +1041,7 @@ int fun_read_script_int(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_read_script_str(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_read_script_str(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
dumb_ptr<block_list> subject_p = ARGENTITY(0);
VarName var_name = stringish<VarName>(ARGSTR(1));
@@ -1055,7 +1055,7 @@ int fun_read_script_str(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_rbox(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_rbox(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
location_t loc = ARGLOCATION(0);
int radius = ARGINT(1);
@@ -1071,7 +1071,7 @@ int fun_rbox(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_running_status_update(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_running_status_update(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
if (ENTITY_TYPE(0) != BL::PC && ENTITY_TYPE(0) != BL::MOB)
return 1;
@@ -1082,28 +1082,28 @@ int fun_running_status_update(dumb_ptr<env_t>, val_t *result, const_array<val_t>
}
static
-int fun_status_option(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_status_option(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = (bool((ARGPC(0))->status.option & static_cast<Option>(ARGINT(1))));
return 0;
}
static
-int fun_element(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_element(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = static_cast<int>(battle_get_element(ARGENTITY(0)).element);
return 0;
}
static
-int fun_element_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_element_level(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = battle_get_element(ARGENTITY(0)).level;
return 0;
}
static
-int fun_is_exterior(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_is_exterior(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
#warning "Evil assumptions!"
RESULTINT = ARGLOCATION(0).m->name_[4] == '1';
@@ -1111,14 +1111,14 @@ int fun_is_exterior(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_contains_string(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_contains_string(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = NULL != strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str());
return 0;
}
static
-int fun_strstr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_strstr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
const char *offset = strstr(ARGSTR(0).c_str(), ARGSTR(1).c_str());
RESULTINT = offset - ARGSTR(0).c_str();
@@ -1126,14 +1126,14 @@ int fun_strstr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_strlen(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_strlen(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = strlen(ARGSTR(0).c_str());
return 0;
}
static
-int fun_substr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_substr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
const char *src = ARGSTR(0).c_str();
const int slen = strlen(src);
@@ -1159,14 +1159,14 @@ int fun_substr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_sqrt(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_sqrt(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
RESULTINT = static_cast<int>(sqrt(ARGINT(0)));
return 0;
}
static
-int fun_map_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_map_level(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
#warning "Evil assumptions!"
RESULTINT = ARGLOCATION(0).m->name_[4] - '0';
@@ -1174,7 +1174,7 @@ int fun_map_level(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_map_nr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_map_nr(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
#warning "Evil assumptions!"
MapName mapname = ARGLOCATION(0).m->name_;
@@ -1185,7 +1185,7 @@ int fun_map_nr(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_dir_towards(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_dir_towards(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
int dx;
int dy;
@@ -1251,7 +1251,7 @@ int fun_dir_towards(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
}
static
-int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, const_array<val_t> args)
+int fun_extract_healer_xp(dumb_ptr<env_t>, val_t *result, Slice<val_t> args)
{
dumb_ptr<map_session_data> sd = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
@@ -1526,10 +1526,10 @@ TYPE type_key(char ty_key)
}
int magic_signature_check(ZString opname, ZString funname, ZString signature,
- int args_nr, val_t *args, int line, int column)
+ Slice<val_t> args, int line, int column)
{
int i;
- for (i = 0; i < args_nr; i++)
+ for (i = 0; i < args.size(); i++)
{
val_t *arg = &args[i];
char ty_key = signature[i];
@@ -1553,8 +1553,8 @@ int magic_signature_check(ZString opname, ZString funname, ZString signature,
if (!ty_key)
{
FPRINTF(stderr,
- "[magic-eval]: L%d:%d: Too many arguments (%d) to %s `%s'\n",
- line, column, args_nr, opname, funname);
+ "[magic-eval]: L%d:%d: Too many arguments (%zu) to %s `%s'\n",
+ line, column, args.size(), opname, funname);
return 1;
}
@@ -1640,9 +1640,9 @@ void magic_eval(dumb_ptr<env_t> env, val_t *dest, dumb_ptr<expr_t> expr)
for (i = 0; i < args_nr; ++i)
magic_eval(env, &arguments[i], expr->e.e_funapp.args[i]);
- if (magic_signature_check("function", f->name, f->signature, args_nr, arguments,
+ if (magic_signature_check("function", f->name, f->signature, Slice<val_t>(arguments, args_nr),
expr->e.e_funapp.line_nr, expr->e.e_funapp.column)
- || f->fun(env, dest, const_array<val_t>(arguments, args_nr)))
+ || f->fun(env, dest, Slice<val_t>(arguments, args_nr)))
dest->ty = TYPE::FAIL;
else
{
diff --git a/src/map/magic-expr.hpp b/src/map/magic-expr.hpp
index 79fdc3f..b2b0dd2 100644
--- a/src/map/magic-expr.hpp
+++ b/src/map/magic-expr.hpp
@@ -3,6 +3,8 @@
# include "magic-interpreter.hpp"
+# include "../range/slice.hpp"
+
# include "../strings/fwd.hpp"
# include "../strings/zstring.hpp"
@@ -24,14 +26,14 @@ struct fun_t
ZString name;
ZString signature;
char ret_ty;
- int (*fun)(dumb_ptr<env_t> env, val_t *result, const_array<val_t> arga);
+ int (*fun)(dumb_ptr<env_t> env, val_t *result, Slice<val_t> arga);
};
struct op_t
{
ZString name;
ZString signature;
- int (*op)(dumb_ptr<env_t> env, const_array<val_t> arga);
+ int (*op)(dumb_ptr<env_t> env, Slice<val_t> arga);
};
/**
@@ -72,7 +74,7 @@ void magic_copy_var(val_t *dest, val_t *src);
void magic_random_location(location_t *dest, dumb_ptr<area_t> area);
// ret -1: not a string, ret 1: no such item, ret 0: OK
-int magic_find_item(const_array<val_t> args, int index, struct item *item, int *stackable);
+int magic_find_item(Slice<val_t> args, int index, struct item *item, int *stackable);
# define GET_ARG_ITEM(index, dest, stackable) \
switch (magic_find_item(args, index, &dest, &stackable)) \
diff --git a/src/map/magic-stmt.cpp b/src/map/magic-stmt.cpp
index 4063a68..081651c 100644
--- a/src/map/magic-stmt.cpp
+++ b/src/map/magic-stmt.cpp
@@ -298,7 +298,7 @@ dumb_ptr<npc_data> local_spell_effect(map_local *m, int x, int y, int effect,
}
static
-int op_sfx(dumb_ptr<env_t>, const_array<val_t> args)
+int op_sfx(dumb_ptr<env_t>, Slice<val_t> args)
{
interval_t delay = static_cast<interval_t>(ARGINT(2));
@@ -319,7 +319,7 @@ int op_sfx(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_instaheal(dumb_ptr<env_t> env, const_array<val_t> args)
+int op_instaheal(dumb_ptr<env_t> env, Slice<val_t> args)
{
dumb_ptr<block_list> caster = (env->VAR(VAR_CASTER).ty == TYPE::ENTITY)
? map_id2bl(env->VAR(VAR_CASTER).v.v_int) : NULL;
@@ -340,7 +340,7 @@ int op_instaheal(dumb_ptr<env_t> env, const_array<val_t> args)
}
static
-int op_itemheal(dumb_ptr<env_t> env, const_array<val_t> args)
+int op_itemheal(dumb_ptr<env_t> env, Slice<val_t> args)
{
dumb_ptr<block_list> subject = ARGENTITY(0);
if (subject->bl_type == BL::PC)
@@ -370,7 +370,7 @@ using e::Shroud;
#define ARGCHAR(n) (ARGENTITY(n)->is_player())
static
-int op_shroud(dumb_ptr<env_t>, const_array<val_t> args)
+int op_shroud(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> subject = ARGCHAR(0);
Shroud arg = static_cast<Shroud>(ARGINT(1));
@@ -389,7 +389,7 @@ int op_shroud(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_reveal(dumb_ptr<env_t>, const_array<val_t> args)
+int op_reveal(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> subject = ARGCHAR(0);
@@ -400,7 +400,7 @@ int op_reveal(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_message(dumb_ptr<env_t>, const_array<val_t> args)
+int op_message(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> subject = ARGCHAR(0);
@@ -419,7 +419,7 @@ void timer_callback_kill_npc(TimerData *, tick_t, int npc_id)
}
static
-int op_messenger_npc(dumb_ptr<env_t>, const_array<val_t> args)
+int op_messenger_npc(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<npc_data> npc;
location_t *loc = &ARGLOCATION(0);
@@ -476,7 +476,7 @@ void entity_warp(dumb_ptr<block_list> target, map_local *destm, int destx, int d
}
static
-int op_move(dumb_ptr<env_t>, const_array<val_t> args)
+int op_move(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<block_list> subject = ARGENTITY(0);
DIR dir = ARGDIR(1);
@@ -491,7 +491,7 @@ int op_move(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_warp(dumb_ptr<env_t>, const_array<val_t> args)
+int op_warp(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<block_list> subject = ARGENTITY(0);
location_t *loc = &ARGLOCATION(1);
@@ -502,7 +502,7 @@ int op_warp(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_banish(dumb_ptr<env_t>, const_array<val_t> args)
+int op_banish(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<block_list> subject = ARGENTITY(0);
@@ -529,7 +529,7 @@ void record_status_change(dumb_ptr<invocation> invocation_, int bl_id,
}
static
-int op_status_change(dumb_ptr<env_t> env, const_array<val_t> args)
+int op_status_change(dumb_ptr<env_t> env, Slice<val_t> args)
{
dumb_ptr<block_list> subject = ARGENTITY(0);
int invocation_id = env->VAR(VAR_INVOCATION).ty == TYPE::INVOCATION
@@ -550,7 +550,7 @@ int op_status_change(dumb_ptr<env_t> env, const_array<val_t> args)
}
static
-int op_stop_status_change(dumb_ptr<env_t>, const_array<val_t> args)
+int op_stop_status_change(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<block_list> subject = ARGENTITY(0);
@@ -561,7 +561,7 @@ int op_stop_status_change(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_override_attack(dumb_ptr<env_t> env, const_array<val_t> args)
+int op_override_attack(dumb_ptr<env_t> env, Slice<val_t> args)
{
dumb_ptr<block_list> psubject = ARGENTITY(0);
int charges = ARGINT(1);
@@ -602,7 +602,7 @@ int op_override_attack(dumb_ptr<env_t> env, const_array<val_t> args)
}
static
-int op_create_item(dumb_ptr<env_t>, const_array<val_t> args)
+int op_create_item(dumb_ptr<env_t>, Slice<val_t> args)
{
struct item item;
dumb_ptr<block_list> entity = ARGENTITY(0);
@@ -640,7 +640,7 @@ bool AGGRAVATION_MODE_MAKES_AGGRESSIVE(int n)
}
static
-int op_aggravate(dumb_ptr<env_t>, const_array<val_t> args)
+int op_aggravate(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<block_list> victim = ARGENTITY(2);
int mode = ARGINT(1);
@@ -675,7 +675,7 @@ enum class MonsterAttitude
};
static
-int op_spawn(dumb_ptr<env_t>, const_array<val_t> args)
+int op_spawn(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<area_t> area = ARGAREA(0);
dumb_ptr<block_list> owner_e = ARGENTITY(1);
@@ -766,7 +766,7 @@ const char *get_invocation_name(dumb_ptr<env_t> env)
}
static
-int op_injure(dumb_ptr<env_t> env, const_array<val_t> args)
+int op_injure(dumb_ptr<env_t> env, Slice<val_t> args)
{
dumb_ptr<block_list> caster = ARGENTITY(0);
dumb_ptr<block_list> target = ARGENTITY(1);
@@ -816,7 +816,7 @@ int op_injure(dumb_ptr<env_t> env, const_array<val_t> args)
}
static
-int op_emote(dumb_ptr<env_t>, const_array<val_t> args)
+int op_emote(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<block_list> victim = ARGENTITY(0);
int emotion = ARGINT(1);
@@ -826,7 +826,7 @@ int op_emote(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_set_script_variable(dumb_ptr<env_t>, const_array<val_t> args)
+int op_set_script_variable(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
VarName varname = stringish<VarName>(ARGSTR(1));
@@ -841,7 +841,7 @@ int op_set_script_variable(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_set_script_str(dumb_ptr<env_t>, const_array<val_t> args)
+int op_set_script_str(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
VarName varname = stringish<VarName>(ARGSTR(1));
@@ -856,7 +856,7 @@ int op_set_script_str(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_set_hair_colour(dumb_ptr<env_t>, const_array<val_t> args)
+int op_set_hair_colour(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
@@ -869,7 +869,7 @@ int op_set_hair_colour(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_set_hair_style(dumb_ptr<env_t>, const_array<val_t> args)
+int op_set_hair_style(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
@@ -882,7 +882,7 @@ int op_set_hair_style(dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_drop_item_for (dumb_ptr<env_t>, const_array<val_t> args)
+int op_drop_item_for (dumb_ptr<env_t>, Slice<val_t> args)
{
struct item item;
int stackable;
@@ -908,7 +908,7 @@ int op_drop_item_for (dumb_ptr<env_t>, const_array<val_t> args)
}
static
-int op_gain_exp(dumb_ptr<env_t>, const_array<val_t> args)
+int op_gain_exp(dumb_ptr<env_t>, Slice<val_t> args)
{
dumb_ptr<map_session_data> c = (ENTITY_TYPE(0) == BL::PC) ? ARGPC(0) : NULL;
@@ -1468,7 +1468,7 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
int newpos = run_script_l(
ScriptPointer(&*e->e.e_script, invocation_->script_pos),
message_recipient, invocation_->bl_id,
- 3, arg);
+ arg);
/* Returns the new script position, or -1 once the script is finished */
if (newpos != -1)
{
@@ -1498,10 +1498,10 @@ interval_t spell_run(dumb_ptr<invocation> invocation_, int allow_delete)
magic_eval(invocation_->env, &args[i], e->e.e_op.args[i]);
if (!magic_signature_check("effect", op->name, op->signature,
- e->e.e_op.args_nr, args,
+ Slice<val_t>(args, e->e.e_op.args_nr),
e->e.e_op.line_nr,
e->e.e_op.column))
- op->op(invocation_->env, const_array<val_t>(args, e->e.e_op.args_nr));
+ op->op(invocation_->env, Slice<val_t>(args, e->e.e_op.args_nr));
for (i = 0; i < e->e.e_op.args_nr; i++)
magic_clear_var(&args[i]);
diff --git a/src/map/magic-v2.cpp b/src/map/magic-v2.cpp
index 1fad61d..41d29cd 100644
--- a/src/map/magic-v2.cpp
+++ b/src/map/magic-v2.cpp
@@ -254,7 +254,7 @@ namespace magic_v2
return true;
}
static
- bool op_effect(io::LineSpan span, ZString name, const_array<dumb_ptr<expr_t>> argv, dumb_ptr<effect_t>& effect)
+ bool op_effect(io::LineSpan span, ZString name, Slice<dumb_ptr<expr_t>> argv, dumb_ptr<effect_t>& effect)
{
op_t *op = magic_get_op(name);
if (!op)
@@ -290,7 +290,7 @@ namespace magic_v2
return retval;
}
static
- bool fun_expr(io::LineSpan span, ZString name, const_array<dumb_ptr<expr_t>> argv, dumb_ptr<expr_t>& expr)
+ bool fun_expr(io::LineSpan span, ZString name, Slice<dumb_ptr<expr_t>> argv, dumb_ptr<expr_t>& expr)
{
fun_t *fun = magic_get_fun(name);
if (!fun)
@@ -322,7 +322,7 @@ namespace magic_v2
e[0] = left;
e[1] = right;
dumb_ptr<expr_t> rv;
- if (!fun_expr(span, name, const_array<dumb_ptr<expr_t>>(e, 2), rv))
+ if (!fun_expr(span, name, e, rv))
abort();
return rv;
}
diff --git a/src/map/map.cpp b/src/map/map.cpp
index e5a3341..f701730 100644
--- a/src/map/map.cpp
+++ b/src/map/map.cpp
@@ -72,7 +72,7 @@ Map<int, struct charid2nick> charid_db;
static
int users = 0;
static
-dumb_ptr<block_list> object[MAX_FLOORITEM];
+Array<dumb_ptr<block_list>, MAX_FLOORITEM> object;
static
int first_free_object_id = 0, last_object_id = 0;
@@ -546,6 +546,7 @@ int map_addobject(dumb_ptr<block_list> bl)
*/
int map_delobjectnofree(int id, BL type)
{
+ assert (id < MAX_FLOORITEM);
if (!object[id])
return 0;
@@ -581,6 +582,7 @@ int map_delobjectnofree(int id, BL type)
*/
int map_delobject(int id, BL type)
{
+ assert (id < MAX_FLOORITEM);
dumb_ptr<block_list> obj = object[id];
if (obj == NULL)
@@ -603,6 +605,7 @@ int map_delobject(int id, BL type)
void map_foreachobject(std::function<void(dumb_ptr<block_list>)> func,
BL type)
{
+ assert (last_object_id < MAX_FLOORITEM);
std::vector<dumb_ptr<block_list>> bl_list;
for (int i = 2; i <= last_object_id; i++)
{
@@ -634,6 +637,7 @@ void map_foreachobject(std::function<void(dumb_ptr<block_list>)> func,
*/
void map_clearflooritem_timer(TimerData *tid, tick_t, int id)
{
+ assert (id < MAX_FLOORITEM);
dumb_ptr<block_list> obj = object[id];
assert (obj && obj->bl_type == BL::ITEM);
dumb_ptr<flooritem_data> fitem = obj->is_item();
@@ -1669,48 +1673,49 @@ bool map_confs(XString key, ZString value)
* Map-Server Init and Command-line Arguments [Valaris]
*------------------------------------------------------
*/
-int do_init(int argc, ZString *argv)
+int do_init(Slice<ZString> argv)
{
+ ZString argv0 = argv.pop_front();
runflag &= magic_init0();
bool loaded_config_yet = false;
- for (int i = 1; i < argc; ++i)
+ while (argv)
{
- if (argv[i].startswith('-'))
+ ZString argvi = argv.pop_front();
+ if (argvi.startswith('-'))
{
- if (argv[i] == "--help")
+ if (argvi == "--help")
{
PRINTF("Usage: %s [--help] [--version] [--write_atcommand_config outfile] [files...]\n",
- argv[0]);
+ argv0);
exit(0);
}
- else if (argv[i] == "--version")
+ else if (argvi == "--version")
{
PRINTF("%s\n", CURRENT_VERSION_STRING);
exit(0);
}
- else if (argv[i] == "--write-atcommand-config")
+ else if (argvi == "--write-atcommand-config")
{
- ++i;
- if (i == argc)
+ if (!argv)
{
PRINTF("Missing argument\n");
exit(1);
}
- ZString filename = argv[i];
+ ZString filename = argv.pop_front();
atcommand_config_write(filename);
exit(0);
}
else
{
- FPRINTF(stderr, "Unknown argument: %s\n", argv[i]);
+ FPRINTF(stderr, "Unknown argument: %s\n", argvi);
runflag = false;
}
}
else
{
loaded_config_yet = true;
- runflag &= load_config_file(argv[i], map_confs);
+ runflag &= load_config_file(argvi, map_confs);
}
}
diff --git a/src/map/map.hpp b/src/map/map.hpp
index 0f9f3d1..cb57c6b 100644
--- a/src/map/map.hpp
+++ b/src/map/map.hpp
@@ -113,7 +113,7 @@ public:
struct walkpath_data
{
unsigned char path_len, path_pos, path_half;
- DIR path[MAX_WALKPATH];
+ Array<DIR, MAX_WALKPATH> path;
};
struct status_change
{
@@ -173,7 +173,7 @@ struct map_session_data : block_list, SessionData
unsigned char tmw_version; // tmw client version
CharKey status_key;
CharData status;
- struct item_data *inventory_data[MAX_INVENTORY];
+ Array<struct item_data *, MAX_INVENTORY> inventory_data;
earray<short, EQUIP, EQUIP::COUNT> equip_index;
int weight, max_weight;
MapName mapname_;
@@ -275,8 +275,8 @@ struct map_session_data : block_list, SessionData
short sc_count;
int trade_partner;
- int deal_item_index[10];
- int deal_item_amount[10];
+ Array<int, TRADE_MAX> deal_item_index;
+ Array<int, TRADE_MAX> deal_item_amount;
int deal_zeny;
short deal_locked;
@@ -292,7 +292,7 @@ struct map_session_data : block_list, SessionData
int pvp_lastusers;
std::list<NpcEvent> eventqueuel;
- Timer eventtimer[MAX_EVENTTIMER];
+ Array<Timer, MAX_EVENTTIMER> eventtimer;
struct
{
@@ -349,7 +349,7 @@ struct npc_data : block_list
short flag;
std::list<RString> eventqueuel;
- Timer eventtimer[MAX_EVENTTIMER];
+ Array<Timer, MAX_EVENTTIMER> eventtimer;
short arenaflag;
private:
@@ -517,13 +517,7 @@ struct map_local : map_abstract
MapFlags flag;
struct point save;
struct point resave;
- dumb_ptr<npc_data> npc[MAX_NPC_PER_MAP];
- struct
- {
- int drop_id;
- int drop_type;
- int drop_per;
- } drop_list[MAX_DROP_PER_MAP];
+ Array<dumb_ptr<npc_data>, MAX_NPC_PER_MAP> npc;
};
struct map_remote : map_abstract
@@ -535,6 +529,8 @@ struct map_remote : map_abstract
inline
MapCell read_gatp(map_local *m, int x, int y)
{
+ assert (0 <= x && x < m->xs);
+ assert (0 <= y && y < m->ys);
return m->gat[x + y * m->xs];
}
diff --git a/src/map/mapflag.cpp b/src/map/mapflag.cpp
index 097f4d1..51af30a 100644
--- a/src/map/mapflag.cpp
+++ b/src/map/mapflag.cpp
@@ -40,41 +40,41 @@ bool extract<MapFlag, void, void>(XString str, MapFlag *mf)
{
const struct
{
- char str[32];
+ ZString str;
MapFlag id;
} flags[] =
{
- //{"alias", MapFlag::ALIAS},
- //{"nomemo", MapFlag::NOMEMO},
- {"noteleport", MapFlag::NOTELEPORT},
- {"noreturn", MapFlag::NORETURN},
- {"monster_noteleport", MapFlag::MONSTER_NOTELEPORT},
- {"nosave", MapFlag::NOSAVE},
- //{"nobranch", MapFlag::NOBRANCH},
- {"nopenalty", MapFlag::NOPENALTY},
- {"pvp", MapFlag::PVP},
- {"pvp_noparty", MapFlag::PVP_NOPARTY},
- //{"pvp_noguild", MapFlag::PVP_NOGUILD},
- //{"pvp_nightmaredrop", MapFlag::PVP_NIGHTMAREDROP},
- {"pvp_nocalcrank", MapFlag::PVP_NOCALCRANK},
- //{"gvg", MapFlag::GVG},
- //{"gvg_noparty", MapFlag::GVG_NOPARTY},
- //{"nozenypenalty", MapFlag::NOZENYPENALTY},
- //{"notrade", MapFlag::NOTRADE},
- //{"noskill", MapFlag::NOSKILL},
- {"nowarp", MapFlag::NOWARP},
- {"nowarpto", MapFlag::NOWARPTO},
- {"nopvp", MapFlag::NOPVP},
- //{"noicewall", MapFlag::NOICEWALL},
- {"snow", MapFlag::SNOW},
- {"fog", MapFlag::FOG},
- {"sakura", MapFlag::SAKURA},
- {"leaves", MapFlag::LEAVES},
- {"rain", MapFlag::RAIN},
- {"no_player_drops", MapFlag::NO_PLAYER_DROPS},
- {"town", MapFlag::TOWN},
- {"outside", MapFlag::OUTSIDE},
- {"resave", MapFlag::RESAVE},
+ //{ZString("alias"), MapFlag::ALIAS},
+ //{ZString("nomemo"), MapFlag::NOMEMO},
+ {ZString("noteleport"), MapFlag::NOTELEPORT},
+ {ZString("noreturn"), MapFlag::NORETURN},
+ {ZString("monster_noteleport"), MapFlag::MONSTER_NOTELEPORT},
+ {ZString("nosave"), MapFlag::NOSAVE},
+ //{ZString("nobranch"), MapFlag::NOBRANCH},
+ {ZString("nopenalty"), MapFlag::NOPENALTY},
+ {ZString("pvp"), MapFlag::PVP},
+ {ZString("pvp_noparty"), MapFlag::PVP_NOPARTY},
+ //{ZString("pvp_noguild"), MapFlag::PVP_NOGUILD},
+ //{ZString("pvp_nightmaredrop"), MapFlag::PVP_NIGHTMAREDROP},
+ {ZString("pvp_nocalcrank"), MapFlag::PVP_NOCALCRANK},
+ //{ZString("gvg"), MapFlag::GVG},
+ //{ZString("gvg_noparty"), MapFlag::GVG_NOPARTY},
+ //{ZString("nozenypenalty"), MapFlag::NOZENYPENALTY},
+ //{ZString("notrade"), MapFlag::NOTRADE},
+ //{ZString("noskill"), MapFlag::NOSKILL},
+ {ZString("nowarp"), MapFlag::NOWARP},
+ {ZString("nowarpto"), MapFlag::NOWARPTO},
+ {ZString("nopvp"), MapFlag::NOPVP},
+ //{ZString("noicewall"), MapFlag::NOICEWALL},
+ {ZString("snow"), MapFlag::SNOW},
+ {ZString("fog"), MapFlag::FOG},
+ {ZString("sakura"), MapFlag::SAKURA},
+ {ZString("leaves"), MapFlag::LEAVES},
+ {ZString("rain"), MapFlag::RAIN},
+ {ZString("no_player_drops"), MapFlag::NO_PLAYER_DROPS},
+ {ZString("town"), MapFlag::TOWN},
+ {ZString("outside"), MapFlag::OUTSIDE},
+ {ZString("resave"), MapFlag::RESAVE},
};
for (auto& pair : flags)
if (str == pair.str)
diff --git a/src/map/mob.cpp b/src/map/mob.cpp
index 61dcfb6..c4a4304 100644
--- a/src/map/mob.cpp
+++ b/src/map/mob.cpp
@@ -1305,7 +1305,7 @@ int mob_can_reach(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int range)
int mob_target(dumb_ptr<mob_data> md, dumb_ptr<block_list> bl, int dist)
{
dumb_ptr<map_session_data> sd;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
MobMode mode;
nullpo_ret(md);
@@ -3560,15 +3560,15 @@ bool extract<MobSkillCondition, void, void>(XString str, MobSkillCondition *msc)
{
const struct
{
- char str[32];
+ ZString str;
MobSkillCondition id;
} cond1[] =
{
- {"always", MobSkillCondition::MSC_ALWAYS},
- {"myhpltmaxrate", MobSkillCondition::MSC_MYHPLTMAXRATE},
- {"notintown", MobSkillCondition::MSC_NOTINTOWN},
- {"slavelt", MobSkillCondition::MSC_SLAVELT},
- {"slavele", MobSkillCondition::MSC_SLAVELE},
+ {ZString("always"), MobSkillCondition::MSC_ALWAYS},
+ {ZString("myhpltmaxrate"), MobSkillCondition::MSC_MYHPLTMAXRATE},
+ {ZString("notintown"), MobSkillCondition::MSC_NOTINTOWN},
+ {ZString("slavelt"), MobSkillCondition::MSC_SLAVELT},
+ {ZString("slavele"), MobSkillCondition::MSC_SLAVELE},
};
for (auto& pair : cond1)
if (str == pair.str)
@@ -3584,14 +3584,14 @@ bool extract<MobSkillState, void, void>(XString str, MobSkillState *mss)
{
const struct
{
- char str[32];
+ ZString str;
MobSkillState id;
} state[] =
{
- {"any", MobSkillState::ANY},
- {"idle", MobSkillState::MSS_IDLE},
- {"walk", MobSkillState::MSS_WALK},
- {"attack", MobSkillState::MSS_ATTACK},
+ {ZString("any"), MobSkillState::ANY},
+ {ZString("idle"), MobSkillState::MSS_IDLE},
+ {ZString("walk"), MobSkillState::MSS_WALK},
+ {ZString("attack"), MobSkillState::MSS_ATTACK},
};
for (auto& pair : state)
if (str == pair.str)
@@ -3607,12 +3607,12 @@ bool extract<MobSkillTarget, void, void>(XString str, MobSkillTarget *mst)
{
const struct
{
- char str[32];
+ ZString str;
MobSkillTarget id;
} target[] =
{
- {"target", MobSkillTarget::MST_TARGET},
- {"self", MobSkillTarget::MST_SELF},
+ {ZString("target"), MobSkillTarget::MST_TARGET},
+ {ZString("self"), MobSkillTarget::MST_SELF},
};
for (auto& pair : target)
if (str == pair.str)
diff --git a/src/map/npc.cpp b/src/map/npc.cpp
index dd75691..514c042 100644
--- a/src/map/npc.cpp
+++ b/src/map/npc.cpp
@@ -200,7 +200,7 @@ void npc_timer_event(NpcEvent eventname)
*/
static
void npc_event_doall_sub(NpcEvent key, struct event_data *ev,
- int *c, ScriptLabel name, int rid, int argc, argrec_t *argv)
+ int *c, ScriptLabel name, int rid, Slice<argrec_t> argv)
{
ScriptLabel p = key.label;
@@ -209,45 +209,45 @@ void npc_event_doall_sub(NpcEvent key, struct event_data *ev,
if (name == p)
{
run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id,
- argc, argv);
+ argv);
(*c)++;
}
}
-int npc_event_doall_l(ScriptLabel name, int rid, int argc, argrec_t *args)
+int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> args)
{
int c = 0;
for (auto& pair : ev_db)
- npc_event_doall_sub(pair.first, &pair.second, &c, name, rid, argc, args);
+ npc_event_doall_sub(pair.first, &pair.second, &c, name, rid, args);
return c;
}
static
void npc_event_do_sub(NpcEvent key, struct event_data *ev,
- int *c, NpcEvent name, int rid, int argc, argrec_t *argv)
+ int *c, NpcEvent name, int rid, Slice<argrec_t> argv)
{
nullpo_retv(ev);
if (name == key)
{
run_script_l(ScriptPointer(ev->nd->scr.script.get(), ev->pos), rid, ev->nd->bl_id,
- argc, argv);
+ argv);
(*c)++;
}
}
-int npc_event_do_l(NpcEvent name, int rid, int argc, argrec_t *args)
+int npc_event_do_l(NpcEvent name, int rid, Slice<argrec_t> args)
{
int c = 0;
if (!name.npc)
{
- return npc_event_doall_l(name.label, rid, argc, args);
+ return npc_event_doall_l(name.label, rid, args);
}
for (auto& pair : ev_db)
- npc_event_do_sub(pair.first, &pair.second, &c, name, rid, argc, args);
+ npc_event_do_sub(pair.first, &pair.second, &c, name, rid, args);
return c;
}
diff --git a/src/map/npc.hpp b/src/map/npc.hpp
index 93f2030..8d2dc5b 100644
--- a/src/map/npc.hpp
+++ b/src/map/npc.hpp
@@ -51,17 +51,17 @@ void npc_delsrcfile(XString);
bool do_init_npc(void);
int npc_event_do_oninit(void);
-int npc_event_doall_l(ScriptLabel name, int rid, int argc, struct argrec_t *argv);
-int npc_event_do_l(NpcEvent name, int rid, int argc, struct argrec_t *argv);
+int npc_event_doall_l(ScriptLabel name, int rid, Slice<argrec_t> argv);
+int npc_event_do_l(NpcEvent name, int rid, Slice<argrec_t> argv);
inline
int npc_event_doall(ScriptLabel name)
{
- return npc_event_doall_l(name, 0, 0, NULL);
+ return npc_event_doall_l(name, 0, nullptr);
}
inline
int npc_event_do(NpcEvent name)
{
- return npc_event_do_l(name, 0, 0, NULL);
+ return npc_event_do_l(name, 0, nullptr);
}
void npc_timerevent_start(dumb_ptr<npc_data_script> nd);
diff --git a/src/map/pc.cpp b/src/map/pc.cpp
index 10c2b22..343e0fc 100644
--- a/src/map/pc.cpp
+++ b/src/map/pc.cpp
@@ -589,7 +589,7 @@ static
int pc_isequip(dumb_ptr<map_session_data> sd, int n)
{
struct item_data *item;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
//転生や養子の場合の元の職業を算出する
nullpo_ret(sd);
@@ -1074,7 +1074,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
};
run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
sd->bl_id, 0,
- 2, arg);
+ arg);
}
sd->state.lr_flag = 0;
}
@@ -1091,7 +1091,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
sd->attackrange += sd->inventory_data[index]->range;
run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
sd->bl_id, 0,
- 2, arg);
+ arg);
}
}
else if (sd->inventory_data[index]->type == ItemType::ARMOR)
@@ -1104,7 +1104,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
sd->watk += sd->inventory_data[index]->atk;
run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
sd->bl_id, 0,
- 2, arg);
+ arg);
}
}
}
@@ -1130,7 +1130,7 @@ int pc_calcstatus(dumb_ptr<map_session_data> sd, int first)
sd->state.lr_flag = 2;
run_script_l(ScriptPointer(sd->inventory_data[index]->equip_script.get(), 0),
sd->bl_id, 0,
- 2, arg);
+ arg);
sd->state.lr_flag = 0;
sd->arrow_atk += sd->inventory_data[index]->atk;
}
@@ -2702,7 +2702,7 @@ void pc_attack_timer(TimerData *, tick_t tick, int id)
{
dumb_ptr<map_session_data> sd;
dumb_ptr<block_list> bl;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int dist, range;
sd = map_id2sd(id);
@@ -3514,10 +3514,10 @@ int pc_damage(dumb_ptr<block_list> src, dumb_ptr<map_session_data> sd,
{"@victimrid", sd->bl_id},
{"@victimlvl", sd->status.base_level},
};
- npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"), sd->bl_id, 3, arg);
- npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"), src->bl_id, 3, arg);
+ npc_event_doall_l(stringish<ScriptLabel>("OnPCKilledEvent"), sd->bl_id, arg);
+ npc_event_doall_l(stringish<ScriptLabel>("OnPCKillEvent"), src->bl_id, arg);
}
- npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"), sd->bl_id, 0, NULL);
+ npc_event_doall_l(stringish<ScriptLabel>("OnPCDieEvent"), sd->bl_id, nullptr);
return 0;
}
@@ -4084,6 +4084,7 @@ int pc_readglobalreg(dumb_ptr<map_session_data> sd, VarName reg)
nullpo_ret(sd);
+ assert (sd->status.global_reg_num < GLOBAL_REG_NUM);
for (i = 0; i < sd->status.global_reg_num; i++)
{
if (sd->status.global_reg[i].str == reg)
@@ -4109,6 +4110,7 @@ int pc_setglobalreg(dumb_ptr<map_session_data> sd, VarName reg, int val)
sd->die_counter = val;
pc_calcstatus(sd, 0);
}
+ assert (sd->status.global_reg_num < GLOBAL_REG_NUM);
if (val == 0)
{
for (i = 0; i < sd->status.global_reg_num; i++)
@@ -4155,6 +4157,7 @@ int pc_readaccountreg(dumb_ptr<map_session_data> sd, VarName reg)
nullpo_ret(sd);
+ assert (sd->status.account_reg_num < ACCOUNT_REG_NUM);
for (i = 0; i < sd->status.account_reg_num; i++)
{
if (sd->status.account_reg[i].str == reg)
diff --git a/src/map/script.cpp b/src/map/script.cpp
index cbb6d96..18055b8 100644
--- a/src/map/script.cpp
+++ b/src/map/script.cpp
@@ -78,20 +78,20 @@ Map<ScriptLabel, int> scriptlabel_db;
UPMap<RString, const ScriptBuffer> userfunc_db;
static
-const char *pos_str[11] =
-{
- "Head",
- "Body",
- "Left hand",
- "Right hand",
- "Robe",
- "Shoes",
- "Accessory 1",
- "Accessory 2",
- "Head 2",
- "Head 3",
- "Not Equipped",
-};
+Array<ZString, 11> pos_str //=
+{{
+ ZString("Head"),
+ ZString("Body"),
+ ZString("Left hand"),
+ ZString("Right hand"),
+ ZString("Robe"),
+ ZString("Shoes"),
+ ZString("Accessory 1"),
+ ZString("Accessory 2"),
+ ZString("Head 2"),
+ ZString("Head 3"),
+ ZString("Not Equipped"),
+}};
static
struct Script_Config
@@ -2202,8 +2202,8 @@ void builtin_strcharinfo(ScriptState *st)
// indexed by the equip_* in db/const.txt
// TODO change to use EQUIP
static
-EPOS equip[11] =
-{
+Array<EPOS, 11> equip //=
+{{
EPOS::HAT,
EPOS::MISC1,
EPOS::SHIELD,
@@ -2215,7 +2215,7 @@ EPOS equip[11] =
EPOS::TORSO,
EPOS::LEGS,
EPOS::ARROW,
-};
+}};
/*==========================================
* GetEquipID(Pos); Pos: 1-10
@@ -4693,11 +4693,11 @@ void run_script_main(ScriptState *st, const ScriptBuffer *rootscript)
*/
int run_script(ScriptPointer sp, int rid, int oid)
{
- return run_script_l(sp, rid, oid, 0, NULL);
+ return run_script_l(sp, rid, oid, nullptr);
}
int run_script_l(ScriptPointer sp, int rid, int oid,
- int args_nr, argrec_t *args)
+ Slice<argrec_t> args)
{
struct script_stack stack;
ScriptState st;
@@ -4717,7 +4717,7 @@ int run_script_l(ScriptPointer sp, int rid, int oid,
st.scriptp = sp;
st.rid = rid;
st.oid = oid;
- for (i = 0; i < args_nr; i++)
+ for (i = 0; i < args.size(); i++)
{
if (args[i].name.back() == '$')
pc_setregstr(sd, SIR::from(variable_names.intern(args[i].name)), args[i].v.s);
diff --git a/src/map/script.hpp b/src/map/script.hpp
index 8c072b3..ea087c2 100644
--- a/src/map/script.hpp
+++ b/src/map/script.hpp
@@ -6,6 +6,8 @@
# include <vector>
+# include "../range/slice.hpp"
+
# include "../strings/rstring.hpp"
# include "../strings/astring.hpp"
# include "../strings/zstring.hpp"
@@ -153,7 +155,7 @@ struct argrec_t
argrec_t(ZString n, int i) : name(n), v(i) {}
argrec_t(ZString n, ZString z) : name(n), v(z) {}
};
-int run_script_l(ScriptPointer, int, int, int, argrec_t *args);
+int run_script_l(ScriptPointer, int, int, Slice<argrec_t> args);
int run_script(ScriptPointer, int, int);
struct ScriptLabel;
diff --git a/src/map/skill-pools.cpp b/src/map/skill-pools.cpp
index 31998f8..2ac3a93 100644
--- a/src/map/skill-pools.cpp
+++ b/src/map/skill-pools.cpp
@@ -7,7 +7,7 @@
#include "../poison.hpp"
-SkillID skill_pool_skills[MAX_POOL_SKILLS];
+Array<SkillID, MAX_POOL_SKILLS> skill_pool_skills;
int skill_pool_skills_size = 0;
void skill_pool_register(SkillID id)
diff --git a/src/map/skill.cpp b/src/map/skill.cpp
index 72d7f7a..c29704a 100644
--- a/src/map/skill.cpp
+++ b/src/map/skill.cpp
@@ -232,7 +232,7 @@ int skill_attack(BF attack_type, dumb_ptr<block_list> src,
SkillID skillid, int skilllv, tick_t tick, BCT flag)
{
struct Damage dmg;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int type, lv, damage;
nullpo_ret(src);
@@ -550,7 +550,7 @@ int skill_castend_nodamage_id(dumb_ptr<block_list> src, dumb_ptr<block_list> bl,
interval_t skill_castfix(dumb_ptr<block_list> bl, interval_t interval)
{
dumb_ptr<mob_data> md; // [Valaris]
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int dex;
int castrate = 100;
SkillID skill;
@@ -601,7 +601,7 @@ interval_t skill_castfix(dumb_ptr<block_list> bl, interval_t interval)
*/
interval_t skill_delayfix(dumb_ptr<block_list> bl, interval_t interval)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_retr(interval_t::zero(), bl);
@@ -663,7 +663,7 @@ int skill_castcancel(dumb_ptr<block_list> bl, int)
*/
int skill_status_change_active(dumb_ptr<block_list> bl, StatusChange type)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
nullpo_ret(bl);
if (bl->bl_type != BL::PC && bl->bl_type != BL::MOB)
@@ -682,7 +682,7 @@ int skill_status_change_active(dumb_ptr<block_list> bl, StatusChange type)
void skill_status_change_end(dumb_ptr<block_list> bl, StatusChange type, TimerData *tid)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
int opt_flag = 0, calc_flag = 0;
short *sc_count;
Option *option;
@@ -806,7 +806,7 @@ void skill_status_change_timer(TimerData *tid, tick_t tick, int id, StatusChange
{
dumb_ptr<block_list> bl;
dumb_ptr<map_session_data> sd = NULL;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
//short *sc_count; //使ってない?
if ((bl = map_id2bl(id)) == NULL)
@@ -907,7 +907,7 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type,
interval_t tick, int spell_invocation)
{
dumb_ptr<map_session_data> sd = NULL;
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
short *sc_count;
Option *option;
Opt1 *opt1;
@@ -1081,7 +1081,7 @@ int skill_status_effect(dumb_ptr<block_list> bl, StatusChange type,
*/
int skill_status_change_clear(dumb_ptr<block_list> bl, int type)
{
- eptr<struct status_change, StatusChange> sc_data;
+ eptr<struct status_change, StatusChange, StatusChange::MAX_STATUSCHANGE> sc_data;
short *sc_count;
Option *option;
Opt1 *opt1;
diff --git a/src/map/skill.hpp b/src/map/skill.hpp
index b612268..ece2ab5 100644
--- a/src/map/skill.hpp
+++ b/src/map/skill.hpp
@@ -22,17 +22,16 @@ struct skill_db_
SkillFlags poolflags;
int max_raise; // `max' is the global max, `max_raise' is the maximum attainable via skill-ups
int num_k;
- int cast[MAX_SKILL_LEVEL], delay[MAX_SKILL_LEVEL];
- int upkeep_time[MAX_SKILL_LEVEL], upkeep_time2[MAX_SKILL_LEVEL];
+ Array<int, MAX_SKILL_LEVEL> cast, delay;
+ Array<int, MAX_SKILL_LEVEL> upkeep_time, upkeep_time2;
bool castcancel;
int cast_def_rate;
int inf2, maxcount;
- int hp[MAX_SKILL_LEVEL], sp[MAX_SKILL_LEVEL], mhp[MAX_SKILL_LEVEL],
- hp_rate[MAX_SKILL_LEVEL], sp_rate[MAX_SKILL_LEVEL],
- zeny[MAX_SKILL_LEVEL];
+ Array<int, MAX_SKILL_LEVEL> hp, sp, mhp,
+ hprate, sp_rate,
+ zeny;
int weapon;
- int itemid[10], amount[10];
- int castnodex[MAX_SKILL_LEVEL];
+ Array<int, MAX_SKILL_LEVEL> castnodex;
};
extern
earray<skill_db_, SkillID, SkillID::MAX_SKILL_DB> skill_db;
@@ -115,7 +114,7 @@ constexpr int MAX_SKILL_POOL = 3;
// Max. # of skills that may be classified as pool skills in db/skill_db.txt
constexpr int MAX_POOL_SKILLS = 128;
-extern SkillID skill_pool_skills[MAX_POOL_SKILLS]; // All pool skills
+extern Array<SkillID, MAX_POOL_SKILLS> skill_pool_skills; // All pool skills
extern int skill_pool_skills_size; // Number of entries in skill_pool_skills
// Yields all active skills in the skill pool; no more than MAX_SKILL_POOL. Return is number of skills.
diff --git a/src/map/tmw.hpp b/src/map/tmw.hpp
index 65e71fb..65eb28a 100644
--- a/src/map/tmw.hpp
+++ b/src/map/tmw.hpp
@@ -3,8 +3,6 @@
# include "../strings/fwd.hpp"
-# include "../generic/const_array.hpp"
-
# include "../mmo/dumb_ptr.hpp"
# include "map.hpp"
diff --git a/src/map/trade.cpp b/src/map/trade.cpp
index e9c5fd4..bd6e2bf 100644
--- a/src/map/trade.cpp
+++ b/src/map/trade.cpp
@@ -137,7 +137,7 @@ void trade_tradeadditem(dumb_ptr<map_session_data> sd, int index, int amount)
&& target_sd->inventory_data[i] == NULL)
free_++;
}
- for (trade_i = 0; trade_i < 10; trade_i++)
+ for (trade_i = 0; trade_i < TRADE_MAX; trade_i++)
{
if (sd->deal_item_amount[trade_i] == 0)
{
@@ -238,7 +238,7 @@ void trade_tradeok(dumb_ptr<map_session_data> sd)
nullpo_retv(sd);
- for (trade_i = 0; trade_i < 10; trade_i++)
+ for (trade_i = 0; trade_i < TRADE_MAX; trade_i++)
{
if (sd->deal_item_amount[trade_i] >
sd->status.inventory[sd->deal_item_index[trade_i] - 2].amount
@@ -272,7 +272,7 @@ void trade_tradecancel(dumb_ptr<map_session_data> sd)
if ((target_sd = map_id2sd(sd->trade_partner)) != NULL)
{
- for (trade_i = 0; trade_i < 10; trade_i++)
+ for (trade_i = 0; trade_i < TRADE_MAX; trade_i++)
{ //give items back (only virtual)
if (sd->deal_item_amount[trade_i] != 0)
{
@@ -352,7 +352,7 @@ void trade_tradecommit(dumb_ptr<map_session_data> sd)
}
sd->trade_partner = 0;
target_sd->trade_partner = 0;
- for (trade_i = 0; trade_i < 10; trade_i++)
+ for (trade_i = 0; trade_i < TRADE_MAX; trade_i++)
{
if (sd->deal_item_amount[trade_i] != 0)
{
diff --git a/src/mmo/core.cpp b/src/mmo/core.cpp
index 1a9a52e..26b5128 100644
--- a/src/mmo/core.cpp
+++ b/src/mmo/core.cpp
@@ -83,7 +83,7 @@ int main(int argc, char **argv)
ZString *args = static_cast<ZString *>(alloca(argc * sizeof(ZString)));
for (int i = 0; i < argc; ++i)
args[i] = ZString(strings::really_construct_from_a_pointer, argv[i], nullptr);
- do_init(argc, args);
+ do_init(Slice<ZString>(args, argc));
if (!runflag)
{
diff --git a/src/mmo/core.hpp b/src/mmo/core.hpp
index 1788ece..7a26f7d 100644
--- a/src/mmo/core.hpp
+++ b/src/mmo/core.hpp
@@ -3,6 +3,8 @@
# include "../sanity.hpp"
+# include "../range/slice.hpp"
+
# include "../strings/fwd.hpp"
/// core.c contains a server-independent main() function
@@ -13,7 +15,7 @@ extern volatile bool runflag;
/// This is an external function defined by each server
/// This function must register stuff for the parse loop
-extern int do_init(int, ZString *);
+extern int do_init(Slice<ZString>);
/// Cleanup function called whenever a signal kills us
/// or when if we manage to exit() gracefully.
diff --git a/src/mmo/dumb_ptr.hpp b/src/mmo/dumb_ptr.hpp
index 98c6308..9632945 100644
--- a/src/mmo/dumb_ptr.hpp
+++ b/src/mmo/dumb_ptr.hpp
@@ -29,8 +29,6 @@
# include "../strings/zstring.hpp"
# include "../strings/xstring.hpp"
-# include "../generic/const_array.hpp"
-
// unmanaged new/delete-able pointer
// should be replaced by std::unique_ptr<T>
template<class T>
diff --git a/src/mmo/extract.hpp b/src/mmo/extract.hpp
index 0ea9eb9..622281b 100644
--- a/src/mmo/extract.hpp
+++ b/src/mmo/extract.hpp
@@ -25,8 +25,6 @@
# include "../strings/xstring.hpp"
-# include "../generic/const_array.hpp"
-
# include "mmo.hpp"
# include "utils.hpp"
diff --git a/src/mmo/mmo.hpp b/src/mmo/mmo.hpp
index 6b3cd53..f867492 100644
--- a/src/mmo/mmo.hpp
+++ b/src/mmo/mmo.hpp
@@ -21,6 +21,7 @@ constexpr int MAX_MAP_PER_SERVER = 512;
constexpr int MAX_INVENTORY = 100;
constexpr int MAX_AMOUNT = 30000;
constexpr int MAX_ZENY = 1000000000; // 1G zeny
+constexpr int TRADE_MAX = 10;
enum class SkillID : uint16_t;
constexpr SkillID MAX_SKILL = SkillID(474); // not 450
@@ -43,6 +44,20 @@ constexpr int MAX_PARTY = 12;
# define MIN_CLOTH_COLOR battle_config.min_cloth_color
# define MAX_CLOTH_COLOR battle_config.max_cloth_color
+template<class T, size_t n>
+struct Array
+{
+ T data[n];
+public:
+ T& operator [](size_t i) { assert (i < n); return data[i]; }
+ const T& operator [](size_t i) const { assert (i < n); return data[i]; }
+
+ T *begin() { return data + 0; }
+ T *end() { return data + n; }
+ const T *begin() const { return data + 0; }
+ const T *end() const { return data + n; }
+};
+
struct AccountName : VString<23> {};
struct AccountPass : VString<23> {};
struct AccountCrypt : VString<39> {};
@@ -319,14 +334,14 @@ struct CharData
unsigned int mapport;
struct point last_point, save_point;
- struct item inventory[MAX_INVENTORY];
+ Array<struct item, MAX_INVENTORY> inventory;
earray<skill_value, SkillID, MAX_SKILL> skill;
int global_reg_num;
- struct global_reg global_reg[GLOBAL_REG_NUM];
+ Array<struct global_reg, GLOBAL_REG_NUM> global_reg;
int account_reg_num;
- struct global_reg account_reg[ACCOUNT_REG_NUM];
+ Array<struct global_reg, ACCOUNT_REG_NUM> account_reg;
int account_reg2_num;
- struct global_reg account_reg2[ACCOUNT_REG2_NUM];
+ Array<struct global_reg, ACCOUNT_REG2_NUM> account_reg2;
};
struct CharPair
@@ -345,11 +360,9 @@ struct storage
int account_id;
short storage_status;
short storage_amount;
- struct item storage_[MAX_STORAGE];
+ Array<struct item, MAX_STORAGE> storage_;
};
-//struct map_session_data;
-
struct GM_Account
{
int account_id;
@@ -371,7 +384,7 @@ struct party
PartyName name;
int exp;
int item;
- struct party_member member[MAX_PARTY];
+ Array<struct party_member, MAX_PARTY> member;
};
#endif // TMWA_MMO_MMO_HPP
diff --git a/src/mmo/utils.hpp b/src/mmo/utils.hpp
index 5e9de26..40ff595 100644
--- a/src/mmo/utils.hpp
+++ b/src/mmo/utils.hpp
@@ -10,7 +10,6 @@
# include "../strings/fwd.hpp"
# include "../strings/vstring.hpp"
-# include "../generic/const_array.hpp"
# include "../generic/operators.hpp"
# include "../io/fwd.hpp"
diff --git a/src/range/slice.cpp b/src/range/slice.cpp
new file mode 100644
index 0000000..5b23447
--- /dev/null
+++ b/src/range/slice.cpp
@@ -0,0 +1 @@
+#include "slice.hpp"
diff --git a/src/range/slice.hpp b/src/range/slice.hpp
new file mode 100644
index 0000000..f645595
--- /dev/null
+++ b/src/range/slice.hpp
@@ -0,0 +1,74 @@
+#ifndef TMWA_GENERIC_SLICE_HPP
+#define TMWA_GENERIC_SLICE_HPP
+// slice.hpp - a borrowed array
+//
+// Copyright © 2011-2014 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+# include "../sanity.hpp"
+
+# include <cstddef>
+
+# include <type_traits>
+
+# include <vector>
+
+template<class T>
+class Slice
+{
+ T *_begin;
+ T *_end;
+public:
+ class iterator;
+
+ Slice(std::nullptr_t);
+ Slice(T *b, T *e);
+ Slice(T *b, size_t l);
+ template<class U, typename=typename std::enable_if<sizeof(T) == sizeof(U) && std::is_base_of<T, U>::value>::type>
+ Slice(Slice<U> o);
+ template<size_t n, typename=typename std::enable_if<sizeof(T) != 1>::type>
+ Slice(T (&arr)[n]);
+ // TODO: come up with something else once using ranges (wrap all containers?)
+ Slice(std::vector<T>& vec);
+
+ iterator begin() const;
+ iterator end() const;
+ T *data() const;
+ size_t size() const;
+ operator bool() const;
+ bool operator not() const;
+ T& front() const;
+ T& back() const;
+ T& pop_front();
+ T& pop_back();
+ __attribute__((deprecated("use iterators instead")))
+ T& operator[](size_t o);
+
+ Slice slice_t(size_t o) const;
+ Slice slice_h(size_t o) const;
+ Slice rslice_t(size_t no) const;
+ Slice rslice_h(size_t no) const;
+ Slice islice_t(iterator it) const;
+ Slice islice_h(iterator it) const;
+ Slice lslice(size_t o, size_t l) const;
+ Slice pslice(size_t b, size_t e) const;
+ Slice islice(iterator b, iterator e) const;
+};
+
+# include "slice.tcc"
+
+#endif // TMWA_GENERIC_SLICE_HPP
diff --git a/src/range/slice.tcc b/src/range/slice.tcc
new file mode 100644
index 0000000..3a1ceb5
--- /dev/null
+++ b/src/range/slice.tcc
@@ -0,0 +1,216 @@
+// strings/base.tcc - Inline functions for strings/base.hpp
+//
+// Copyright © 2013 Ben Longbons <b.r.longbons@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include <cassert>
+
+#include <algorithm>
+
+// simple pointer-wrapping iterator
+template<class T>
+class Slice<T>::iterator
+{
+ typedef iterator X;
+
+ T *_ptr;
+public:
+ typedef ptrdiff_t difference_type;
+ typedef T value_type;
+ typedef T *pointer;
+ typedef T& reference;
+ typedef std::random_access_iterator_tag iterator_category;
+
+ iterator(T *p=nullptr) : _ptr(p) {}
+
+ // iterator
+ reference operator *() const { return *_ptr; }
+ X& operator ++() { ++_ptr; return *this; }
+ // equality comparable
+ friend bool operator == (X l, X r) { return l._ptr == r._ptr; }
+ // input iterator
+ friend bool operator != (X l, X r) { return !(l == r); }
+ pointer operator->() const { return _ptr; }
+ X operator++ (int) { X out = *this; ++*this; return out; }
+ // forward iterator is mostly semantical, and the ctor is above
+ // bidirectional iterator
+ X& operator --() { --_ptr; return *this; }
+ X operator-- (int) { X out = *this; --*this; return out; }
+ // random access iterator
+ X& operator += (difference_type n) { _ptr += n; return *this; }
+ friend X operator + (X a, difference_type n) { return a += n; }
+ friend X operator + (difference_type n, X a) { return a += n; }
+ X& operator -= (difference_type n) { _ptr -= n; return *this; }
+ friend X operator - (X a, difference_type n) { return a -= n; }
+ friend difference_type operator - (X b, X a) { return b._ptr - a._ptr; }
+ reference operator[](difference_type n) const { return _ptr[n]; }
+ friend bool operator < (X a, X b) { return a._ptr < b._ptr; }
+ friend bool operator > (X a, X b) { return b < a; }
+ friend bool operator >= (X a, X b) { return !(a < b); }
+ friend bool operator <= (X a, X b) { return !(a > b); }
+};
+
+template<class T>
+Slice<T>::Slice(std::nullptr_t) : _begin(nullptr), _end(nullptr)
+{}
+
+template<class T>
+Slice<T>::Slice(T *b, T *e) : _begin(b), _end(e)
+{}
+
+template<class T>
+Slice<T>::Slice(T *b, size_t l) : _begin(b), _end(b + l)
+{}
+
+template<class T>
+template<class U, typename>
+Slice<T>::Slice(Slice<U> o) : _begin(o.data()), _end(o.data() + o.size())
+{}
+
+template<class T>
+template<size_t n, typename>
+Slice<T>::Slice(T (&arr)[n]) : _begin(arr), _end(arr + n)
+{}
+
+template<class T>
+Slice<T>::Slice(std::vector<T>& vec) : _begin(&*vec.begin()), _end(&*vec.end())
+{}
+
+
+template<class T>
+typename Slice<T>::iterator Slice<T>::begin() const
+{
+ return _begin;
+}
+
+template<class T>
+typename Slice<T>::iterator Slice<T>::end() const
+{
+ return _end;
+}
+
+template<class T>
+T *Slice<T>::data() const
+{
+ return _begin;
+}
+
+template<class T>
+size_t Slice<T>::size() const
+{
+ return _end - _begin;
+}
+
+template<class T>
+Slice<T>::operator bool() const
+{
+ return _begin != _end;
+}
+
+template<class T>
+bool Slice<T>::operator not() const
+{
+ return _begin == _end;
+}
+
+template<class T>
+T& Slice<T>::front() const
+{
+ return _begin[0];
+}
+
+template<class T>
+T& Slice<T>::back() const
+{
+ return _end[-1];
+}
+
+template<class T>
+T& Slice<T>::pop_front()
+{
+ ++_begin;
+ return _begin[0 - 1];
+}
+
+template<class T>
+T& Slice<T>::pop_back()
+{
+ --_end;
+ return _end[-1 + 1];
+}
+
+template<class T>
+T& Slice<T>::operator[](size_t o)
+{
+ assert (o < size());
+ return _begin[o];
+}
+
+
+template<class T>
+Slice<T> Slice<T>::slice_t(size_t o) const
+{
+ return Slice(_begin + o, _end);
+}
+
+template<class T>
+Slice<T> Slice<T>::slice_h(size_t o) const
+{
+ return Slice(_begin, _begin + o);
+}
+
+template<class T>
+Slice<T> Slice<T>::rslice_t(size_t no) const
+{
+ return Slice(_end - no, _end);
+}
+
+template<class T>
+Slice<T> Slice<T>::rslice_h(size_t no) const
+{
+ return Slice(_begin, _end - no);
+}
+
+template<class T>
+Slice<T> Slice<T>::islice_t(iterator it) const
+{
+ return Slice(&*it, _end);
+}
+
+template<class T>
+Slice<T> Slice<T>::islice_h(iterator it) const
+{
+ return Slice(_begin, &*it);
+}
+
+template<class T>
+Slice<T> Slice<T>::lslice(size_t o, size_t l) const
+{
+ return Slice(_begin + o, _begin + o + l);
+}
+
+template<class T>
+Slice<T> Slice<T>::pslice(size_t b, size_t e) const
+{
+ return Slice(_begin + b, _begin + e);
+}
+
+template<class T>
+Slice<T> Slice<T>::islice(iterator b, iterator e) const
+{
+ return Slice(&*b, &*e);
+}
diff --git a/src/range/slice_test.cpp b/src/range/slice_test.cpp
new file mode 100644
index 0000000..5bd2748
--- /dev/null
+++ b/src/range/slice_test.cpp
@@ -0,0 +1,89 @@
+#include "slice.hpp"
+
+#include <gtest/gtest.h>
+
+TEST(slice, slice)
+{
+ int init[] = {1, 2, 3, 4, 5};
+
+ Slice<int> slice(std::begin(init), std::end(init));
+ EXPECT_EQ(slice.data(), init);
+ EXPECT_EQ(slice.size(), 5);
+
+ Slice<int> head = slice.slice_h(2);
+ Slice<int> tail = slice.slice_t(2);
+ EXPECT_EQ(head.size(), 2);
+ EXPECT_EQ(tail.size(), 3);
+ EXPECT_EQ(head.front(), 1);
+ EXPECT_EQ(head.back(), 2);
+ EXPECT_EQ(tail.front(), 3);
+ EXPECT_EQ(tail.back(), 5);
+
+ head = slice.rslice_h(3);
+ tail = slice.rslice_t(3);
+ EXPECT_EQ(head.size(), 2);
+ EXPECT_EQ(tail.size(), 3);
+ EXPECT_EQ(head.front(), 1);
+ EXPECT_EQ(head.back(), 2);
+ EXPECT_EQ(tail.front(), 3);
+ EXPECT_EQ(tail.back(), 5);
+
+ head = slice.islice_h(slice.begin() + 2);
+ tail = slice.islice_t(slice.end() - 3);
+ EXPECT_EQ(head.size(), 2);
+ EXPECT_EQ(tail.size(), 3);
+ EXPECT_EQ(head.front(), 1);
+ EXPECT_EQ(head.back(), 2);
+ EXPECT_EQ(tail.front(), 3);
+ EXPECT_EQ(tail.back(), 5);
+
+ tail = slice.lslice(1, 3);
+ EXPECT_EQ(tail.size(), 3);
+ EXPECT_EQ(tail.front(), 2);
+ EXPECT_EQ(tail.back(), 4);
+
+ tail = slice.pslice(1, 4);
+ EXPECT_EQ(tail.size(), 3);
+ EXPECT_EQ(tail.front(), 2);
+ EXPECT_EQ(tail.back(), 4);
+
+ tail = slice.islice(slice.begin() + 1, slice.end() - 1);
+ EXPECT_EQ(tail.size(), 3);
+ EXPECT_EQ(tail.front(), 2);
+ EXPECT_EQ(tail.back(), 4);
+
+ head = slice;
+ while (head)
+ {
+ size_t headsize = head.size();
+ EXPECT_EQ(head.back(), headsize);
+ EXPECT_EQ(head.pop_back(), headsize);
+ }
+
+ tail = slice;
+ while (!!tail)
+ {
+ size_t tailsize = tail.size();
+ EXPECT_EQ(tail.front(), 6 - tailsize);
+ EXPECT_EQ(tail.pop_front(), 6 - tailsize);
+ }
+}
+
+TEST(slice, cast)
+{
+ struct Foo
+ {
+ int x;
+ };
+ struct Bar : Foo
+ {
+ };
+
+ Bar bars[2] = {Bar(), Bar()};
+
+ Slice<Bar> slice(bars, 2);
+ Slice<Foo> foos(slice);
+
+ EXPECT_EQ(foos.size(), slice.size());
+ EXPECT_EQ(&foos.end()[-1], &slice.end()[-1]);
+}
diff --git a/src/strings/base.hpp b/src/strings/base.hpp
index cd8d46f..c5181da 100644
--- a/src/strings/base.hpp
+++ b/src/strings/base.hpp
@@ -31,6 +31,8 @@
// than would probably be necessary in an ideal language.
namespace strings
{
+ // TODO reimplement some things in terms of Slice and Slice::iterator?
+
// simple pointer-wrapping iterator that can be used to get distinct
// types for different containers.
template<class Tag>
diff --git a/src/strings/pair.hpp b/src/strings/pair.hpp
index a519ddb..a592a91 100644
--- a/src/strings/pair.hpp
+++ b/src/strings/pair.hpp
@@ -28,9 +28,7 @@
namespace strings
{
// TODO instead typedef ranges::Contiguous<const char>
- // or whatever it becomes once it exists.
- // const_array is just a hack, as evidenced by the fact
- // that it's not really const.
+ // or whatever it becomes once it exists (probably grown from Slice).
class XPair
{
const char *_begin;