Private Proxies – Buy Cheap Private Elite USA Proxy + 50% Discount!Private Proxies – Buy Cheap Private Elite USA Proxy + 50% Discount!Private Proxies – Buy Cheap Private Elite USA Proxy + 50% Discount!Private Proxies – Buy Cheap Private Elite USA Proxy + 50% Discount!
    0
  •   was successfully added to your cart.
  • Home
  • Buy proxies
  • Extra features
  • Help
  • Contact
  • Login
  • 50% OFF
    BUY NOW!
    50
    PROXIES
    $19
    --------------------
    BUY NOW!
    BUY NOW!
    BUY NOW!
    BUY NOW!
    BUY NOW!
    $29
    $49
    $109
    $179
    $299
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    PROXIES
    PROXIES
    PROXIES
    PROXIES
    PROXIES
    100
    200
    500
    1,000
    2,000
    TOP SELLER
    BEST VALUE
    For All Private Proxies!

I wanted to include some kind of debug or admin console in my game engine. Basically a simple command line that I can use to interact with the code while it runs; i.e. modify object properties, change the game state, and receive information about error handling. It begins with a stream buffer object.

ConsoleBuffer.hpp

#ifndef CONSOLE_BUFFER_HPP #define CONSOLE_BUFFER_HPP  /***********/ /* Headers */ /***********/ #include <iostream> #include <streambuf>  class ConsoleBuffer : public std::streambuf {     public:         ConsoleBuffer();          ~ConsoleBuffer();      private:         virtual int overflow(int character);          virtual int underflow();          virtual int sync();          static const int bufferSize = 64;         char iBuffer[bufferSize];         char oBuffer[bufferSize]; };  #endif // CONSOLE_BUFFER_HPP 

ConsoleBuffer.cpp

/***********/ /* Headers */ /***********/ #include <cstdio> #include <cstring> #include <io.h>  ConsoleBuffer::ConsoleBuffer() {     setp(iBuffer, iBuffer + (bufferSize - 1));     setg(oBuffer + bufferSize, oBuffer + bufferSize, oBuffer + bufferSize); }  ConsoleBuffer::~ConsoleBuffer() {     sync(); }  int ConsoleBuffer::overflow(int character) {     if((character != EOF) && (pptr() != epptr()))     {         return sputc(static_cast<char>(character));     }     else if(character != EOF)     {         sync();         return overflow(character);     }     else     {         return sync();     } }  int ConsoleBuffer::underflow() {     if(gptr() != egptr())         return static_cast<int>(*gptr());      int putbackSize = gptr() - eback();      if(putbackSize > 32)         putbackSize = 32;      std::memmove(iBuffer + (32 - putbackSize), gptr() - putbackSize, putbackSize);      int numOfChars = read(0, iBuffer + 32, bufferSize - 32);      if(numOfChars <= 0)         return EOF;      setg(iBuffer + 32 - putbackSize, iBuffer + 32, iBuffer + 32 + numOfChars);      return static_cast<int>(*gptr()); }  int ConsoleBuffer::sync() {     if(pbase() != pptr())     {         std::size_t size = static_cast<int>(pptr() - pbase());         fwrite(pbase(), 1, size, stderr);          setp(pbase(), epptr());     }      return 0; } 

Right off the bat, I’ll say I looked at a number of resources and examples on implementing a stream buffer and kind of used an amalgamation of those methods. I’m still a little unfamiliar with some of the C standard library stuff I used, and as a result it feels hacked together. I would really appreciate some good references on streambuf implementations.

Next is the Console class. This contains an iostream object which uses the ConsoleBuffer, and an std::map which stores command names as keys and ConsoleCommand objects as values. We interact with the console primarily in two ways, the first is the overloaded << operator, which simply writes to the command line. The other is via the Console::listen() function. This is non-blocking, and calls the Console::readFromStream() in a separate thread, but executes commands back in the main thread so that we can manipulate any data without having to worry about more locks and mutexes. We also do a little parsing of the commands, it’s pretty rudimentary but supports nested commands and basic data types.

Console.hpp

