From 8b5370313dcc00a45ea5c3e8b4c497bc00fd8e13 Mon Sep 17 00:00:00 2001 From: Ben Longbons Date: Tue, 11 Jun 2013 21:55:13 -0700 Subject: Allegedly remove all manual memory management --- src/common/const_array.hpp | 38 +++++---- src/common/core.cpp | 12 +++ src/common/db.hpp | 69 ++++++++++++++-- src/common/dumb_ptr.hpp | 199 +++++++++++++++++++++++++++++++++++++++++++++ src/common/intern-pool.hpp | 35 ++++++++ src/common/matrix.hpp | 50 ++++++++++++ src/common/md5calc.cpp | 4 +- src/common/mmo.hpp | 2 +- src/common/socket.cpp | 51 ++++++++++-- src/common/utils.cpp | 2 +- src/common/utils.hpp | 34 -------- src/common/utils2.hpp | 12 +-- 12 files changed, 435 insertions(+), 73 deletions(-) create mode 100644 src/common/intern-pool.hpp create mode 100644 src/common/matrix.hpp (limited to 'src/common') diff --git a/src/common/const_array.hpp b/src/common/const_array.hpp index 93ae337..06045dc 100644 --- a/src/common/const_array.hpp +++ b/src/common/const_array.hpp @@ -70,55 +70,59 @@ public: // but disallow conversion from a temporary const_array(std::vector&&) = delete; - // All methods are non-const to "encourage" you - // to always pass a const_array by value. - // After all, "const const_array" looks funny. + // Oops. see src/warnings.hpp constexpr - const T *data() { return d; } + const T *data() const { return d; } constexpr - size_t size() { return n; } + size_t size() const { return n; } constexpr - bool empty() { return not n; } + bool empty() const { return not n; } constexpr explicit - operator bool() { return n; } + operator bool() const { return n; } constexpr - std::pair cut(size_t o) + std::pair cut(size_t o) const { return {const_array(d, o), const_array(d + o, n - o)}; } constexpr - const_array first(size_t o) + const_array first(size_t o) const { return cut(o).first; } constexpr - const_array last(size_t l) + const_array last(size_t l) const { return cut(size() - l).second; } constexpr - const_array after(size_t o) + const_array after(size_t o) const { return cut(o).second; } constexpr - iterator begin() { return d; } + iterator begin() const { return d; } constexpr - iterator end() { return d + n; } + iterator end() const { return d + n; } constexpr - reverse_iterator rbegin() { return reverse_iterator(end()); } + reverse_iterator rbegin() const { return reverse_iterator(end()); } constexpr - reverse_iterator rend() { return reverse_iterator(begin()); } + reverse_iterator rend() const { return reverse_iterator(begin()); } constexpr - const T& front() { return *begin(); } + const T& front() const { return *begin(); } constexpr - const T& back() { return *rbegin(); } + 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(d[i]); + } }; // subclass just provides a simpler name and some conversions diff --git a/src/common/core.cpp b/src/common/core.cpp index 994de93..153414d 100644 --- a/src/common/core.cpp +++ b/src/common/core.cpp @@ -36,7 +36,10 @@ sigfunc compat_signal(int signo, sigfunc func) sact.sa_flags = 0; if (sigaction(signo, &sact, &oact) < 0) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" return SIG_ERR; +#pragma GCC diagnostic pop return oact.sa_handler; } @@ -50,7 +53,10 @@ static __attribute__((noreturn)) void sig_proc(int) { for (int i = 1; i < 31; ++i) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" compat_signal(i, SIG_IGN); +#pragma GCC diagnostic pop term_func(); _exit(0); } @@ -74,17 +80,23 @@ int main(int argc, char **argv) // set up exit handlers *after* the initialization has happened. // This is because term_func is likely to depend on successful init. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" compat_signal(SIGPIPE, SIG_IGN); +#pragma GCC diagnostic pop compat_signal(SIGTERM, sig_proc); compat_signal(SIGINT, sig_proc); compat_signal(SIGCHLD, chld_proc); // Signal to create coredumps by system when necessary (crash) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" compat_signal(SIGSEGV, SIG_DFL); compat_signal(SIGBUS, SIG_DFL); compat_signal(SIGTRAP, SIG_DFL); compat_signal(SIGILL, SIG_DFL); compat_signal(SIGFPE, SIG_DFL); +#pragma GCC diagnostic pop atexit(term_func); diff --git a/src/common/db.hpp b/src/common/db.hpp index bd47928..927db22 100644 --- a/src/common/db.hpp +++ b/src/common/db.hpp @@ -22,6 +22,7 @@ # include "sanity.hpp" # include +# include template class Map @@ -56,7 +57,7 @@ public: return nullptr; return &it->second; } - void insert(K k, V v) + void insert(const K& k, V v) { // As far as I can tell, this is the simplest way to // implement move-only insert-with-replacement. @@ -69,7 +70,7 @@ public: return (void)&it->second; } - V *init(K k) + V *init(const K& k) { return &impl[k]; } @@ -81,10 +82,14 @@ public: { impl.clear(); } - bool empty() + bool empty() const { return impl.empty(); } + size_t size() const + { + return impl.size(); + } }; template @@ -102,22 +107,74 @@ public: const_iterator begin() const { return impl.begin(); } const_iterator end() const { return impl.end(); } - V get(K k) + // const V& ? with a static default V? + V get(const K& k) { V *vp = impl.search(k); return vp ? *vp : V(); } - void put(K k, V v) + void put(const K& k, V v) { if (v == V()) impl.erase(k); else - impl.insert(k, v); + impl.insert(k, std::move(v)); } void clear() { impl.clear(); } + bool empty() const + { + return impl.empty(); + } + size_t size() const + { + return impl.size(); + } +}; + +template +class UPMap +{ + typedef std::unique_ptr U; + typedef Map Impl; + + Impl impl; +public: + typedef typename Impl::iterator iterator; + typedef typename Impl::const_iterator const_iterator; + + iterator begin() { return impl.begin(); } + iterator end() { return impl.end(); } + const_iterator begin() const { return impl.begin(); } + const_iterator end() const { return impl.end(); } + + // const V& ? with a static default V? + V *get(const K& k) + { + U *up = impl.search(k); + return up ? up->get() : nullptr; + } + void put(const K& k, U v) + { + if (!v) + impl.erase(k); + else + impl.insert(k, std::move(v)); + } + void clear() + { + impl.clear(); + } + bool empty() const + { + return impl.empty(); + } + size_t size() const + { + return impl.size(); + } }; #endif // DB_HPP diff --git a/src/common/dumb_ptr.hpp b/src/common/dumb_ptr.hpp index 1a0b4a1..e10ca3a 100644 --- a/src/common/dumb_ptr.hpp +++ b/src/common/dumb_ptr.hpp @@ -21,8 +21,12 @@ #include "sanity.hpp" +#include + #include +#include "const_array.hpp" + // unmanaged new/delete-able pointer // should be replaced by std::unique_ptr template @@ -176,4 +180,199 @@ public: } }; +struct dumb_string +{ + dumb_ptr impl; + + dumb_string() + : impl() + {} + dumb_string(char *) = delete; + // copy ctor, copy assign, and dtor are all default + + static dumb_string copy(const char *b, const char *e) + { + dumb_string rv; + rv.impl.new_((e - b) + 1); + std::copy(b, e, &rv.impl[0]); + return rv; + } + static dumb_string copy(const char *sz) + { + return dumb_string::copy(sz, sz + strlen(sz)); + } + static dumb_string copys(const std::string& s) + { + return dumb_string::copy(&*s.begin(), &*s.end()); + } + static dumb_string copyn(const char *sn, size_t n) + { + return dumb_string::copy(sn, sn + strnlen(sn, n)); + } + static dumb_string copyc(const_string s) + { + return dumb_string::copy(s.begin(), s.end()); + } + + static + dumb_string fake(const char *p) + { + dumb_string rv; + rv.impl = dumb_ptr(const_cast(p), strlen(p)); + return rv; + } + + dumb_string dup() const + { + return dumb_string::copy(&impl[0]); + } + void delete_() + { + impl.delete_(); + } + + const char *c_str() const + { + return &impl[0]; + } + + std::string str() const + { + return c_str(); + } + + operator const_string() const + { + return const_string(c_str()); + } + + char& operator[](size_t i) const + { + return impl[i]; + } + + explicit + operator bool() const + { + return bool(impl); + } + bool operator !() const + { + return !impl; + } + +#if 0 + friend bool operator == (dumb_string l, dumb_string r) + { + return l.impl == r.impl; + } + friend bool operator != (dumb_string l, dumb_string r) + { + return !(l == r); + } +#endif +}; + +namespace operators +{ + inline + bool operator == (dumb_string l, dumb_string r) + { + return strcmp(l.c_str(), r.c_str()) == 0; + } + inline + bool operator != (dumb_string l, dumb_string r) + { + return strcmp(l.c_str(), r.c_str()) != 0; + } + inline + bool operator < (dumb_string l, dumb_string r) + { + return strcmp(l.c_str(), r.c_str()) < 0; + } + inline + bool operator <= (dumb_string l, dumb_string r) + { + return strcmp(l.c_str(), r.c_str()) <= 0; + } + inline + bool operator > (dumb_string l, dumb_string r) + { + return strcmp(l.c_str(), r.c_str()) > 0; + } + inline + bool operator >= (dumb_string l, dumb_string r) + { + return strcmp(l.c_str(), r.c_str()) >= 0; + } + + inline + bool operator == (const char *l, dumb_string r) + { + return strcmp(l, r.c_str()) == 0; + } + inline + bool operator != (const char *l, dumb_string r) + { + return strcmp(l, r.c_str()) != 0; + } + inline + bool operator < (const char *l, dumb_string r) + { + return strcmp(l, r.c_str()) < 0; + } + inline + bool operator <= (const char *l, dumb_string r) + { + return strcmp(l, r.c_str()) <= 0; + } + inline + bool operator > (const char *l, dumb_string r) + { + return strcmp(l, r.c_str()) > 0; + } + inline + bool operator >= (const char *l, dumb_string r) + { + return strcmp(l, r.c_str()) >= 0; + } + + inline + bool operator == (dumb_string l, const char *r) + { + return strcmp(l.c_str(), r) == 0; + } + inline + bool operator != (dumb_string l, const char *r) + { + return strcmp(l.c_str(), r) != 0; + } + inline + bool operator < (dumb_string l, const char *r) + { + return strcmp(l.c_str(), r) < 0; + } + inline + bool operator <= (dumb_string l, const char *r) + { + return strcmp(l.c_str(), r) <= 0; + } + inline + bool operator > (dumb_string l, const char *r) + { + return strcmp(l.c_str(), r) > 0; + } + inline + bool operator >= (dumb_string l, const char *r) + { + return strcmp(l.c_str(), r) >= 0; + } +} + +inline +const char *convert_for_printf(dumb_string ds) +{ + return ds.c_str(); +} + #endif // TMWA_COMMON_DUMB_PTR_HPP diff --git a/src/common/intern-pool.hpp b/src/common/intern-pool.hpp new file mode 100644 index 0000000..caa54e4 --- /dev/null +++ b/src/common/intern-pool.hpp @@ -0,0 +1,35 @@ +#ifndef INTERN_POOL_HPP +#define INTERN_POOL_HPP + +#include + +#include +#include +#include + +class InternPool +{ + std::map known; + std::vector names; +public: + size_t intern(const std::string& name) + { + auto pair = known.insert({name, known.size()}); + if (pair.second) + names.push_back(name); + assert (known.size() == names.size()); + return pair.first->second; + } + + const std::string& outtern(size_t sz) const + { + return names[sz]; + } + + size_t size() const + { + return known.size(); + } +}; + +#endif //INTERN_POOL_HPP diff --git a/src/common/matrix.hpp b/src/common/matrix.hpp new file mode 100644 index 0000000..8595191 --- /dev/null +++ b/src/common/matrix.hpp @@ -0,0 +1,50 @@ +#ifndef TMWA_COMMON_MATRIX_HPP +#define TMWA_COMMON_MATRIX_HPP + +template +class Matrix +{ + std::unique_ptr _data; + size_t _xs, _ys; +public: + Matrix() + : _data() + , _xs() + , _ys() + {} + Matrix(size_t x, size_t y) + : _data(new T[x * y]()) + , _xs(x) + , _ys(y) + {} + // no copy-ctor or copy-assign + + void reset(size_t x, size_t y) + { + *this = Matrix(x, y); + } + void clear() + { + *this = Matrix(); + } + + T& ref(size_t x, size_t y) + { + return _data[x + y * _xs]; + } + const T& ref(size_t x, size_t y) const + { + return _data[x + y * _xs]; + } + + size_t xs() const + { + return _xs; + } + size_t ys() const + { + return _ys; + } +}; + +#endif // TMWA_COMMON_MATRIX_HPP diff --git a/src/common/md5calc.cpp b/src/common/md5calc.cpp index 1625912..36f220d 100644 --- a/src/common/md5calc.cpp +++ b/src/common/md5calc.cpp @@ -210,7 +210,7 @@ MD5_state MD5_from_string(const char* msg, const size_t msglen) if (64 - rem > 8) { for (int i=0; i<8; i++) - buf[0x38+i] = ((uint64_t)msglen*8) >> (i*8); + buf[0x38+i] = (static_cast(msglen)*8) >> (i*8); } for (int i=0; i<0x10; i++) X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24; @@ -219,7 +219,7 @@ MD5_state MD5_from_string(const char* msg, const size_t msglen) { memset(buf,'\0', 0x38); for (int i=0; i<8; i++) - buf[0x38+i] = ((uint64_t)msglen*8) >> (i*8); + buf[0x38+i] = (static_cast(msglen)*8) >> (i*8); for (int i=0; i<0x10; i++) X[i] = buf[4*i+0] | buf[4*i+1]<<8 | buf[4*i+2]<<16 | buf[4*i+3]<<24; MD5_do_block(&state, block); diff --git a/src/common/mmo.hpp b/src/common/mmo.hpp index e72bf80..a04fd34 100644 --- a/src/common/mmo.hpp +++ b/src/common/mmo.hpp @@ -206,7 +206,7 @@ struct map_session_data; struct GM_Account { int account_id; - int level; + uint8_t level; }; struct party_member diff --git a/src/common/socket.cpp b/src/common/socket.cpp index db944cc..0ee8712 100644 --- a/src/common/socket.cpp +++ b/src/common/socket.cpp @@ -29,7 +29,10 @@ const uint32_t RFIFO_SIZE = 65536; static const uint32_t WFIFO_SIZE = 65536; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" std::array, FD_SETSIZE> session; +#pragma GCC diagnostic pop /// clean up by discarding handled bytes inline @@ -119,7 +122,7 @@ void connect_client(int listen_fd) struct sockaddr_in client_address; socklen_t len = sizeof(client_address); - int fd = accept(listen_fd, (struct sockaddr *) &client_address, &len); + int fd = accept(listen_fd, reinterpret_cast(&client_address), &len); if (fd == -1) { perror("accept"); @@ -156,11 +159,14 @@ void connect_client(int listen_fd) setsockopt(fd, IPPROTO_TCP, TCP_THIN_DUPACK, &yes, sizeof yes); #endif +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" FD_SET(fd, &readfds); +#pragma GCC diagnostic pop fcntl(fd, F_SETFL, O_NONBLOCK); - session[fd].reset(new socket_data()); + session[fd] = make_unique(); session[fd]->rdata.new_(RFIFO_SIZE); session[fd]->wdata.new_(WFIFO_SIZE); @@ -202,10 +208,13 @@ int make_listen_port(uint16_t port) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &yes, sizeof yes); server_address.sin_family = AF_INET; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" server_address.sin_addr.s_addr = htonl(INADDR_ANY); server_address.sin_port = htons(port); +#pragma GCC diagnostic pop - if (bind(fd, (struct sockaddr *) &server_address, + if (bind(fd, reinterpret_cast(&server_address), sizeof(server_address)) == -1) { perror("bind"); @@ -217,9 +226,12 @@ int make_listen_port(uint16_t port) exit(1); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" FD_SET(fd, &readfds); +#pragma GCC diagnostic pop - session[fd].reset(new socket_data()); + session[fd] = make_unique(); session[fd]->func_recv = connect_client; session[fd]->created = TimeT::now(); @@ -254,18 +266,24 @@ int make_connection(uint32_t ip, uint16_t port) server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = ip; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" server_address.sin_port = htons(port); +#pragma GCC diagnostic pop fcntl(fd, F_SETFL, O_NONBLOCK); /// Errors not caught - we must not block /// Let the main select() loop detect when we know the state - connect(fd, (struct sockaddr *) &server_address, + connect(fd, reinterpret_cast(&server_address), sizeof(struct sockaddr_in)); +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" FD_SET(fd, &readfds); +#pragma GCC diagnostic pop - session[fd].reset(new socket_data()); + session[fd] = make_unique(); session[fd]->rdata.new_(RFIFO_SIZE); session[fd]->wdata.new_(WFIFO_SIZE); @@ -283,14 +301,20 @@ int make_connection(uint32_t ip, uint16_t port) void delete_session(int fd) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" if (fd < 0 || fd >= FD_SETSIZE) +#pragma GCC diagnostic pop return; // If this was the highest fd, decrease it // We could add a loop to decrement fd_max further for every null session, // but this is cheap and good enough for the typical case if (fd == fd_max - 1) fd_max--; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" FD_CLR(fd, &readfds); +#pragma GCC diagnostic pop if (session[fd]) { session[fd]->rdata.delete_(); @@ -343,11 +367,17 @@ void WFIFOSET(int fd, size_t len) void do_sendrecv(interval_t next_ms) { fd_set rfd = readfds, wfd; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" FD_ZERO(&wfd); +#pragma GCC diagnostic pop for (int i = 0; i < fd_max; i++) { if (session[i] && session[i]->wdata_size) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" FD_SET(i, &wfd); +#pragma GCC diagnostic pop } struct timeval timeout; { @@ -362,13 +392,19 @@ void do_sendrecv(interval_t next_ms) { if (!session[i]) continue; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" if (FD_ISSET(i, &wfd)) +#pragma GCC diagnostic pop { if (session[i]->func_send) //send_from_fifo(i); session[i]->func_send(i); } +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" if (FD_ISSET(i, &rfd)) +#pragma GCC diagnostic pop { if (session[i]->func_recv) //recv_to_fifo(i); @@ -406,7 +442,10 @@ void do_parsepacket(void) void do_socket(void) { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wold-style-cast" FD_ZERO(&readfds); +#pragma GCC diagnostic pop currentuse = 3; } diff --git a/src/common/utils.cpp b/src/common/utils.cpp index e3867eb..4e00808 100644 --- a/src/common/utils.cpp +++ b/src/common/utils.cpp @@ -87,7 +87,7 @@ int config_switch (const char *str) const char *ip2str(struct in_addr ip, bool extra_dot) { - const uint8_t *p = (const uint8_t *)(&ip); + const uint8_t *p = reinterpret_cast(&ip); static char buf[17]; if (extra_dot) sprintf(buf, "%d.%d.%d.%d.", p[0], p[1], p[2], p[3]); diff --git a/src/common/utils.hpp b/src/common/utils.hpp index f2a2117..caa39ed 100644 --- a/src/common/utils.hpp +++ b/src/common/utils.hpp @@ -12,40 +12,6 @@ #include "operators.hpp" #include "utils2.hpp" -/* -Notes about memory allocation in tmwAthena: -There used to be 3 sources of allocation: these macros, -a{C,M,Re}alloc in common/malloc.{h,c}, and direct calls. -I deleted malloc.{h,c} because it was redundant; -future calls should either use this or depend on the coming segfault. -*/ -template -void create_impl(T *& result, size_t number) -{ - result = (T *)calloc(number, sizeof(T)); - if (!result && number) - { - perror("SYSERR: malloc failure"); - abort(); - } -} -template -void recreate_impl(T *& result, size_t number) -{ - result = (T *)realloc(result, sizeof(T) * number); - if (!result && number) - { - perror("SYSERR: realloc failure"); - abort(); - } -} - -# define CREATE(result, type, number) \ - create_impl(result, number) - -# define RECREATE(result, type, number) \ - recreate_impl(result, number) - int remove_control_chars(char *str); int e_mail_check(const char *email); int config_switch (const char *str); diff --git a/src/common/utils2.hpp b/src/common/utils2.hpp index 5f02beb..2218625 100644 --- a/src/common/utils2.hpp +++ b/src/common/utils2.hpp @@ -214,17 +214,17 @@ struct is_array_of_unknown_bound : std::is_same::type[]> {}; -template -typename std::enable_if::value, std::unique_ptr>::type make_unique(A&&... a) +template, class... A> +typename std::enable_if::value, std::unique_ptr>::type make_unique(A&&... a) { - return std::unique_ptr(new T(a...)); + return std::unique_ptr(new T(a...)); } -template -typename std::enable_if::value, std::unique_ptr>::type make_unique(size_t sz) +template> +typename std::enable_if::value, std::unique_ptr>::type make_unique(size_t sz) { typedef typename std::remove_extent::type E; - return std::unique_ptr(new E[sz]); + return std::unique_ptr(new E[sz]()); } #endif // UTILS2_HPP -- cgit v1.2.3-70-g09d2