<commit_before>#include <stdio.h>
#include <sysexits.h> 	// portablish exit values.
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <string.h>
#include <assert.h>

#include <string>

#include <client.h>                     // we are a client of the watcher.
#include <libwatcher/edgeMessage.h>     // we send edgeMessages to the watcher.
#include <logger.h>

using namespace std;
using namespace watcher;
using namespace watcher::event;

static const char *rcsid __attribute__ ((unused)) = "$Id: routingfeeder.c,v 1.0 2009/04/28 22:08:47 glawler Exp $";

#define DEBUG 1

/* This is a feeder which polls the routing table,
 * and draws the routing algorithm's edges on the watcher
 *
 *  Copyright (C) 2006,2007,2008,2009 Sparta Inc.  Written by the NIP group, SRD, ISSO
 */

typedef struct Route
{
    unsigned int dst;
    unsigned int nexthop;
    unsigned int mask;
    char iface[16];

    struct Route *next;
} Route;

/*
   Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask       MTU      Window  IRTT
   eth0    7402A8C0        7C02A8C0        0007    0       0       0       FFFFFFFF   00       0
   eth0    7402A8C0        7202A8C0        0007    0       0       0       FFFFFFFF   00       0
   */

static Route *routeRead(unsigned int network, unsigned int netmask)
{
    TRACE_ENTER();

    FILE *fil;
    char line[1024];
    Route *list=NULL,*nxt;

    fil=fopen("/proc/net/route","r");
    while(fgets(line,sizeof(line)-1,fil))
    {
        char iface[16];
        int flags,refcnt,use,metric,mtu,window;
        unsigned int dst,nexthop,mask;
        int rc;

        rc=sscanf(line,"%s\t%x\t%x\t%d\t%d\t%d\t%d\t%x\t%o\t%d\n",iface,&dst,&nexthop,&flags,&refcnt,&use,&metric,&mask,&mtu,&window);

        if (rc==10 && ((ntohl(dst) & netmask) == network))
        {
            nxt = (Route*)malloc(sizeof(*nxt));
            assert(nxt!=NULL);
            nxt->dst=htonl(dst);
            nxt->nexthop=htonl(nexthop);
            nxt->mask=ntohl(mask);
            strncpy(nxt->iface,iface,sizeof(nxt->iface));

            nxt->next=list;
            list=nxt;
        }
    }

    fclose(fil);

    TRACE_EXIT();
    return list;
}

static void routeDump(Route *r)
{
    TRACE_ENTER();
    while(r)
    {
        LOG_DEBUG(r->dst << " -> " << r->nexthop << " mask " << r->mask);
        r=r->next;
    }
    TRACE_EXIT();
}

static int routeNumber(Route *r)
{
    TRACE_ENTER();
    int count=0;

    while(r)
    {
        count++;
        r=r->next;
    }

    TRACE_EXIT_RET(count);
    return count;
}

static void routeFree(Route *r)
{
    TRACE_ENTER();
    Route *d;

    while(r)
    {
        d=r;
        r=r->next;
        free(d);
    }
    TRACE_EXIT();
}

static void routeInsert(Route **list, Route *n)
{
    TRACE_ENTER();
    Route *nxt;
    nxt = (Route*)malloc(sizeof(*nxt));
    nxt->dst=n->dst;
    nxt->nexthop=n->nexthop;
    nxt->mask=n->mask;

    nxt->next=*list;
    *list=nxt;
    TRACE_EXIT();
}

/* return first route to in list which has the same nexthop
*/
static Route *routeSearchNext(Route *list, Route *key)
{
    TRACE_ENTER();
    Route *r;

    r=list;
    while(r)
    {
        if (r->nexthop==key->nexthop)
        {
            TRACE_EXIT_RET(r);
            return r;
        }
        r=r->next;
    }
    TRACE_EXIT_RET("NULL");
    return NULL;
}

typedef struct detector
{
    Client *watcherClientPtr;

    useconds_t reportperiod;		/* frequency to generate reports at */
    int reportnum;
    unsigned int localaddr;
    string iface;
    int routeedgewidth;
    Color onehopcolor;
    Color nexthopcolor;

    string nexthoplayer;
    string onehoplayer;

    int duration;			  /* Time to run (in seconds) or 0 to run until broken */

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

} detector;

typedef struct DetectorInit
{
    useconds_t reportperiod;		/* frequency to generate reports at */
    string iface;
    int onehopfamily;
    Color onehopcolor;
    Color nexthopcolor;
    int mouthnum;
    int duration;			  /* Time to run (in seconds) or 0 to run until broken */
    int routeedgewidth;

    string serverName;

    string nexthoplayer;
    string onehoplayer;

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

} DetectorInit;

static void updateRoutes(detector *st, Route *list)
{
    TRACE_ENTER();
    Route *r,*tmpNextHop=NULL;
    Route *tmpOneHop=NULL;

    /*
     * 	for each edge in newlist,
     * 	   	if there is not an edge in oldList or tmpList to nexthop, add it, and add to tmpList
     */
    vector<MessagePtr> messages;
    for(r=list;r;r=r->next)
    {

        if (st->iface != string(r->iface))    /* if we're checking interfaces, and this route is on the wrong one...  */
            continue;

#if 1
        LOG_DEBUG("nexthop inserting us -> " << r->nexthop);
#endif

        if ((r->nexthop!=0) && (routeSearchNext(tmpNextHop,r)==NULL))   /* if its multi-hop, and not on the next hop list */
        {
            EdgeMessagePtr em=EdgeMessagePtr(new EdgeMessage);
            em->node1=boost::asio::ip::address_v4(st->localaddr);
            em->node2=boost::asio::ip::address_v4(r->nexthop);
            em->edgeColor=st->nexthopcolor;
            em->expiration=st->reportperiod*1.5;
            em->width=st->routeedgewidth;
            em->layer=ROUTING_LAYER; // GTL st->nexthoplayer;
            em->addEdge=true;
            em->bidirectional=false;
            messages.push_back(em);

            routeInsert(&tmpNextHop,r);
        }

        if (r->nexthop==0)   /* if its a one-hop... */
        {
#if 1
            LOG_DEBUG("onehop inserting us -> " << r->dst);
#endif
            EdgeMessagePtr em=EdgeMessagePtr(new EdgeMessage);
            em->node1=boost::asio::ip::address_v4(st->localaddr);
            em->node2=boost::asio::ip::address_v4(r->dst);
            em->edgeColor=st->onehopcolor;
            em->expiration=st->reportperiod*1.5;
            em->width=st->routeedgewidth;
            em->layer=ROUTING_LAYER; // GTL st->onehoplayer;
            em->addEdge=true;
            em->bidirectional=false;
            messages.push_back(em);

            routeInsert(&tmpOneHop,r);
        }
    }
    st->watcherClientPtr->sendMessages(messages);

    routeFree(tmpNextHop);
    routeFree(tmpOneHop);

    TRACE_EXIT();
}

/* This is called regularly by the select loop (below)
 * It will create a message, and send it to this node's coordinator
 */
static void detectorSend(detector *st)
{
    TRACE_ENTER();

    Route *list;

    list=routeRead(st->filterNetwork.s_addr, st->filterMask.s_addr);

    long long int curtime;
    struct timeval tp;
    gettimeofday(&tp, NULL);
    curtime=(long long int)tp.tv_sec * 1000 + (long long int)tp.tv_usec/1000;

    LOG_DEBUG("node= " << st->localaddr << " time= " << curtime << " numroutes= " << routeNumber(list));

#ifdef DEBUG
#if 0
    LOG_DEBUG("old:");
    routeDump(st->oldList);
#endif
    LOG_DEBUG("new:");
    routeDump(list);
#endif

    st->reportnum++;

    updateRoutes(st,list);

    routeFree(list);

    TRACE_EXIT();
}

static detector *detectorInit(DetectorInit *detinit)
{
    TRACE_ENTER();
    detector *st;

    st=new detector;
    st->iface="";

    st->watcherClientPtr=new Client(detinit->serverName);
    if(st->watcherClientPtr==NULL)
        return NULL;

    st->duration=detinit->duration;
    st->reportperiod=detinit->reportperiod;
    st->reportnum=0;
    st->iface=detinit->iface;

    st->onehoplayer=detinit->onehoplayer;
    st->onehopcolor=detinit->onehopcolor;

    st->nexthoplayer=detinit->nexthoplayer;
    st->nexthopcolor=st->nexthopcolor;

    st->routeedgewidth=detinit->routeedgewidth;

	st->filterNetwork.s_addr=detinit->filterNetwork.s_addr;
	st->filterMask.s_addr=detinit->filterMask.s_addr;
	st->localhost.s_addr=detinit->localhost.s_addr;

    TRACE_EXIT();
    return st;
}

/*
 * Wait around until we are ready to generate a message, then do it.
 */