#ifndef CONSOLE_HPP #define CONSOLE_HPP  /***********/ /* Headers */ /***********/ #include <ConsoleBuffer.hpp> #include <ConsoleCommand.hpp> #include <map> #include <vector> #include <memory> #include <thread>  class Console {     public:         Console();          ~Console();          void registerCommand(std::string id, std::shared_ptr<AbstractBase::ConsoleCommand> command);          void listen();          void setPrompt(std::string prompt);          bool usePrompt(bool value = -1);          std::string getPrompt();          template<typename ValueType>         std::ostream& operator<<(ValueType value)         {             return (_stream << value);         }      private:         std::map<std::string, std::shared_ptr<AbstractBase::ConsoleCommand>> _commands;         bool _usePrompt;         std::string _prompt;         ConsoleBuffer _buffer;         std::iostream _stream;         std::thread _thread;         bool _threadIsActive;         std::vector<std::string> _tokens;          void readFromStream();          std::string parse(std::vector<std::string> tokens); };  Console& console();  #endif // CONSOLE_HPP 

Console.cpp

/***********/ /* Headers */ /***********/ #include <Console.hpp> #include <iterator>  Console::Console() : _buffer(), _stream(&_buffer), _prompt("> "), _usePrompt(true), _threadIsActive(false) {     _stream.tie(&_stream);     _thread = std::thread([]{ return; }); }  Console::~Console() {     if(_thread.joinable())         _thread.join(); }  void Console::registerCommand(std::string id, std::shared_ptr<AbstractBase::ConsoleCommand> command) {     _commands[id] = command; }  std::string Console::parse(std::vector<std::string> tokens) {     if(tokens.empty())         return "";      auto itr = tokens.begin();      while(itr != tokens.end())     {         if(itr->front() == '"')         {             itr->erase(itr->begin());              if(itr->back() == '"')             {                 itr->pop_back();             }             else             {                 for(auto subItr = itr + 1; subItr != tokens.end(); tokens.erase(subItr))                 {                     itr->append(1, ' ');                     itr->append(*subItr);                      if(subItr->back() == '"')                     {                         tokens.erase(subItr);                         break;                     }                 }                  if(itr->back() != '"')                 {                     _stream << Alert("Missing terminating \" character", Alert::Code::ERROR);                     return "";                 }                  itr->pop_back();             }         }         else if(itr->front() == '$  ')         {             itr->erase(itr->begin());              if(itr->front() != '{')             {                 _stream << Alert("Invalid token, subexpression must begin with $  {", Alert::Code::ERROR);                 return "";             }             else             {                 itr->erase(itr->begin());                  std::vector<std::string> expression;                  int nestedLevel = 0;                  for(auto subItr = itr; subItr != tokens.end(); tokens.erase(subItr))                 {                     expression.push_back(*subItr);                      if(subItr->front() == '$  ')                     {                         nestedLevel++;                     }                     if(subItr->back() == '}')                     {                         if(nestedLevel != 0)                         {                             nestedLevel--;                         }                         else                         {                             tokens.erase(subItr);                             break;                         }                     }                 }                  if(expression.back().back() != '}')                 {                     _stream << Alert("Missing terminating } character", Alert::Code::ERROR);                     return "";                 }                  expression.back().pop_back();                  tokens.insert(itr, parse(expression));             }         }          itr++;     }      if(_commands.find(tokens.front()) != _commands.end())     {         return _commands.find(tokens.front())->second->execute(tokens);     }     else     {         _stream << Alert("\"" + tokens.front() + "\" is not a valid command", Alert::Code::ERROR | Alert::Code::INVALID_COMMAND);         return "";     } }  void Console::listen() {     if(!_threadIsActive)     {         if(_thread.joinable())         {             _thread.join();             parse(_tokens);         }         else             _thread = std::thread([=]{ readFromStream(); });     } }  void Console::readFromStream() {     _threadIsActive = true;      _tokens.clear();      if(_usePrompt)         _stream << _prompt;      std::string input;      getline(_stream, input);      if(input == "")     {         _threadIsActive = false;         return;     }      std::istringstream sstream(input);      std::copy(std::istream_iterator<std::string>(sstream),                 std::istream_iterator<std::string>(),                 std::back_inserter(_tokens));      _threadIsActive = false; }  void Console::setPrompt(std::string prompt) {     _prompt = prompt; }  std::string Console::getPrompt() {     return _prompt; }  bool Console::usePrompt(bool value) {     if(value != -1)         _usePrompt = value;      return _usePrompt; }  Console& console() {     static Console _console;      return _console; } 

Before getting into the ConsoleCommand templates, I wanted to throw in this simple lexical cast which comes into play later. I know boost includes a pretty full-featured lexical cast but I will eventually need to develop a way of casting to more complex object types so I figured I’d just make my own.

LexicalCast.hpp

