Code View

plugin / plugin-2.2.0.0 / example / plugin / testShape.cpp
// SPDX-License-Identifier: MIT
#include "Circle.hh"
#include "Ellipse.hh"
#include "Shape.hh"

#include <dso/DSOLoader.hh>
#include <plugin/Plugin.hh>

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

using namespace std;
using namespace plugin;
using namespace plugin::example;
using namespace fedem::dso;

vector< unique_ptr< Shape > > objectList;

int main( )
{
  DSOLoader::prefix( "lib"s );

  // ----- Config-based creation demo -----
  cout << "=== Config-based creation demo ===\n\n";

  // Load plugins
  try
  {
    DSOLoader::load( "./libCircle.so"s );
  }
  catch( exception& )
  {
  }
  try
  {
    DSOLoader::load( "./libEllipse.so"s );
  }
  catch( exception& )
  {
  }
  try
  {
    DSOLoader::load( "./libSquare.so"s );
  }
  catch( exception& )
  {
  }

  // Circle with config
  {
    auto circle = Shape::create( "Circle", Circle::Config { 42 } );
    if( circle )
    {
      cout << "Circle (config r=42): ";
      circle->printOn( cout );

      objectList.push_back( move( circle ) );
    }
  }

  // Ellipse with config
  {
    auto ellipse = Shape::create( "Ellipse", Ellipse::Config { 10, 20 } );
    if( ellipse )
    {
      cout << "Ellipse (config a=10 b=20): ";
      ellipse->printOn( cout );

      objectList.push_back( move( ellipse ) );
    }
  }

  // Default construction (backward compatible)
  {
    auto circle = Shape::create( "Circle" );
    if( circle )
    {
      circle->setSize( 7 );
      cout << "Circle (default + setSize 7): ";
      circle->printOn( cout );

      objectList.push_back( move( circle ) );
    }
  }

  // Square — registered with REGISTER (no config support)
  {
    auto square = Shape::create( "Square" );
    if( square )
    {
      square->setSize( 15 );
      cout << "Square (default + setSize 15): ";
      square->printOn( cout );

      objectList.push_back( move( square ) );
    }
  }

  cout << "\n=== Interactive mode ===\n\n";

  // ----- Interactive mode -----
  do
  {
    cout << "Available addons:";
    auto addons = Plugin< Shape >::catalog( ).names( true );
    if( addons.empty( ) )
    {
      cout << " (none)\n";
    }
    else
    {
      for( auto const& name : addons )
        cout << ' ' << name;
      cout << '\n';
    }

    cout << "shape/command : ";
    string cmd;
    cin >> cmd;

    if( ! cin || cmd == "exit" || cmd == "quit" || cmd == "q" )
      break;

    if( cmd == "list" )
    {
      for( auto const& shape : objectList )
      {
        shape->printOn( cout );
      }
      cout << '\n';

      continue;
    }

    if( find( addons.cbegin( ), addons.cend( ), cmd ) == addons.cend( ) )
    {
      auto const dsoFilename = DSOLoader::prefix( ) + cmd + ".so"s;
      bool loaded            = false;
      try
      {
        DSOLoader::load( "./"s + dsoFilename );
        loaded = true;
      }
      catch( exception& )
      {
      }

      if( ! loaded )
      {
        try
        {
          DSOLoader::load( dsoFilename );
          loaded = true;
        }
        catch( exception& )
        {
          cerr << "Could not load DSO for '" << cmd << "'\n";
          continue;
        }
      }
    }

    auto shape = Shape::create( cmd );

    if( ! shape )
    {
      cout << '`' << cmd << "` could not be created!\n";
    }
    else
    {
      cout << "size : ";
      unsigned int size;
      cin >> size;

      if( ! cin )
      {
        constexpr auto max_size = std::numeric_limits< std::streamsize >::max( );
        cin.clear( );                  // unset failbit
        cin.ignore( max_size, '\n' );  // skip bad input
        cout << "abort: unknow size!\n";
        continue;
      }

      shape->setSize( size );

      cout << "Size of shape is " << shape->getSize( ) << endl;
      cout << *shape << '\n';

      objectList.push_back( move( shape ) );
    }
  } while( true );

  return EXIT_SUCCESS;
}