static void selectLoop(detector *dt)
{
    TRACE_ENTER();

    time_t startTime=time(NULL);

    while(1)
    {
        usleep(dt->reportperiod*(useconds_t)1000.0);
        detectorSend(dt);

        if (dt->duration)
            if (time(NULL)-startTime>dt->duration)
                break;
    }

    dt->watcherClientPtr->wait();

    TRACE_EXIT();
}

int main(int argc, char *argv[])
{
    TRACE_ENTER();
    detector *dt;
    int ch;
    string logPropsFile("routeFeeder.log.properties");

    DetectorInit detinit;
    detinit.iface="";
    detinit.onehopcolor=Color::green;
    detinit.onehoplayer="One Hop Routing";
    detinit.nexthopcolor=Color::blue;
    detinit.nexthoplayer="Network Routing";
    detinit.reportperiod=2000;
    detinit.duration=0;
    detinit.routeedgewidth=15;

	detinit.filterNetwork.s_addr=0;
	detinit.filterMask.s_addr=0;
	detinit.localhost.s_addr=0;

    while ((ch = getopt(argc, argv, "m:n:h:o:x:t:e:b:i:d:p:w:l:?")) != -1)
        switch (ch)
        {
            case 'm': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterMask))
                      {
                          fprintf(stderr, "Error parsing filter mask: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'n': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterNetwork))
                      {
                          fprintf(stderr, "Error parsing filter network: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'h': if(-1 == inet_pton(AF_INET, optarg, &detinit.localhost))
                      {
                          fprintf(stderr, "Error parsing localhost address: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'o':
                      detinit.onehopcolor.fromString(optarg);
                      break;
            case 'x':
                      detinit.nexthopcolor.fromString(optarg);
                      break;
            case 't':
                      sscanf(optarg,"%d",&detinit.duration);
                      break;
            case 'e':
                      detinit.onehoplayer=string(optarg);
                      break;
            case 'b':
                      detinit.nexthoplayer=string(optarg);
                      break;
            case 'i':
                      detinit.iface=string(optarg);
                      break;
            case 'd':
                      detinit.serverName=string(optarg);
                      break;
            case 'p':
                      sscanf(optarg,"%d",&detinit.reportperiod);
                      break;
            case 'w':
                      sscanf(optarg, "%d", &detinit.routeedgewidth);
                      break;
            case 'l':
                      logPropsFile=string(optarg);
                      break;
            case '?':
            default:
                      fprintf(stderr,"routingdetector - poll the linux routing table, and draw the routes in the watcher\n"
                              "-d ipaddr/hostname - specify watcherd address to connect to (duck)\n"
                              "-h ipaddr - this host's address\n"
                              "-m netmask - the mask used to filter the routes (ex. 255.255.255.0)\n"
                              "-n network - the network used to filter the routes (ex. 192.168.1.0)\n"
                              "-p milliseconds - specify the period to poll and report\n"
                              "-i interface - display only routes through this ethernet interface (or any if unspecified)\n"
                              "-o color - onehop edge color\n"
                              "-e layer - onehop layer name\n"
                              "-x color - nexthop edge color\n"
                              "-b layer - nexthop layer name\n"
                              "-t seconds - Run for this long, then exit\n"
                              "-w width - make edges width pixels wide (default 15)\n"
                             );
                      exit(1);
                      break;
        }

    // init the logging system
    LOAD_LOG_PROPS(logPropsFile);
    LOG_INFO("Logger initialized from file \"" << logPropsFile << "\"");

	// check args, errors, etc before doing real work
	if(detinit.localhost.s_addr == 0)
    {
        fprintf(stderr, "localhost address cannot be blank\n");
        exit(EX_USAGE);
    }
	if(detinit.filterNetwork.s_addr == 0)
	{
        fprintf(stderr, "filter network cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.filterMask.s_addr == 0)
	{
        fprintf(stderr, "filter mask cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.serverName.empty())
	{
        fprintf(stderr, "watcherd hostname cannot be blank\n");
        exit(EX_USAGE);
	}

    dt=detectorInit(&detinit);

    if (dt==NULL)
    {
        fprintf(stderr,"detector init failed, probably could not connect to infrastructure demon.\n");
        exit(1);
    }
    printf("%s: starting\n",argv[0]);
    selectLoop(dt);

    TRACE_EXIT();
    return 0;
}
<commit_msg>send routes as array of messages so they all get stuck in the same IP packet.<commit_after>#include <stdio.h>
#include <sysexits.h> 	// portablish exit values.
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <string.h>
#include <assert.h>

#include <string>

#include <client.h>                     // we are a client of the watcher.
#include <libwatcher/edgeMessage.h>     // we send edgeMessages to the watcher.
#include <logger.h>

using namespace std;
using namespace watcher;
using namespace watcher::event;

static const char *rcsid __attribute__ ((unused)) = "$Id: routingfeeder.c,v 1.0 2009/04/28 22:08:47 glawler Exp $";

// #define DEBUG 1

/* This is a feeder which polls the routing table,
 * and draws the routing algorithm's edges on the watcher
 *
 *  Copyright (C) 2006,2007,2008,2009 Sparta Inc.  Written by the NIP group, SRD, ISSO
 */

typedef struct Route
{
    unsigned int dst;
    unsigned int nexthop;
    unsigned int mask;
    char iface[16];

    struct Route *next;
} Route;

/*
   Iface   Destination     Gateway         Flags   RefCnt  Use     Metric  Mask       MTU      Window  IRTT
   eth0    7402A8C0        7C02A8C0        0007    0       0       0       FFFFFFFF   00       0
   eth0    7402A8C0        7202A8C0        0007    0       0       0       FFFFFFFF   00       0
   */

static Route *routeRead(unsigned int network, unsigned int netmask)
{
    TRACE_ENTER();

    FILE *fil;
    char line[1024];
    Route *list=NULL,*nxt;

    fil=fopen("/proc/net/route","r");
    while(fgets(line,sizeof(line)-1,fil))
    {
        char iface[16];
        int flags,refcnt,use,metric,mtu,window;
        unsigned int dst,nexthop,mask;
        int rc;

        rc=sscanf(line,"%s\t%x\t%x\t%d\t%d\t%d\t%d\t%x\t%o\t%d\n",iface,&dst,&nexthop,&flags,&refcnt,&use,&metric,&mask,&mtu,&window);

        if (rc==10 && ((ntohl(dst) & ntohl(netmask)) == ntohl(network)))
        {
            nxt = (Route*)malloc(sizeof(*nxt));
            assert(nxt!=NULL);
            nxt->dst=htonl(dst);
            nxt->nexthop=htonl(nexthop);
            nxt->mask=ntohl(mask);
            strncpy(nxt->iface,iface,sizeof(nxt->iface));

            nxt->next=list;
            list=nxt;
        }
    }

    fclose(fil);

    TRACE_EXIT();
    return list;
}

#if DEBUG
static void routeDump(Route *r)
{
    TRACE_ENTER();
    while(r)
    {
        LOG_DEBUG(r->dst << " -> " << r->nexthop << " mask " << r->mask);
        r=r->next;
    }
    TRACE_EXIT();
}
#endif // DEBUG

static int routeNumber(Route *r)
{
    TRACE_ENTER();
    int count=0;

    while(r)
    {
        count++;
        r=r->next;
    }

    TRACE_EXIT_RET(count);
    return count;
}

static void routeFree(Route *r)
{
    TRACE_ENTER();
    Route *d;

    while(r)
    {
        d=r;
        r=r->next;
        free(d);
    }
    TRACE_EXIT();
}

static void routeInsert(Route **list, Route *n)
{
    TRACE_ENTER();
    Route *nxt;
    nxt = (Route*)malloc(sizeof(*nxt));
    nxt->dst=n->dst;
    nxt->nexthop=n->nexthop;
    nxt->mask=n->mask;

    nxt->next=*list;
    *list=nxt;
    TRACE_EXIT();
}

/* return first route to in list which has the same nexthop
*/
static Route *routeSearchNext(Route *list, Route *key)
{
    TRACE_ENTER();
    Route *r;

    r=list;
    while(r)
    {
        if (r->nexthop==key->nexthop)
        {
            TRACE_EXIT_RET(r);
            return r;
        }
        r=r->next;
    }
    TRACE_EXIT_RET("NULL");
    return NULL;
}

typedef struct detector
{
    Client *watcherClientPtr;

    useconds_t reportperiod;		/* frequency to generate reports at */
    int reportnum;
    string iface;
    int routeedgewidth;
    Color onehopcolor;
    Color nexthopcolor;

    string nexthoplayer;
    string onehoplayer;

    int duration;			  /* Time to run (in seconds) or 0 to run until broken */

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

} detector;

typedef struct DetectorInit
{
    useconds_t reportperiod;		/* frequency to generate reports at */
    string iface;
    int onehopfamily;
    Color onehopcolor;
    Color nexthopcolor;
    int mouthnum;
    int duration;			  /* Time to run (in seconds) or 0 to run until broken */
    int routeedgewidth;

    string serverName;

    string nexthoplayer;
    string onehoplayer;

	struct in_addr filterNetwork;
	struct in_addr filterMask;
	struct in_addr localhost;

} DetectorInit;

static void updateRoutes(detector *st, Route *list)
{
    TRACE_ENTER();
    Route *r,*tmpNextHop=NULL;
    Route *tmpOneHop=NULL;

    /*
     * 	for each edge in newlist,
     * 	   	if there is not an edge in oldList or tmpList to nexthop, add it, and add to tmpList
     */
    vector<MessagePtr> messages;
    for(r=list;r;r=r->next)
    {
        if (!st->iface.empty())
            if (st->iface != string(r->iface))    /* if we're checking interfaces, and this route is on the wrong one...  */
                continue;

#if 1
        LOG_DEBUG("nexthop inserting us -> " << r->nexthop);
#endif

        if ((r->nexthop!=0) && (routeSearchNext(tmpNextHop,r)==NULL))   /* if its multi-hop, and not on the next hop list */
        {
            EdgeMessagePtr em=EdgeMessagePtr(new EdgeMessage);
            em->node1=boost::asio::ip::address_v4(htonl(st->localhost.s_addr));
            em->node2=boost::asio::ip::address_v4(r->nexthop);
            em->edgeColor=st->nexthopcolor;
            em->expiration=st->reportperiod*1.5;
            em->width=st->routeedgewidth;
            em->layer=ROUTING_LAYER; // GTL st->nexthoplayer;
            em->addEdge=true;
            em->bidirectional=false;
            messages.push_back(em);

            routeInsert(&tmpNextHop,r);
        }

        if (r->nexthop==0)   /* if its a one-hop... */
        {
#if 1
            LOG_DEBUG("onehop inserting us -> " << r->dst);
#endif
            EdgeMessagePtr em=EdgeMessagePtr(new EdgeMessage);
            em->node1=boost::asio::ip::address_v4(htonl(st->localhost.s_addr));
            em->node2=boost::asio::ip::address_v4(r->dst);
            em->edgeColor=st->onehopcolor;
            em->expiration=st->reportperiod*1.5;
            em->width=st->routeedgewidth;
            em->layer=ROUTING_LAYER; // GTL st->onehoplayer;
            em->addEdge=true;
            em->bidirectional=false;
            messages.push_back(em);

            routeInsert(&tmpOneHop,r);
        }
    }
    if (!messages.empty())
        st->watcherClientPtr->sendMessages(messages);
    else
        LOG_DEBUG("No routes found so no messages sent!");

    routeFree(tmpNextHop);
    routeFree(tmpOneHop);

    TRACE_EXIT();
}

/* This is called regularly by the select loop (below)
 * It will create a message, and send it to this node's coordinator
 */
static void detectorSend(detector *st)
{
    TRACE_ENTER();

    Route *list;

    list=routeRead(st->filterNetwork.s_addr, st->filterMask.s_addr);

    long long int curtime;
    struct timeval tp;
    gettimeofday(&tp, NULL);
    curtime=(long long int)tp.tv_sec * 1000 + (long long int)tp.tv_usec/1000;

    LOG_DEBUG("node= " << st->localhost.s_addr << " time= " << curtime << " numroutes= " << routeNumber(list));

#ifdef DEBUG
    LOG_DEBUG("old:");
    routeDump(st->oldList);

    LOG_DEBUG("new:");
    routeDump(list);
#endif

    st->reportnum++;

    updateRoutes(st,list);

    routeFree(list);

    TRACE_EXIT();
}

static detector *detectorInit(DetectorInit *detinit)
{
    TRACE_ENTER();
    detector *st;

    st=new detector;
    st->iface="";

    st->watcherClientPtr=new Client(detinit->serverName);
    if(st->watcherClientPtr==NULL)
        return NULL;

    st->duration=detinit->duration;
    st->reportperiod=detinit->reportperiod;
    st->reportnum=0;
    st->iface=detinit->iface;

    st->onehoplayer=detinit->onehoplayer;
    st->onehopcolor=detinit->onehopcolor;

    st->nexthoplayer=detinit->nexthoplayer;
    st->nexthopcolor=st->nexthopcolor;

    st->routeedgewidth=detinit->routeedgewidth;

	st->filterNetwork.s_addr=detinit->filterNetwork.s_addr;
	st->filterMask.s_addr=detinit->filterMask.s_addr;
	st->localhost.s_addr=detinit->localhost.s_addr;

    TRACE_EXIT();
    return st;
}

/*
 * Wait around until we are ready to generate a message, then do it.
 */
static void selectLoop(detector *dt)
{
    TRACE_ENTER();

    time_t startTime=time(NULL);

    while(1)
    {
        usleep(dt->reportperiod*(useconds_t)1000.0);
        detectorSend(dt);

        if (dt->duration)
            if (time(NULL)-startTime>dt->duration)
                break;
    }

    dt->watcherClientPtr->wait();

    TRACE_EXIT();
}

int main(int argc, char *argv[])
{
    TRACE_ENTER();
    detector *dt;
    int ch;
    string logPropsFile("routeFeeder.log.properties");

    DetectorInit detinit;
    detinit.iface="";
    detinit.onehopcolor=Color::green;
    detinit.onehoplayer="One Hop Routing";
    detinit.nexthopcolor=Color::blue;
    detinit.nexthoplayer="Network Routing";
    detinit.reportperiod=2000;
    detinit.duration=0;
    detinit.routeedgewidth=15;

	detinit.filterNetwork.s_addr=0;
	detinit.filterMask.s_addr=0;
	detinit.localhost.s_addr=0;

    while ((ch = getopt(argc, argv, "m:n:h:o:x:t:e:b:i:d:p:w:l:?")) != -1)
        switch (ch)
        {
            case 'm': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterMask))
                      {
                          fprintf(stderr, "Error parsing filter mask: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'n': if(-1 == inet_pton(AF_INET, optarg, &detinit.filterNetwork))
                      {
                          fprintf(stderr, "Error parsing filter network: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'h': if(-1 == inet_pton(AF_INET, optarg, &detinit.localhost))
                      {
                          fprintf(stderr, "Error parsing localhost address: %s\n", optarg);
                          exit(EX_USAGE);
                      }
                      break;
            case 'o':
                      detinit.onehopcolor.fromString(optarg);
                      break;
            case 'x':
                      detinit.nexthopcolor.fromString(optarg);
                      break;
            case 't':
                      sscanf(optarg,"%d",&detinit.duration);
                      break;
            case 'e':
                      detinit.onehoplayer=string(optarg);
                      break;
            case 'b':
                      detinit.nexthoplayer=string(optarg);
                      break;
            case 'i':
                      detinit.iface=string(optarg);
                      break;
            case 'd':
                      detinit.serverName=string(optarg);
                      break;
            case 'p':
                      sscanf(optarg,"%d",&detinit.reportperiod);
                      break;
            case 'w':
                      sscanf(optarg, "%d", &detinit.routeedgewidth);
                      break;
            case 'l':
                      logPropsFile=string(optarg);
                      break;
            case '?':
            default:
                      fprintf(stderr,"routingdetector - poll the linux routing table, and draw the routes in the watcher\n"
                              "-d ipaddr/hostname - specify watcherd address to connect to (duck)\n"
                              "-h ipaddr - this host's address\n"
                              "-m netmask - the mask used to filter the routes (ex. 255.255.255.0)\n"
                              "-n network - the network used to filter the routes (ex. 192.168.1.0)\n"
                              "-p milliseconds - specify the period to poll and report\n"
                              "-i interface - display only routes through this ethernet interface (or any if unspecified)\n"
                              "-o color - onehop edge color\n"
                              "-e layer - onehop layer name\n"
                              "-x color - nexthop edge color\n"
                              "-b layer - nexthop layer name\n"
                              "-t seconds - Run for this long, then exit\n"
                              "-w width - make edges width pixels wide (default 15)\n"
                             );
                      exit(1);
                      break;
        }

    // init the logging system
    LOAD_LOG_PROPS(logPropsFile);
    LOG_INFO("Logger initialized from file \"" << logPropsFile << "\"");

	// check args, errors, etc before doing real work
	if(detinit.localhost.s_addr == 0)
    {
        fprintf(stderr, "localhost address cannot be blank\n");
        exit(EX_USAGE);
    }
	if(detinit.filterNetwork.s_addr == 0)
	{
        fprintf(stderr, "filter network cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.filterMask.s_addr == 0)
	{
        fprintf(stderr, "filter mask cannot be blank\n");
        exit(EX_USAGE);
	}
	if(detinit.serverName.empty())
	{
        fprintf(stderr, "watcherd hostname cannot be blank\n");
        exit(EX_USAGE);
	}

    dt=detectorInit(&detinit);

    if (dt==NULL)
    {
        fprintf(stderr,"detector init failed, probably could not connect to infrastructure demon.\n");
        exit(1);
    }
    printf("%s: starting\n",argv[0]);
    selectLoop(dt);

    TRACE_EXIT();
    return 0;
}
<|endoftext|>


<commit_before>#include "applications.h"
#include <QDir>

const int Applications::NameRole = Qt::UserRole + 1;
const int Applications::IconRole = Qt::UserRole + 2;
const int Applications::ExecRole = Qt::UserRole + 3;
const int Applications::TerminalRole = Qt::UserRole + 4;

Applications::Applications(QObject *parent) :
    QAbstractListModel(parent)
{
    connect(&m_parserThreadWatcher, SIGNAL(finished()), this, SLOT(parseFinished()));
    m_parserRunning = true;
    m_parserThread = QtConcurrent::run(this, &Applications::parseApplications);
    m_parserThreadWatcher.setFuture(m_parserThread);
}

Applications::~Applications()
{
    if (m_parserThread.isRunning())
        m_parserThread.cancel();
    qDeleteAll(this->m_internalData);
}

void Applications::parseApplications()
{
    this->m_files.append(this->readFolder(QDir::homePath() + APPLICATIONS_LOCAL_PATH));
    this->m_files.append(this->readFolder(APPLICATIONS_PATH));

    foreach(QString file, this->m_files)
    {
        DesktopFile* app = new DesktopFile(file);
        if (!app->noDisplay() && !app->terminal())
        {
            m_internalData.append(app);
        }
    }
    this->m_files.clear();
}

QStringList Applications::readFolder(QString folder)
{
    QDir dir(folder);
    QFileInfoList file_list = dir.entryInfoList(
                QStringList(APPLICATIONS_FILES), QDir::Files | QDir::Readable);

    QStringList files;
    foreach(QFileInfo file, file_list)
    {
        if (this->m_files.filter(file.fileName()).count() == 0)
        {
            files.append(file.absoluteFilePath());
        }
    }
    return files;
}

void Applications::add(DesktopFile *item)
{
    beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
    m_data.append(item);
    endInsertRows();
    emit countChanged(m_data.size());
}

void Applications::sort()
{
    std::sort(this->m_data.begin(), this->m_data.end(),
              [](const DesktopFile* left, const DesktopFile* right) -> bool
    {
        return QString::compare(left->name(),right->name(), Qt::CaseInsensitive) < 0;
    });
}

DesktopFile* Applications::get(int index) const
{
    return m_data.at(index);
}

void Applications::filter(QString search)
{
    if (m_parserRunning) return;
    beginRemoveRows(QModelIndex(), 0, m_data.size());
    m_data.clear();
    endRemoveRows();
    foreach(DesktopFile* file, m_internalData)
    {
        if(file->name().contains(search,Qt::CaseInsensitive)
                || file->comment().contains(search, Qt::CaseInsensitive)
                || file->exec().contains(search, Qt::CaseInsensitive))
        {
            this->add(file);
        }
    }
    this->sort();
}

int Applications::rowCount(const QModelIndex &) const
{
    return m_data.count();
}

QVariant Applications::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if (index.row() > (m_data.size()-1) )
        return QVariant();

    DesktopFile* obj = m_data.at(index.row());
    switch(role)
    {
        case Qt::DisplayRole:
        case NameRole:
            return QVariant::fromValue(obj->name());
        break;

        case IconRole:
            return QVariant::fromValue(obj->icon());

        case ExecRole:
            return QVariant::fromValue(obj->exec());

        case TerminalRole:
            return QVariant::fromValue(obj->terminal());

        default:
            return QVariant();
    }
}

QHash<int, QByteArray> Applications::roleNames() const
{
    QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
    roles.insert(NameRole, QByteArray("name"));
    roles.insert(IconRole, QByteArray("icon"));
    roles.insert(ExecRole, QByteArray("exec"));
    roles.insert(TerminalRole, QByteArray("terminal"));
    return roles;
}

void Applications::parseFinished()
{
    m_parserRunning = false;
    this->filter("");
    emit ready();
}
<commit_msg>Add debug message<commit_after>#include "applications.h"
#include <QDir>
#include <qdebug.h>

const int Applications::NameRole = Qt::UserRole + 1;
const int Applications::IconRole = Qt::UserRole + 2;
const int Applications::ExecRole = Qt::UserRole + 3;
const int Applications::TerminalRole = Qt::UserRole + 4;

Applications::Applications(QObject *parent) :
    QAbstractListModel(parent)
{
    connect(&m_parserThreadWatcher, SIGNAL(finished()), this, SLOT(parseFinished()));
    m_parserRunning = true;
    m_parserThread = QtConcurrent::run(this, &Applications::parseApplications);
    m_parserThreadWatcher.setFuture(m_parserThread);
}

Applications::~Applications()
{
    if (m_parserThread.isRunning())
        m_parserThread.cancel();
    qDeleteAll(this->m_internalData);
}

void Applications::parseApplications()
{
    this->m_files.append(this->readFolder(QDir::homePath() + APPLICATIONS_LOCAL_PATH));
    this->m_files.append(this->readFolder(APPLICATIONS_PATH));

    foreach(QString file, this->m_files)
    {
        DesktopFile* app = new DesktopFile(file);
        if (!app->noDisplay() && !app->terminal())
        {
            // qDebug() << "Adding application: " << app->name();
            m_internalData.append(app);
        }
    }
    this->m_files.clear();
}

QStringList Applications::readFolder(QString folder)
{
    QDir dir(folder);
    QFileInfoList file_list = dir.entryInfoList(
                QStringList(APPLICATIONS_FILES), QDir::Files | QDir::Readable);

    QStringList files;
    foreach(QFileInfo file, file_list)
    {
        if (this->m_files.filter(file.fileName()).count() == 0)
        {
            files.append(file.absoluteFilePath());
        }
    }
    return files;
}

void Applications::add(DesktopFile *item)
{
    beginInsertRows(QModelIndex(), m_data.size(), m_data.size());
    m_data.append(item);
    endInsertRows();
    emit countChanged(m_data.size());
}

void Applications::sort()
{
    std::sort(this->m_data.begin(), this->m_data.end(),
              [](const DesktopFile* left, const DesktopFile* right) -> bool
    {
        return QString::compare(left->name(),right->name(), Qt::CaseInsensitive) < 0;
    });
}

DesktopFile* Applications::get(int index) const
{
    return m_data.at(index);
}

void Applications::filter(QString search)
{
    if (m_parserRunning) return;
    beginRemoveRows(QModelIndex(), 0, m_data.size());
    m_data.clear();
    endRemoveRows();
    foreach(DesktopFile* file, m_internalData)
    {
        if(file->name().contains(search,Qt::CaseInsensitive)
                || file->comment().contains(search, Qt::CaseInsensitive)
                || file->exec().contains(search, Qt::CaseInsensitive))
        {
            this->add(file);
        }
    }
    this->sort();
}

int Applications::rowCount(const QModelIndex &) const
{
    return m_data.count();
}

QVariant Applications::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if (index.row() > (m_data.size()-1) )
        return QVariant();

    DesktopFile* obj = m_data.at(index.row());
    switch(role)
    {
        case Qt::DisplayRole:
        case NameRole:
            return QVariant::fromValue(obj->name());
        break;

        case IconRole:
            return QVariant::fromValue(obj->icon());

        case ExecRole:
            return QVariant::fromValue(obj->exec());

        case TerminalRole:
            return QVariant::fromValue(obj->terminal());

        default:
            return QVariant();
    }
}

QHash<int, QByteArray> Applications::roleNames() const
{
    QHash<int, QByteArray> roles = QAbstractListModel::roleNames();
    roles.insert(NameRole, QByteArray("name"));
    roles.insert(IconRole, QByteArray("icon"));
    roles.insert(ExecRole, QByteArray("exec"));
    roles.insert(TerminalRole, QByteArray("terminal"));
    return roles;
}

void Applications::parseFinished()
{
    m_parserRunning = false;
    this->filter("");
    emit ready();
}
<|endoftext|>


<commit_before>#ifndef ITER_DROPWHILE_H_
#define ITER_DROPWHILE_H_

#include "internal/iterbase.hpp"
#include "filter.hpp"

#include <utility>
#include <iterator>

namespace iter {
  namespace impl {
    template <typename FilterFunc, typename Container>
    class Dropper;

    using DropWhileFn = IterToolFnOptionalBindFirst<Dropper, BoolTester>;
  }
  constexpr impl::DropWhileFn dropwhile{};
}

template <typename FilterFunc, typename Container>
class iter::impl::Dropper {
 private:
  Container container;
  FilterFunc filter_func;

  friend DropWhileFn;

  Dropper(FilterFunc in_filter_func, Container&& in_container)
      : container(std::forward<Container>(in_container)),
        filter_func(in_filter_func) {}

 public:
  Dropper(Dropper&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag,
                       iterator_traits_deref<Container>> {
   private:
    using Holder = DerefHolder<iterator_deref<Container>>;
    iterator_type<Container> sub_iter;
    iterator_type<Container> sub_end;
    Holder item;
    FilterFunc* filter_func;

    void inc_sub_iter() {
      ++this->sub_iter;
      if (this->sub_iter != this->sub_end) {
        this->item.reset(*this->sub_iter);
      }
    }

    // skip all values for which the predicate is true
    void skip_passes() {
      while (this->sub_iter != this->sub_end
             && (*this->filter_func)(this->item.get())) {
        this->inc_sub_iter();
      }
    }

   public:
    Iterator(iterator_type<Container>&& iter, iterator_type<Container>&& end,
        FilterFunc& in_filter_func)
        : sub_iter{std::move(iter)},
          sub_end{std::move(end)},
          filter_func(&in_filter_func) {
      if (this->sub_iter != this->sub_end) {
        this->item.reset(*this->sub_iter);
      }
      this->skip_passes();
    }

    typename Holder::reference operator*() {
      return this->item.get();
    }

    typename Holder::pointer operator->() {
      return this->item.get_ptr();
    }

    Iterator& operator++() {
      this->inc_sub_iter();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return this->sub_iter != other.sub_iter;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::end(this->container),
        this->filter_func};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->container),
        this->filter_func};
  }
};

#endif
<commit_msg>Supports different begin and end in dropwhile<commit_after>#ifndef ITER_DROPWHILE_H_
#define ITER_DROPWHILE_H_

#include "internal/iterbase.hpp"
#include "internal/iterator_wrapper.hpp"
#include "filter.hpp"

#include <utility>
#include <iterator>

namespace iter {
  namespace impl {
    template <typename FilterFunc, typename Container>
    class Dropper;

    using DropWhileFn = IterToolFnOptionalBindFirst<Dropper, BoolTester>;
  }
  constexpr impl::DropWhileFn dropwhile{};
}

template <typename FilterFunc, typename Container>
class iter::impl::Dropper {
 private:
  Container container;
  FilterFunc filter_func;

  friend DropWhileFn;

  Dropper(FilterFunc in_filter_func, Container&& in_container)
      : container(std::forward<Container>(in_container)),
        filter_func(in_filter_func) {}

 public:
  Dropper(Dropper&&) = default;
  class Iterator : public std::iterator<std::input_iterator_tag,
                       iterator_traits_deref<Container>> {
   private:
    using Holder = DerefHolder<iterator_deref<Container>>;
    IteratorWrapper<Container> sub_iter;
    IteratorWrapper<Container> sub_end;
    Holder item;
    FilterFunc* filter_func;

    void inc_sub_iter() {
      ++this->sub_iter;
      if (this->sub_iter != this->sub_end) {
        this->item.reset(*this->sub_iter);
      }
    }

    // skip all values for which the predicate is true
    void skip_passes() {
      while (this->sub_iter != this->sub_end
             && (*this->filter_func)(this->item.get())) {
        this->inc_sub_iter();
      }
    }

   public:
    Iterator(IteratorWrapper<Container>&& iter, IteratorWrapper<Container>&& end,
        FilterFunc& in_filter_func)
        : sub_iter{std::move(iter)},
          sub_end{std::move(end)},
          filter_func(&in_filter_func) {
      if (this->sub_iter != this->sub_end) {
        this->item.reset(*this->sub_iter);
      }
      this->skip_passes();
    }

    typename Holder::reference operator*() {
      return this->item.get();
    }

    typename Holder::pointer operator->() {
      return this->item.get_ptr();
    }

    Iterator& operator++() {
      this->inc_sub_iter();
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return this->sub_iter != other.sub_iter;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::end(this->container),
        this->filter_func};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->container),
        this->filter_func};
  }
};

#endif
<|endoftext|>


<commit_before>#ifndef DROPWHILE__H__
#define DROPWHILE__H__

#include <iterbase.hpp>

#include <utility>

namespace iter {

    //Forward declarations of DropWhile and dropwhile
    template <typename FilterFunc, typename Container>
    class DropWhile;

    template <typename FilterFunc, typename Container>
    DropWhile<FilterFunc, Container> dropwhile(FilterFunc, Container &);

    template <typename FilterFunc, typename Container>
    class DropWhile : IterBase<Container> {
        private:
            Container & container;
            FilterFunc filter_func;

            friend DropWhile dropwhile<FilterFunc, Container>(
                    FilterFunc, Container &);

            using typename IterBase<Container>::contained_iter_type;

            using typename IterBase<Container>::contained_iter_ret;

            // Value constructor for use only in the dropwhile function
            DropWhile(FilterFunc filter_func, Container & container) :
                container(container),
                filter_func(filter_func)
            { }
            DropWhile () = delete;
            DropWhile & operator=(const DropWhile &) = delete;

        public:
            DropWhile(const DropWhile &) = default;
            class Iterator {
                private:
                    contained_iter_type sub_iter;
                    const contained_iter_type sub_end;
                    FilterFunc filter_func;

                    // skip all values for which the predicate is true
                    void skip_passes() {
                        while (this->sub_iter != this->sub_end
                                && this->filter_func(*this->sub_iter)) {
                            ++this->sub_iter;
                        }
                    }

                public:
                    Iterator (contained_iter_type iter,
                            contained_iter_type end,
                            FilterFunc filter_func) :
                        sub_iter(iter),
                        sub_end(end),
                        filter_func(filter_func)
                    {
                        this->skip_passes();
                    }

                    contained_iter_ret operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator & operator++() {
                        ++this->sub_iter;
                        return *this;
                    }

                    bool operator!=(const Iterator & other) const {
                        return this->sub_iter != other.sub_iter;
                    }
            };

            Iterator begin() const {
                return Iterator(
                        std::begin(this->container),
                        std::end(this->container),
                        this->filter_func);
            }

            Iterator end() const {
                return Iterator(
                        std::end(this->container),
                        std::end(this->container),
                        this->filter_func);
            }

    };

    // Helper function to instantiate a DropWhile
    template <typename FilterFunc, typename Container>
    DropWhile<FilterFunc, Container> dropwhile(
            FilterFunc filter_func, Container & container) {
        return DropWhile<FilterFunc, Container>(filter_func, container);
    }

}

#endif //ifndef DROPWHILE__H__
<commit_msg>Tweaks #includes<commit_after>#ifndef DROPWHILE__H__
#define DROPWHILE__H__

#include <iterbase.hpp>

#include <utility>
#include <iterator>

namespace iter {

    //Forward declarations of DropWhile and dropwhile
    template <typename FilterFunc, typename Container>
    class DropWhile;

    template <typename FilterFunc, typename Container>
    DropWhile<FilterFunc, Container> dropwhile(FilterFunc, Container &);

    template <typename FilterFunc, typename Container>
    class DropWhile : IterBase<Container> {
        private:
            Container & container;
            FilterFunc filter_func;

            friend DropWhile dropwhile<FilterFunc, Container>(
                    FilterFunc, Container &);

            using typename IterBase<Container>::contained_iter_type;

            using typename IterBase<Container>::contained_iter_ret;

            // Value constructor for use only in the dropwhile function
            DropWhile(FilterFunc filter_func, Container & container) :
                container(container),
                filter_func(filter_func)
            { }
            DropWhile () = delete;
            DropWhile & operator=(const DropWhile &) = delete;

        public:
            DropWhile(const DropWhile &) = default;
            class Iterator {
                private:
                    contained_iter_type sub_iter;
                    const contained_iter_type sub_end;
                    FilterFunc filter_func;

                    // skip all values for which the predicate is true
                    void skip_passes() {
                        while (this->sub_iter != this->sub_end
                                && this->filter_func(*this->sub_iter)) {
                            ++this->sub_iter;
                        }
                    }

                public:
                    Iterator (contained_iter_type iter,
                            contained_iter_type end,
                            FilterFunc filter_func) :
                        sub_iter(iter),
                        sub_end(end),
                        filter_func(filter_func)
                    {
                        this->skip_passes();
                    }

                    contained_iter_ret operator*() const {
                        return *this->sub_iter;
                    }

                    Iterator & operator++() {
                        ++this->sub_iter;
                        return *this;
                    }

                    bool operator!=(const Iterator & other) const {
                        return this->sub_iter != other.sub_iter;
                    }
            };

            Iterator begin() const {
                return Iterator(
                        std::begin(this->container),
                        std::end(this->container),
                        this->filter_func);
            }

            Iterator end() const {
                return Iterator(
                        std::end(this->container),
                        std::end(this->container),
                        this->filter_func);
            }

    };

    // Helper function to instantiate a DropWhile
    template <typename FilterFunc, typename Container>
    DropWhile<FilterFunc, Container> dropwhile(
            FilterFunc filter_func, Container & container) {
        return DropWhile<FilterFunc, Container>(filter_func, container);
    }

}

#endif //ifndef DROPWHILE__H__
<|endoftext|>


<commit_before>//
// Copyright 2011-2015 Jeff Bush
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include <iostream>
#include <stdlib.h>
#include "Vsoc_tb.h"
#include "verilated.h"
#include "verilated_vpi.h"
#if VM_TRACE
#include <verilated_vcd_c.h>
#endif
using namespace std;

//
// This is compiled into the verilog simulator executable along with the
// source files generated by Verilator. It initializes and runs the simulation
// loop for the full processor.
//

namespace
{
vluint64_t currentTime = 0;
}

// Called whenever the $time variable is accessed.
double sc_time_stamp()
{
    return currentTime;
}

int main(int argc, char **argv, char **env)
{
    Verilated::commandArgs(argc, argv);
    Verilated::debug(0);

    // Default to randomizing contents of memory before the start of
    // simulation. This flag can disable it.
    const char *arg = Verilated::commandArgsPlusMatch("randomize=");
    if (arg[0] == '\0' || atoi(arg + 11) != 0)
    {
        // Initialize random seed.
        long randomSeed;
        arg = Verilated::commandArgsPlusMatch("randseed=");
        if (arg[0] != '\0')
            randomSeed = atol(arg + 10);
        else
        {
            time_t t1;
            time(&t1);
            randomSeed = (long) t1;
        }

        srand48(randomSeed);
        VL_PRINTF("Random seed is %li\n", randomSeed);
        Verilated::randReset(2);
    }
    else
        Verilated::randReset(0);

    Vsoc_tb* testbench = new Vsoc_tb;

    // As with real hardware, reset is a bit tricky.
    // - Most assertions will fail before the design has been reset.
    // - Assertions are not tested while reset is asserted.
    // BUT:
    // - Many blocks require a positive edge on reset to trigger
    //   (not all, any block that also triggers on clock will synchronously
    //   reset if it is asserted).
    //
    // This is a bit of a hack, set the 'last' state of reset to zero and reset to one.
    // This will cause a positive edge event on the next eval() that will trigger
    // all reset blocks. Reset will be deasserted in the main loop below.
    //
    testbench->__Vclklast__TOP__reset = 0;
    testbench->reset = 1;
    testbench->clk = 0;
    testbench->eval();

#if VM_TRACE // If verilator was invoked with --trace
    Verilated::traceEverOn(true);
    VL_PRINTF("Writing waveform to trace.vcd\n");
    VerilatedVcdC* tfp = new VerilatedVcdC;
    testbench->trace(tfp, 99);
    tfp->open("trace.vcd");
#endif

    while (!Verilated::gotFinish())
    {
        // Allow it to run for a few clock cycles with reset asserted. This allows
        // flops that are not reset to settle on valid values so assertions don't trip.
        if (currentTime == 4)
            testbench->reset = 0;

        testbench->clk = !testbench->clk;
        testbench->eval();
#if VM_TRACE
        tfp->dump(currentTime); // Create waveform trace for this timestamp
#endif

        currentTime++;
    }

#if VM_TRACE
    tfp->close();
#endif

    testbench->final();
    delete testbench;

    return 0;
}
<commit_msg>A few minor Verilator main loop changes<commit_after>//
// Copyright 2011-2015 Jeff Bush
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include <iostream>
#include <cstdlib>
#include "Vsoc_tb.h"
#include "verilated.h"
#include "verilated_vpi.h"
#if VM_TRACE
#include <verilated_vcd_c.h>
#endif

//
// This is compiled into the verilog simulator executable along with the
// source files generated by Verilator. It initializes and runs the simulation
// loop for the full processor.
//

namespace
{
vluint64_t currentTime = 0;
}

// Called whenever the $time variable is accessed.
double sc_time_stamp()
{
    return currentTime;
}

int main(int argc, char **argv, char **env)
{
    Verilated::commandArgs(argc, argv);
    Verilated::debug(0);

    // Default to randomizing contents of memory before the start of
    // simulation. This flag can disable it.
    const char *arg = Verilated::commandArgsPlusMatch("randomize=");
    if (arg[0] == '\0' || atoi(arg + 11) != 0)
    {
        // Initialize random seed.
        long randomSeed;
        arg = Verilated::commandArgsPlusMatch("randseed=");
        if (arg[0] != '\0')
            randomSeed = atol(arg + 10);
        else
        {
            time_t t1;
            time(&t1);
            randomSeed = (long) t1;
        }

        srand48(randomSeed);
        VL_PRINTF("Random seed is %li\n", randomSeed);
        Verilated::randReset(2);
    }
    else
        Verilated::randReset(0);

    Vsoc_tb* testbench = new Vsoc_tb;

    // As with real hardware, reset is a bit tricky.
    // - Most assertions will fail before the design has been reset.
    // - Assertions are not tested while reset is asserted.
    // BUT:
    // - Many blocks require a positive edge on reset to trigger
    //   (not all, any block that also triggers on clock will synchronously
    //   reset if it is asserted).
    //
    // This is a bit of a hack, set the 'last' state of reset to zero and reset to one.
    // This will cause a positive edge event on the next eval() that will trigger
    // all reset blocks. Reset will be deasserted in the main loop below.
    testbench->__Vclklast__TOP__reset = 0;
    testbench->reset = 1;
    testbench->clk = 0;
    testbench->eval();

#if VM_TRACE // If verilator was invoked with --trace
    Verilated::traceEverOn(true);
    VL_PRINTF("Writing waveform to trace.vcd\n");
    VerilatedVcdC* tfp = new VerilatedVcdC;
    testbench->trace(tfp, 99);
    tfp->open("trace.vcd");
#endif

    while (!Verilated::gotFinish())
    {
        // Run for a few clock cycles with reset asserted. This allows flops
        // that are not reset to settle on valid values so assertions don't
        // trip.
        if (currentTime == 4)
            testbench->reset = 0;

        testbench->clk = !testbench->clk;
        testbench->eval();
#if VM_TRACE
        tfp->dump(currentTime); // Create waveform trace for this timestamp
#endif

        currentTime++;
    }

    testbench->final();

#if VM_TRACE
    tfp->close();
#endif

    delete testbench;

    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: verbosetrace.hxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: thb $ $Date: 2004-03-18 10:38:26 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CANVAS_VERBOSETRACE_HXX
#define _CANVAS_VERBOSETRACE_HXX

#ifdef VERBOSE
/// Wrap OSL_TRACE with a verbosity switch
#define VERBOSE_TRACE     OSL_TRACE
#else
#define VERBOSE_TRACE     1 ? ((void)0) : OSL_TRACE
#endif

#endif /* _CANVAS_VERBOSETRACE_HXX */
<commit_msg>INTEGRATION: CWS presentationengine01 (1.2.2); FILE MERGED 2004/05/27 14:36:52 thb 1.2.2.2: #110496# verbose tracing is now guarded also with DBG_UTIL. Unified verbose trace output between directx and VCL canvas 2004/04/05 15:57:53 thb 1.2.2.1: Resync with canvas01 changes<commit_after>/*************************************************************************
 *
 *  $RCSfile: verbosetrace.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-11-26 17:03:28 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CANVAS_VERBOSETRACE_HXX
#define _CANVAS_VERBOSETRACE_HXX

#if defined(VERBOSE) && defined(DBG_UTIL)
/// Wrap OSL_TRACE with a verbosity switch
#define VERBOSE_TRACE     OSL_TRACE
#else
#define VERBOSE_TRACE     1 ? ((void)0) : OSL_TRACE
#endif

#endif /* _CANVAS_VERBOSETRACE_HXX */
<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: map.cpp 17 2005-03-08 23:58:43Z pavlenko $,

#include <mapnik/style.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/filter_featureset.hpp>
#include <mapnik/hit_test_filter.hpp>
#include <mapnik/map.hpp>

namespace mapnik
{
    Map::Map()
        : width_(400),
          height_(400),
          srs_("+proj=latlong +datum=WGS84") {}

    Map::Map(int width,int height, std::string const& srs)
        : width_(width),
          height_(height),
          srs_(srs),
          background_(Color(255,255,255)) {}

    Map::Map(const Map& rhs)
        : width_(rhs.width_),
          height_(rhs.height_),
          srs_(rhs.srs_),
          background_(rhs.background_),
          styles_(rhs.styles_),
          layers_(rhs.layers_),
          currentExtent_(rhs.currentExtent_) {}

    Map& Map::operator=(const Map& rhs)
    {
        if (this==&rhs) return *this;
        width_=rhs.width_;
        height_=rhs.height_;
        srs_=rhs.srs_;
        background_=rhs.background_;
        styles_=rhs.styles_;
        layers_=rhs.layers_;
        return *this;
    }

    Map::style_iterator  Map::begin_styles() const
    {
        return styles_.begin();
    }
    Map::style_iterator  Map::end_styles() const
    {
        return styles_.end();
    }

    bool Map::insert_style(std::string const& name,feature_type_style const& style)
    {
        return styles_.insert(make_pair(name,style)).second;
    }

    void Map::remove_style(std::string const& name)
    {
        styles_.erase(name);
    }

    feature_type_style const& Map::find_style(std::string const& name) const
    {
        std::map<std::string,feature_type_style>::const_iterator itr = styles_.find(name);
        if (itr!=styles_.end())
            return itr->second;
        static feature_type_style default_style;
        return default_style;
    }

    size_t Map::layerCount() const
    {
        return layers_.size();
    }

    void Map::addLayer(const Layer& l)
    {
        layers_.push_back(l);
    }
    void Map::removeLayer(size_t index)
    {
        layers_.erase(layers_.begin()+index);
    }

    void Map::remove_all()
    {
        layers_.clear();
        styles_.clear();
    }

    const Layer& Map::getLayer(size_t index) const
    {
        return layers_[index];
    }

    Layer& Map::getLayer(size_t index)
    {
        return layers_[index];
    }

    std::vector<Layer> const& Map::layers() const
    {
        return layers_;
    }

    std::vector<Layer> & Map::layers()
    {
        return layers_;
    }

    unsigned Map::getWidth() const
    {
        return width_;
    }

    unsigned Map::getHeight() const
    {
        return height_;
    }

    void Map::setWidth(unsigned width)
    {
        if (width >= MIN_MAPSIZE && width <= MAX_MAPSIZE)
        {
            width_=width;
            fixAspectRatio();
        }
    }

    void Map::setHeight(unsigned height)
    {
        if (height >= MIN_MAPSIZE && height <= MAX_MAPSIZE)
        {
            height_=height;
            fixAspectRatio();
        }
    }

    void Map::resize(unsigned width,unsigned height)
    {
        if (width >= MIN_MAPSIZE && width <= MAX_MAPSIZE &&
            height >= MIN_MAPSIZE && height <= MAX_MAPSIZE)
        {
            width_=width;
            height_=height;
            fixAspectRatio();
        }
    }

    std::string const&  Map::srs() const
    {
        return srs_;
    }

    void Map::set_srs(std::string const& srs)
    {
        srs_ = srs;
    }

    void Map::setBackground(const Color& c)
    {
        background_=c;
    }

    const Color& Map::getBackground() const
    {
        return background_;
    }

    void Map::zoom(double factor)
    {
        coord2d center = currentExtent_.center();
        double w = factor * currentExtent_.width();
        double h = factor * currentExtent_.height();
        currentExtent_ = Envelope<double>(center.x - 0.5 * w,
                                          center.y - 0.5 * h,
                                          center.x + 0.5 * w,
                                          center.y + 0.5 * h);
        fixAspectRatio();
    }

    void Map::zoom_all()
    {
        try
        {
            projection proj0(srs_);
            Envelope<double> ext;
            bool first = true;
            std::vector<Layer>::const_iterator itr = layers_.begin();
            std::vector<Layer>::const_iterator end = layers_.end();
            while (itr != end)
            {
                std::string const& layer_srs = itr->srs();
                projection proj1(layer_srs);
                proj_transform prj_trans(proj0,proj1);

                Envelope<double> layerExt = itr->envelope();
                double x0 = layerExt.minx();
                double y0 = layerExt.miny();
                double z0 = 0.0;
                double x1 = layerExt.maxx();
                double y1 = layerExt.maxy();
                double z1 = 0.0;
                prj_trans.backward(x0,y0,z0);
                prj_trans.backward(x1,y1,z1);

                Envelope<double> layerExt2(x0,y0,x1,y1);
#ifdef MAPNIK_DEBUG
                std::clog << " layer1 - > " << layerExt << "\n";
                std::clog << " layer2 - > " << layerExt2 << "\n";
#endif
                if (first)
                {
                    ext = layerExt2;
                    first = false;
                }
                else
                {
                    ext.expand_to_include(layerExt2);
                }
                ++itr;
            }
            zoomToBox(ext);
        }
        catch (proj_init_error & ex)
        {
            std::clog << ex.what() << '\n';
        }
    }

    void Map::zoomToBox(const Envelope<double> &box)
    {
        currentExtent_=box;
        fixAspectRatio();
    }

    void Map::fixAspectRatio()
    {
        double ratio1 = (double) width_ / (double) height_;
        double ratio2 = currentExtent_.width() / currentExtent_.height();

        if (ratio2 > ratio1)
        {
            currentExtent_.height(currentExtent_.width() / ratio1);
        }
        else if (ratio2 < ratio1)
        {
            currentExtent_.width(currentExtent_.height() * ratio1);
        }
    }

    const Envelope<double>& Map::getCurrentExtent() const
    {
        return currentExtent_;
    }

    void Map::pan(int x,int y)
    {
        int dx = x - int(0.5 * width_);
        int dy = int(0.5 * height_) - y;
        double s = width_/currentExtent_.width();
        double minx  = currentExtent_.minx() + dx/s;
        double maxx  = currentExtent_.maxx() + dx/s;
        double miny  = currentExtent_.miny() + dy/s;
        double maxy  = currentExtent_.maxy() + dy/s;
        currentExtent_.init(minx,miny,maxx,maxy);
    }

    void Map::pan_and_zoom(int x,int y,double factor)
    {
        pan(x,y);
        zoom(factor);
    }

    double Map::scale() const
    {
        if (width_>0)
            return currentExtent_.width()/width_;
        return currentExtent_.width();
    }

    CoordTransform Map::view_transform() const
    {
        return CoordTransform(width_,height_,currentExtent_);
    }

    featureset_ptr Map::query_point(unsigned index, double lat, double lon) const
    {
        if ( index< layers_.size())
        {
            mapnik::Layer const& layer = layers_[index];
            try
            {
                double x = lon;
                double y = lat;
                double z = 0;
                mapnik::projection dest(srs_);
                dest.forward(x,y);
                mapnik::projection source(layer.srs());
                proj_transform prj_trans(source,dest);
                prj_trans.backward(x,y,z);

                double minx = currentExtent_.minx();
                double miny = currentExtent_.miny();
                double maxx = currentExtent_.maxx();
                double maxy = currentExtent_.maxy();

                prj_trans.backward(minx,miny,z);
                prj_trans.backward(maxx,maxy,z);
                double tol = (maxx - minx) / width_ * 3;
                mapnik::datasource_ptr ds = layer.datasource();
                if (ds)
                {
#ifdef MAPNIK_DEBUG
                    std::clog << " query at point tol = " << tol << " (" << x << "," << y << ")\n";
#endif
                    featureset_ptr fs(new filter_featureset<hit_test_filter>(ds->features_at_point(mapnik::coord2d(x,y)),
                                                                             hit_test_filter(x,y,tol)));
                    return fs;
                }
            }
            catch (...)
            {
#ifdef MAPNIK_DEBUG
                std::clog << "exception caught in \"query_map_point\"\n";
#endif
            }
        }
        return featureset_ptr();
    }

    featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
    {
        if ( index< layers_.size())
        {
            mapnik::Layer const& layer = layers_[index];
            CoordTransform tr = view_transform();
            tr.backward(&x,&y);

            try
            {
                mapnik::projection dest(srs_);
                mapnik::projection source(layer.srs());
                proj_transform prj_trans(source,dest);
                double z = 0;
                prj_trans.backward(x,y,z);

                double minx = currentExtent_.minx();
                double miny = currentExtent_.miny();
                double maxx = currentExtent_.maxx();
                double maxy = currentExtent_.maxy();

                prj_trans.backward(minx,miny,z);
                prj_trans.backward(maxx,maxy,z);
                double tol = (maxx - minx) / width_ * 3;
                mapnik::datasource_ptr ds = layer.datasource();
                if (ds)
                {
#ifdef MAPNIK_DEBUG
                    std::clog << " query at point tol = " << tol << " (" << x << "," << y << ")\n";
#endif

                    featureset_ptr fs(new filter_featureset<hit_test_filter>(ds->features_at_point(mapnik::coord2d(x,y)),
                                                                             hit_test_filter(x,y,tol)));
                    return fs;
                }
            }
            catch (...)
            {
#ifdef MAPNIK_DEBUG
                std::clog << "exception caught in \"query_map_point\"\n";
#endif
            }
        }
        return featureset_ptr();
    }

    Map::~Map() {}
}
<commit_msg>check if featureset is valid before passing to filter_featureset<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id: map.cpp 17 2005-03-08 23:58:43Z pavlenko $,

#include <mapnik/style.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/filter_featureset.hpp>
#include <mapnik/hit_test_filter.hpp>
#include <mapnik/map.hpp>

namespace mapnik
{
    Map::Map()
        : width_(400),
          height_(400),
          srs_("+proj=latlong +datum=WGS84") {}

    Map::Map(int width,int height, std::string const& srs)
        : width_(width),
          height_(height),
          srs_(srs),
          background_(Color(255,255,255)) {}

    Map::Map(const Map& rhs)
        : width_(rhs.width_),
          height_(rhs.height_),
          srs_(rhs.srs_),
          background_(rhs.background_),
          styles_(rhs.styles_),
          layers_(rhs.layers_),
          currentExtent_(rhs.currentExtent_) {}

    Map& Map::operator=(const Map& rhs)
    {
        if (this==&rhs) return *this;
        width_=rhs.width_;
        height_=rhs.height_;
        srs_=rhs.srs_;
        background_=rhs.background_;
        styles_=rhs.styles_;
        layers_=rhs.layers_;
        return *this;
    }

    Map::style_iterator  Map::begin_styles() const
    {
        return styles_.begin();
    }
    Map::style_iterator  Map::end_styles() const
    {
        return styles_.end();
    }

    bool Map::insert_style(std::string const& name,feature_type_style const& style)
    {
        return styles_.insert(make_pair(name,style)).second;
    }

    void Map::remove_style(std::string const& name)
    {
        styles_.erase(name);
    }

    feature_type_style const& Map::find_style(std::string const& name) const
    {
        std::map<std::string,feature_type_style>::const_iterator itr = styles_.find(name);
        if (itr!=styles_.end())
            return itr->second;
        static feature_type_style default_style;
        return default_style;
    }

    size_t Map::layerCount() const
    {
        return layers_.size();
    }

    void Map::addLayer(const Layer& l)
    {
        layers_.push_back(l);
    }
    void Map::removeLayer(size_t index)
    {
        layers_.erase(layers_.begin()+index);
    }

    void Map::remove_all()
    {
        layers_.clear();
        styles_.clear();
    }

    const Layer& Map::getLayer(size_t index) const
    {
        return layers_[index];
    }

    Layer& Map::getLayer(size_t index)
    {
        return layers_[index];
    }

    std::vector<Layer> const& Map::layers() const
    {
        return layers_;
    }

    std::vector<Layer> & Map::layers()
    {
        return layers_;
    }

    unsigned Map::getWidth() const
    {
        return width_;
    }

    unsigned Map::getHeight() const
    {
        return height_;
    }

    void Map::setWidth(unsigned width)
    {
        if (width >= MIN_MAPSIZE && width <= MAX_MAPSIZE)
        {
            width_=width;
            fixAspectRatio();
        }
    }

    void Map::setHeight(unsigned height)
    {
        if (height >= MIN_MAPSIZE && height <= MAX_MAPSIZE)
        {
            height_=height;
            fixAspectRatio();
        }
    }

    void Map::resize(unsigned width,unsigned height)
    {
        if (width >= MIN_MAPSIZE && width <= MAX_MAPSIZE &&
            height >= MIN_MAPSIZE && height <= MAX_MAPSIZE)
        {
            width_=width;
            height_=height;
            fixAspectRatio();
        }
    }

    std::string const&  Map::srs() const
    {
        return srs_;
    }

    void Map::set_srs(std::string const& srs)
    {
        srs_ = srs;
    }

    void Map::setBackground(const Color& c)
    {
        background_=c;
    }

    const Color& Map::getBackground() const
    {
        return background_;
    }

    void Map::zoom(double factor)
    {
        coord2d center = currentExtent_.center();
        double w = factor * currentExtent_.width();
        double h = factor * currentExtent_.height();
        currentExtent_ = Envelope<double>(center.x - 0.5 * w,
                                          center.y - 0.5 * h,
                                          center.x + 0.5 * w,
                                          center.y + 0.5 * h);
        fixAspectRatio();
    }

    void Map::zoom_all()
    {
        try
        {
            projection proj0(srs_);
            Envelope<double> ext;
            bool first = true;
            std::vector<Layer>::const_iterator itr = layers_.begin();
            std::vector<Layer>::const_iterator end = layers_.end();
            while (itr != end)
            {
                std::string const& layer_srs = itr->srs();
                projection proj1(layer_srs);
                proj_transform prj_trans(proj0,proj1);

                Envelope<double> layerExt = itr->envelope();
                double x0 = layerExt.minx();
                double y0 = layerExt.miny();
                double z0 = 0.0;
                double x1 = layerExt.maxx();
                double y1 = layerExt.maxy();
                double z1 = 0.0;
                prj_trans.backward(x0,y0,z0);
                prj_trans.backward(x1,y1,z1);

                Envelope<double> layerExt2(x0,y0,x1,y1);
#ifdef MAPNIK_DEBUG
                std::clog << " layer1 - > " << layerExt << "\n";
                std::clog << " layer2 - > " << layerExt2 << "\n";
#endif
                if (first)
                {
                    ext = layerExt2;
                    first = false;
                }
                else
                {
                    ext.expand_to_include(layerExt2);
                }
                ++itr;
            }
            zoomToBox(ext);
        }
        catch (proj_init_error & ex)
        {
            std::clog << ex.what() << '\n';
        }
    }

    void Map::zoomToBox(const Envelope<double> &box)
    {
        currentExtent_=box;
        fixAspectRatio();
    }

    void Map::fixAspectRatio()
    {
        double ratio1 = (double) width_ / (double) height_;
        double ratio2 = currentExtent_.width() / currentExtent_.height();

        if (ratio2 > ratio1)
        {
            currentExtent_.height(currentExtent_.width() / ratio1);
        }
        else if (ratio2 < ratio1)
        {
            currentExtent_.width(currentExtent_.height() * ratio1);
        }
    }

    const Envelope<double>& Map::getCurrentExtent() const
    {
        return currentExtent_;
    }

    void Map::pan(int x,int y)
    {
        int dx = x - int(0.5 * width_);
        int dy = int(0.5 * height_) - y;
        double s = width_/currentExtent_.width();
        double minx  = currentExtent_.minx() + dx/s;
        double maxx  = currentExtent_.maxx() + dx/s;
        double miny  = currentExtent_.miny() + dy/s;
        double maxy  = currentExtent_.maxy() + dy/s;
        currentExtent_.init(minx,miny,maxx,maxy);
    }

    void Map::pan_and_zoom(int x,int y,double factor)
    {
        pan(x,y);
        zoom(factor);
    }

    double Map::scale() const
    {
        if (width_>0)
            return currentExtent_.width()/width_;
        return currentExtent_.width();
    }

    CoordTransform Map::view_transform() const
    {
        return CoordTransform(width_,height_,currentExtent_);
    }

    featureset_ptr Map::query_point(unsigned index, double lat, double lon) const
    {
        if ( index< layers_.size())
        {
            mapnik::Layer const& layer = layers_[index];
            try
            {
                double x = lon;
                double y = lat;
                double z = 0;
                mapnik::projection dest(srs_);
                dest.forward(x,y);
                mapnik::projection source(layer.srs());
                proj_transform prj_trans(source,dest);
                prj_trans.backward(x,y,z);

                double minx = currentExtent_.minx();
                double miny = currentExtent_.miny();
                double maxx = currentExtent_.maxx();
                double maxy = currentExtent_.maxy();

                prj_trans.backward(minx,miny,z);
                prj_trans.backward(maxx,maxy,z);
                double tol = (maxx - minx) / width_ * 3;
                mapnik::datasource_ptr ds = layer.datasource();
                if (ds)
                {
#ifdef MAPNIK_DEBUG
                    std::clog << " query at point tol = " << tol << " (" << x << "," << y << ")\n";
#endif
                    featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
                    if (fs)
                        return featureset_ptr(new filter_featureset<hit_test_filter>(fs,hit_test_filter(x,y,tol)));
                }
            }
            catch (...)
            {
#ifdef MAPNIK_DEBUG
                std::clog << "exception caught in \"query_map_point\"\n";
#endif
            }
        }
        return featureset_ptr();
    }

    featureset_ptr Map::query_map_point(unsigned index, double x, double y) const
    {
        if ( index< layers_.size())
        {
            mapnik::Layer const& layer = layers_[index];
            CoordTransform tr = view_transform();
            tr.backward(&x,&y);

            try
            {
                mapnik::projection dest(srs_);
                mapnik::projection source(layer.srs());
                proj_transform prj_trans(source,dest);
                double z = 0;
                prj_trans.backward(x,y,z);

                double minx = currentExtent_.minx();
                double miny = currentExtent_.miny();
                double maxx = currentExtent_.maxx();
                double maxy = currentExtent_.maxy();

                prj_trans.backward(minx,miny,z);
                prj_trans.backward(maxx,maxy,z);
                double tol = (maxx - minx) / width_ * 3;
                mapnik::datasource_ptr ds = layer.datasource();
                if (ds)
                {
#ifdef MAPNIK_DEBUG
                    std::clog << " query at point tol = " << tol << " (" << x << "," << y << ")\n";
#endif
                    featureset_ptr fs = ds->features_at_point(mapnik::coord2d(x,y));
                    if (fs)
                        return featureset_ptr(new filter_featureset<hit_test_filter>(fs,hit_test_filter(x,y,tol)));
                }
            }
            catch (...)
            {
#ifdef MAPNIK_DEBUG
                std::clog << "exception caught in \"query_map_point\"\n";
#endif
            }
        }
        return featureset_ptr();
    }

    Map::~Map() {}
}
<|endoftext|>