#ifndef LEXICAL_CAST_HPP #define LEXICAL_CAST_HPP  /***********/ /* Headers */ /***********/ #include <string> #include <sstream>  template<typename Type> Type lexical_cast(std::string str) {     Type value;      std::stringstream sstream(str);      sstream >> value;      return value; }  template<> std::string lexical_cast<std::string>(std::string str);  #endif // LEXICAL_CAST_HPP 

LexicalCast.cpp

/***********/ /* Headers */ /***********/ #include <LexicalCast.hpp>  template<> std::string lexical_cast<std::string>(std::string str) {     return str; } 

Now for the ConsoleCommand. The tricky part was finding a way to determine the quantity and types of arguments for each command in order to construct a tuple of usable variables from the separate tokens which we can forward to the function.

ConsoleCommand.hpp

#ifndef CONSOLE_COMMAND_HPP #define CONSOLE_COMMAND_HPP  /***********/ /* Headers */ /***********/ #include <Alert.hpp> #include <LexicalCast.hpp> #include <string> #include <functional> #include <vector>  namespace AbstractBase {     class ConsoleCommand     {         public:             virtual std::string execute(std::vector<std::string> tokens) = 0;     }; }  template<typename ReturnType, typename... ArgumentList> class ConsoleCommand : public AbstractBase::ConsoleCommand {     public:         ConsoleCommand(std::function<ReturnType(ArgumentList...)> func)         {             _function = func;         }          std::string execute(std::vector<std::string> tokens)         {             constexpr auto numberOfArguments = std::tuple_size<typename std::decay<std::tuple<ArgumentList...>>::type>::value;              if(tokens.size() - 1 != numberOfArguments)             {                 std::stringstream sstream;                  sstream << Alert("Command '" + tokens.front() + "' expects " + std::to_string(numberOfArguments)                                     + " argument(s), " + std::to_string(tokens.size() - 1) + " provided",                                     Alert::Code::ERROR | Alert::Code::INVALID_ARG_COUNT);                  return sstream.str();             }              tokens.erase(tokens.begin());              auto parameters = buildParameterPack(tokens, std::make_index_sequence<numberOfArguments>());              return std::to_string(invoke(parameters, std::make_index_sequence<numberOfArguments>{}));         }      protected:         std::function<ReturnType(ArgumentList...)> _function;          template<std::size_t... N>         decltype(auto) buildParameterPack(std::vector<std::string> tokens, std::index_sequence<N...>)         {             return std::make_tuple(lexical_cast<getArgumentType<N>>(tokens[N])...);         }          template<typename Tuple, std::size_t... index>         ReturnType invoke(Tuple&& args, std::index_sequence<index...>)         {             return _function(std::get<index>(std::forward<Tuple>(args))...);         }          template<std::size_t N>         using getArgumentType = typename std::tuple_element<N, std::tuple<ArgumentList...>>::type; };  template<typename... ArgumentList> class ConsoleCommand<void, ArgumentList...> : public AbstractBase::ConsoleCommand {     public:         ConsoleCommand(std::function<void(ArgumentList...)> func)         {             _function = func;         }          std::string execute(std::vector<std::string> tokens)         {             constexpr auto numberOfArguments = std::tuple_size<typename std::decay<std::tuple<ArgumentList...>>::type>::value;              if(tokens.size() - 1 != numberOfArguments)             {                 std::stringstream sstream;                  sstream << Alert("Command '" + tokens.front() + "' expects " + std::to_string(numberOfArguments)                                     + " argument(s), " + std::to_string(tokens.size() - 1) + " provided",                                     Alert::Code::ERROR | Alert::Code::INVALID_ARG_COUNT);                  return sstream.str();             }              tokens.erase(tokens.begin());              auto parameters = buildParameterPack(tokens, std::make_index_sequence<numberOfArguments>());              invoke(parameters, std::make_index_sequence<numberOfArguments>{});              return "";         }      protected:         std::function<void(ArgumentList...)> _function;          template<std::size_t... N>         decltype(auto) buildParameterPack(std::vector<std::string> tokens, std::index_sequence<N...>)         {             return std::make_tuple(lexical_cast<getArgumentType<N>>(tokens[N])...);         }          template<typename Tuple, std::size_t... index>         void invoke(Tuple&& args, std::index_sequence<index...>)         {             return _function(std::get<index>(std::forward<Tuple>(args))...);         }          template<std::size_t N>         using getArgumentType = typename std::tuple_element<N, std::tuple<ArgumentList...>>::type; };  #endif // CONSOLE_COMMAND_HPP 

And finally, below are a few examples of how you would register console commands.

Examples:

void exit() {     while(Game::instance()->getActiveState() != nullptr)     {         Game::instance()->popState();     } }  void echo(std::string str) {     console() << str << std::endl; }  int fps() {     return Game::instance()->getFPS(); }  void createSprite(std::string id, std::string textureFilePath) {     auto texture = construct<TGE::Texture>(id, textureFilePath);     auto sprite = construct<TGE::Sprite>(id, texture);      Game::instance()->getActiveState()->drawableStack.push_back(sprite); }  void destroySprite(std::string id) {     destroy<Sprite>(id); }  void registerFunctions() {     auto _exit = std::make_shared<ConsoleCommand<void>>(exit);     auto _echo = std::make_shared<ConsoleCommand<void, std::string>>(echo);     auto _fps = std::make_shared<ConsoleCommand<int>>(fps);     auto _createSprite = std::make_shared<ConsoleCommand<void, std::string, std::string>>(createSprite);     auto _destroySprite = std::make_shared<ConsoleCommand<void, std::string>>(destroySprite);      console().registerCommand("exit", _exit);     console().registerCommand("echo", _echo);     console().registerCommand("fps", _fps);     console().registerCommand("createSprite", _createSprite);     console().registerCommand("destroySprite", _destroySprite); } 

This code is working, everything compiles and runs as expected. I do have some improvements that I plan to work on and additional functionality I want to add in order to make it more powerful, but for the time being I just want to know if there are any glaring mistakes or things I clearly should have done better. Thanks in advance for taking the time to look at my code!

✓ Extra quality

ExtraProxies brings the best proxy quality for you with our private and reliable proxies

✓ Extra anonymity

Top level of anonymity and 100% safe proxies – this is what you get with every proxy package

✓ Extra speed

1,ooo mb/s proxy servers speed – we are way better than others – just enjoy our proxies!

50 proxies

$19/month

50% DISCOUNT!
$0.38 per proxy
✓ Private
✓ Elite
✓ Anonymous
Buy now

100 proxies

$29/month

50% DISCOUNT!
$0.29 per proxy
✓ Private
✓ Elite
✓ Anonymous
Buy now

200 proxies

$49/month

50% DISCOUNT!
$0.25 per proxy
✓ Private
✓ Elite
✓ Anonymous
Buy now

500 proxies

$109/month

50% DISCOUNT!
$0.22 per proxy
✓ Private
✓ Elite
✓ Anonymous
Buy now

1,000 proxies

$179/month

50% DISCOUNT!
$0.18 per proxy
✓ Private
✓ Elite
✓ Anonymous
Buy now

2,000 proxies

$299/month

50% DISCOUNT!
$0.15 per proxy
✓ Private
✓ Elite
✓ Anonymous
Buy now

USA proxy location

We offer premium quality USA private proxies – the most essential proxies you can ever want from USA

100% anonymous

Our proxies have TOP level of anonymity + Elite quality, so you are always safe and secure with your proxies

Unlimited bandwidth

Use your proxies as much as you want – we have no limits for data transfer and bandwidth, unlimited usage!

Superfast speed

Superb fast proxy servers with 1,000 mb/s speed – sit back and enjoy your lightning fast private proxies!

99,9% servers uptime

Alive and working proxies all the time – we are taking care of our servers so you can use them without any problems

No usage restrictions

You have freedom to use your proxies with every software, browser or website you want without restrictions

Perfect for SEO

We are 100% friendly with all SEO tasks as well as internet marketing – feel the power with our proxies

Big discounts

Buy more proxies and get better price – we offer various proxy packages with great deals and discounts

Premium support

We are working 24/7 to bring the best proxy experience for you – we are glad to help and assist you!

Satisfaction guarantee

24/7 premium support, free proxy activation and 100% safe payments! Best reliability private proxies for your needs!

Best Proxy Packs

  • 2,000 Private Proxies $600.00 $299.00 / month
  • 1,000 Private Proxies $360.00 $179.00 / month

Quick Links

  • More information
  • Contact us
  • Privacy Policy
  • Terms and Conditions

Like And Follow Us


Copyright ExtraProxies.com | All Rights Reserved.
  • Checkout
  • Contact
  • Help
  • Home
  • My Account
  • My Cart
  • News
  • Privacy Policy
  • Proxy features
  • Proxy packs
  • Terms and Conditions
Private Proxies – Buy Cheap Private Elite USA Proxy + 50% Discount!
    0 items