<commit_before>//
// Copyright (C) 2004-2006 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2004-2006 Pingtel Corp.  All rights reserved.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// SYSTEM INCLUDES

#if defined(_VXWORKS)
#   include <taskLib.h>
#   include <netinet/in.h>
#endif

#include <utl/UtlHashBagIterator.h>
#include <net/SipLine.h>
#include <net/Url.h>
#include <net/SipLineCredentials.h>
#include <os/OsConfigDb.h>
#include <os/OsRWMutex.h>
#include <os/OsReadLock.h>
#include <os/OsWriteLock.h>
#include <os/OsDateTime.h>
#include <os/OsSysLog.h>
#include <net/NetMd5Codec.h>

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// Copy constructor
SipLine::SipLine(const SipLine& rSipLine)
{
   mIsVisible = rSipLine.mIsVisible ;
   mIdentity = rSipLine.mIdentity ;
   mUserEnteredUrl = rSipLine.mUserEnteredUrl;
   mUser = rSipLine.mUser ;
   mCurrentState = rSipLine.mCurrentState ;
   mIsAutoEnabled = rSipLine.mIsAutoEnabled ;
   mIsUsingCallHandling = rSipLine.mIsUsingCallHandling;
   mCanonicalUrl = rSipLine.mCanonicalUrl;
   mLineId = rSipLine.mLineId;
   mPreferredContactUri = rSipLine.mPreferredContactUri ;
   meContactType = rSipLine.meContactType;

   copyCredentials(rSipLine);

}

SipLine& SipLine::operator=(const SipLine& rSipLine)
{
   if (this == &rSipLine)            // handle the assignment to self case
      return *this;
   else
   {
      mIsVisible = rSipLine.mIsVisible ;
      mIdentity = rSipLine.mIdentity ;
      mUserEnteredUrl = rSipLine.mUserEnteredUrl;
      mCanonicalUrl = rSipLine.mCanonicalUrl;
      mUser = rSipLine.mUser ;
      mCurrentState = rSipLine.mCurrentState ;
      mIsAutoEnabled = rSipLine.mIsAutoEnabled ;
      mIsUsingCallHandling = rSipLine.mIsUsingCallHandling;
      mLineId = rSipLine.mLineId;
      mPreferredContactUri = rSipLine.mPreferredContactUri ;
      meContactType = rSipLine.meContactType;
      copyCredentials(rSipLine);
   }
   return *this;
}
//deep copy of credentials
void SipLine::copyCredentials(const SipLine &rSipLine)
{
   UtlString Realm;
   UtlString UserID;
   UtlString Type;
   UtlString Password;

   if(!mCredentials.isEmpty())
   {
      mCredentials.destroyAll();
   }
   if (! rSipLine.mCredentials.isEmpty())
   {
        UtlHashBagIterator observerIterator(const_cast<UtlHashBag&> (rSipLine.mCredentials));
        SipLineCredentials* credential = NULL;
        do
        {
            credential = (SipLineCredentials*) observerIterator();
            if ( credential)
            {
                credential->getRealm(&Realm);
                credential->getUserId(&UserID);
                credential->getType(&Type);
                credential->getPasswordToken(&Password);
                addCredentials(Realm , UserID , Password , Type);
            }
        }
        while(credential != NULL) ;
   }
}

SipLine::SipLine(Url userEnteredUrl,
                 Url identityUri,
                 UtlString user,
                 UtlBoolean visible,
                 int state,
                 UtlBoolean isAutoEnabled,
                 UtlBoolean useCallHandling)
{
   if (user.isNull())
   {
      mUser = userEnteredUrl.toString();
   }
   else
   {
      mUser = user;
   }

   mIsVisible = visible;
   mCurrentState = state;
   mIsAutoEnabled = isAutoEnabled;
   mIsUsingCallHandling = useCallHandling;
   mUserEnteredUrl = userEnteredUrl;
   meContactType = LINE_CONTACT_NAT_MAPPED ;
   if (identityUri.toString().isNull())
   {
      //then get uri from user entered url ...uri is complete in it
      UtlString uri;
      mUserEnteredUrl.getUri(uri);
      mIdentity = Url(uri);
   }
   else
   {
      mIdentity = identityUri;
   }

   //construct a complete url from identity and userEntered Url.
   mCanonicalUrl = mUserEnteredUrl;
   UtlString address;
   mUserEnteredUrl.getHostAddress(address);
   if (address.isNull())
   {
      UtlString identityHost;
      mIdentity.getHostAddress(identityHost);
      int identityPort = mIdentity.getHostPort();
      mCanonicalUrl.setHostAddress(identityHost);
      mCanonicalUrl.setHostPort(identityPort);
   }
   // create new Line Id for this line
   generateLineID(mLineId);
}

SipLine::~SipLine()
{
    mCredentials.destroyAll();
}

UtlString& SipLine::getLineId()
{
   return mLineId;
}

UtlBoolean SipLine::isDeviceLine()
{
    return (getUser().compareTo("Device", UtlString::ignoreCase) == 0) ;
}

int SipLine::getState()
{
    return mCurrentState;
}

void SipLine::setState(int state)
{
    mCurrentState = state;
}

UtlString& SipLine::getUser()
{
    return mUser;
}

void SipLine::setUser(const UtlString user)
{
   mUser.remove(0);
   mUser.append(user);
}

void SipLine::getIdentityAndUrl(Url &identity, Url &userEnteredUrl)
{
   identity = mIdentity;
   userEnteredUrl = mUserEnteredUrl;
}

void SipLine::setIdentityAndUrl(Url identity, Url userEnteredUrl)
{
   UtlString identityHost;
   UtlString address;
   int identityPort;

   mIdentity = identity;
   mLineId.remove(0);
   generateLineID(mLineId);
   mUserEnteredUrl = userEnteredUrl;
   //construct a complete url from identity and userEntered Url.
   mCanonicalUrl = mUserEnteredUrl;

   mUserEnteredUrl.getHostAddress(address);
   if (address.isNull())
   {
      mIdentity.getHostAddress(identityHost);
      identityPort = mIdentity.getHostPort();
      mCanonicalUrl.setHostAddress(identityHost);
      mCanonicalUrl.setHostPort(identityPort);
   }
}

Url& SipLine::getUserEnteredUrl()
{
    return mUserEnteredUrl;
}
Url& SipLine::getIdentity()
{
    return mIdentity;
}

Url& SipLine::getCanonicalUrl()
{
    return mCanonicalUrl;
}

void SipLine::setAutoEnableStatus( UtlBoolean isAutoEnabled)
{
    mIsAutoEnabled = isAutoEnabled;
}

UtlBoolean SipLine::getAutoEnableStatus()
{
    return mIsAutoEnabled ;
}

void SipLine::setVisibility(UtlBoolean isEnable)
{
    mIsVisible = isEnable;
}

UtlBoolean SipLine::getVisibility()
{
    return mIsVisible;
}
void SipLine::setCallHandling(UtlBoolean useCallHandling)
{
    mIsUsingCallHandling = useCallHandling;
}

UtlBoolean SipLine::getCallHandling()
{
    return mIsUsingCallHandling;
}

UtlBoolean SipLine::addCredentials( const UtlString& strRealm,
                             const UtlString& strUserID,
                             const UtlString& strPasswd,
                             const UtlString& Type)
{
   UtlBoolean isAdded = FALSE;

   if(!IsDuplicateRealm(strRealm, Type))
   {
      SipLineCredentials* credential = new SipLineCredentials(strRealm , strUserID, strPasswd, Type);
      mCredentials.insert((UtlString*)credential);
      isAdded = TRUE;
   }
   return isAdded;
}

int SipLine::GetNumOfCredentials()
{
   return mCredentials.entries();

}

UtlBoolean SipLine::getCredentials(const UtlString& type /*[in]*/,
                             const UtlString& realm /*[in]*/,
                             UtlString* userID /*[out]*/,
                             UtlString* MD5_token /*[out]*/)
{
   UtlBoolean credentialsFound = FALSE;
   UtlString matchRealm(realm);
   UtlString emptyRealm(NULL);
   UtlString userPassword;
   *MD5_token = "";

   SipLineCredentials* credential = (SipLineCredentials*) mCredentials.find(&matchRealm);
   if (credential)
   {
      credential->getUserId(userID);
      credential->getPasswordToken(&userPassword);
      credentialsFound = TRUE;
      credential = NULL;
      HttpMessage::buildMd5UserPasswordDigest(userID->data(), matchRealm.data(), userPassword.data(), *MD5_token);
   }
   else
   {
      credential = (SipLineCredentials*) mCredentials.find(&emptyRealm);
      if (credential)
      {
          credential->getUserId(userID);
          credential->getPasswordToken(&userPassword);
          credentialsFound = TRUE;
          credential = NULL;
          HttpMessage::buildMd5UserPasswordDigest(userID->data(), realm.data(), userPassword.data(), *MD5_token);
      }
   }

   return  credentialsFound ;
}

UtlBoolean SipLine::getDuplicateCredentials(const UtlString& type /*[in]*/,
                                            const UtlString& realm /*[in]*/)
{
   UtlBoolean credentialsFound = FALSE;
   UtlString matchRealm(realm);
   UtlString emptyRealm(NULL);

   if (realm.length() == 0)
   {
      SipLineCredentials* credential = (SipLineCredentials*) mCredentials.find(&emptyRealm);
      if (credential)
      {
          credentialsFound = TRUE;
          credential = NULL;
      }
   }
   else
   {
      SipLineCredentials* credential = (SipLineCredentials*) mCredentials.find(&matchRealm);
      if (credential)
      {
         credentialsFound = TRUE;
         credential = NULL;
      }
   }

   return  credentialsFound ;
}

UtlBoolean SipLine::removeCredential(const UtlString *realm)
{
   UtlString matchRealm(*realm);

#if 0
   OsSysLog::add(FAC_SIP, PRI_INFO,
                 "SipLine::removeCredential mCredentials contains: %d credentials for realm: \"%s\"",
                 mCredentials.entries(), matchRealm.data());
#endif

   UtlContainable* wasRemoved = mCredentials.remove(&matchRealm);

   if(wasRemoved)
   {
      delete wasRemoved;
   }

   return(wasRemoved != NULL);
}

void SipLine::removeAllCredentials()
{
    mCredentials.destroyAll();

}

void SipLine::setPreferredContactUri(const Url& preferredContactUri)
{
    mPreferredContactUri = preferredContactUri ;
}

UtlBoolean SipLine::getPreferredContactUri(Url& preferredContactUri) const
{
    UtlString host ;

    preferredContactUri = mPreferredContactUri ;
    preferredContactUri.getHostAddress(host) ;

    return (host.length() > 0) ;
}

LINE_CONTACT_TYPE SipLine::getContactType() const
{
    return meContactType ;
}

void SipLine::setContactType(LINE_CONTACT_TYPE eContactType)
{
    meContactType = eContactType ;
}

UtlBoolean SipLine::getAllCredentials( int MaxEnteries/*[in]*/ ,
      int& actualEnteries /*[out/int]*/,
      UtlString realm[]/*[out/int]*/,
      UtlString userId[]/*[out/int]*/,
      UtlString type[]/*[out/int]*/,
      UtlString passtoken[]/*[out/int]*/)
{
    UtlBoolean credentialsFound = FALSE;
    UtlString Realm;
    UtlString UserID;
    UtlString Type;
    UtlString Password;
    UtlString PassToken;
    int i = 0;

    UtlHashBagIterator observerIterator(mCredentials);
    SipLineCredentials* credential = NULL;

    do
    {
        credential = (SipLineCredentials*) observerIterator();
        if ( credential)
        {
            credential->getRealm(&Realm);
            credential->getUserId(&UserID);
            credential->getType(&Type);
            credential->getPasswordToken(&Password) ;
            PassToken = "";
            HttpMessage::buildMd5UserPasswordDigest(UserID.data(), Realm.data(), Password.data(), PassToken);

            realm[i].remove(0);
            realm[i].append(Realm);

            userId[i].remove(0);
            userId[i].append(UserID);

            type[i].remove(0);
            type[i].append(Type);

            passtoken[i].remove(0) ;
            passtoken[i].append(PassToken) ;

            i++;
            credentialsFound = TRUE;
        }
    }
    while(credential != NULL && i< MaxEnteries) ;
    actualEnteries = i;
    return  credentialsFound ;
}

UtlBoolean SipLine::IsDuplicateRealm(const UtlString realm, const UtlString scheme)
{
   UtlString userID;
   UtlString passToken;
   if (getDuplicateCredentials(scheme, realm))
      return TRUE;
   else
      return FALSE;
}

void SipLine::generateLineID(UtlString& lineId)
{
   NetMd5Codec::encode(mIdentity.toString().data(), lineId);

   // Shorten the line Ids to 12 chars (from 32)
   lineId.remove(12) ;
}
<commit_msg>Added some debug logging to SipLine<commit_after>//
// Copyright (C) 2004-2006 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2004-2006 Pingtel Corp.  All rights reserved.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
///////////////////////////////////////////////////////////////////////////////

// SYSTEM INCLUDES

#if defined(_VXWORKS)
#   include <taskLib.h>
#   include <netinet/in.h>
#endif

#include <utl/UtlHashBagIterator.h>
#include <net/SipLine.h>
#include <net/Url.h>
#include <net/SipLineCredentials.h>
#include <os/OsConfigDb.h>
#include <os/OsRWMutex.h>
#include <os/OsReadLock.h>
#include <os/OsWriteLock.h>
#include <os/OsDateTime.h>
#include <os/OsSysLog.h>
#include <net/NetMd5Codec.h>

// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// CONSTANTS

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

// Copy constructor
SipLine::SipLine(const SipLine& rSipLine)
{
   mIsVisible = rSipLine.mIsVisible ;
   mIdentity = rSipLine.mIdentity ;
   mUserEnteredUrl = rSipLine.mUserEnteredUrl;
   mUser = rSipLine.mUser ;
   mCurrentState = rSipLine.mCurrentState ;
   mIsAutoEnabled = rSipLine.mIsAutoEnabled ;
   mIsUsingCallHandling = rSipLine.mIsUsingCallHandling;
   mCanonicalUrl = rSipLine.mCanonicalUrl;
   mLineId = rSipLine.mLineId;
   mPreferredContactUri = rSipLine.mPreferredContactUri ;
   meContactType = rSipLine.meContactType;

   copyCredentials(rSipLine);

}

SipLine& SipLine::operator=(const SipLine& rSipLine)
{
   if (this == &rSipLine)            // handle the assignment to self case
      return *this;
   else
   {
      mIsVisible = rSipLine.mIsVisible ;
      mIdentity = rSipLine.mIdentity ;
      mUserEnteredUrl = rSipLine.mUserEnteredUrl;
      mCanonicalUrl = rSipLine.mCanonicalUrl;
      mUser = rSipLine.mUser ;
      mCurrentState = rSipLine.mCurrentState ;
      mIsAutoEnabled = rSipLine.mIsAutoEnabled ;
      mIsUsingCallHandling = rSipLine.mIsUsingCallHandling;
      mLineId = rSipLine.mLineId;
      mPreferredContactUri = rSipLine.mPreferredContactUri ;
      meContactType = rSipLine.meContactType;
      copyCredentials(rSipLine);
   }
   return *this;
}
//deep copy of credentials
void SipLine::copyCredentials(const SipLine &rSipLine)
{
   UtlString Realm;
   UtlString UserID;
   UtlString Type;
   UtlString Password;

   if(!mCredentials.isEmpty())
   {
      mCredentials.destroyAll();
   }
   if (! rSipLine.mCredentials.isEmpty())
   {
        UtlHashBagIterator observerIterator(const_cast<UtlHashBag&> (rSipLine.mCredentials));
        SipLineCredentials* credential = NULL;
        do
        {
            credential = (SipLineCredentials*) observerIterator();
            if ( credential)
            {
                credential->getRealm(&Realm);
                credential->getUserId(&UserID);
                credential->getType(&Type);
                credential->getPasswordToken(&Password);
                addCredentials(Realm , UserID , Password , Type);
            }
        }
        while(credential != NULL) ;
   }
}

SipLine::SipLine(Url userEnteredUrl,
                 Url identityUri,
                 UtlString user,
                 UtlBoolean visible,
                 int state,
                 UtlBoolean isAutoEnabled,
                 UtlBoolean useCallHandling)
{
   if (user.isNull())
   {
      mUser = userEnteredUrl.toString();
   }
   else
   {
      mUser = user;
   }

   mIsVisible = visible;
   mCurrentState = state;
   mIsAutoEnabled = isAutoEnabled;
   mIsUsingCallHandling = useCallHandling;
   mUserEnteredUrl = userEnteredUrl;
   meContactType = LINE_CONTACT_NAT_MAPPED ;
   if (identityUri.toString().isNull())
   {
      //then get uri from user entered url ...uri is complete in it
      UtlString uri;
      mUserEnteredUrl.getUri(uri);
      mIdentity = Url(uri);
   }
   else
   {
      mIdentity = identityUri;
   }

   //construct a complete url from identity and userEntered Url.
   mCanonicalUrl = mUserEnteredUrl;
   UtlString address;
   mUserEnteredUrl.getHostAddress(address);
   if (address.isNull())
   {
      UtlString identityHost;
      mIdentity.getHostAddress(identityHost);
      int identityPort = mIdentity.getHostPort();
      mCanonicalUrl.setHostAddress(identityHost);
      mCanonicalUrl.setHostPort(identityPort);
   }
   // create new Line Id for this line
   generateLineID(mLineId);
}

SipLine::~SipLine()
{
    mCredentials.destroyAll();
}

UtlString& SipLine::getLineId()
{
   return mLineId;
}

UtlBoolean SipLine::isDeviceLine()
{
    return (getUser().compareTo("Device", UtlString::ignoreCase) == 0) ;
}

int SipLine::getState()
{
    return mCurrentState;
}

void SipLine::setState(int state)
{
    mCurrentState = state;
}

UtlString& SipLine::getUser()
{
    return mUser;
}

void SipLine::setUser(const UtlString user)
{
   mUser.remove(0);
   mUser.append(user);
}

void SipLine::getIdentityAndUrl(Url &identity, Url &userEnteredUrl)
{
   identity = mIdentity;
   userEnteredUrl = mUserEnteredUrl;
}

void SipLine::setIdentityAndUrl(Url identity, Url userEnteredUrl)
{
   UtlString identityHost;
   UtlString address;
   int identityPort;

   mIdentity = identity;
   mLineId.remove(0);
   generateLineID(mLineId);
   mUserEnteredUrl = userEnteredUrl;
   //construct a complete url from identity and userEntered Url.
   mCanonicalUrl = mUserEnteredUrl;

   mUserEnteredUrl.getHostAddress(address);
   if (address.isNull())
   {
      mIdentity.getHostAddress(identityHost);
      identityPort = mIdentity.getHostPort();
      mCanonicalUrl.setHostAddress(identityHost);
      mCanonicalUrl.setHostPort(identityPort);
   }
}

Url& SipLine::getUserEnteredUrl()
{
    return mUserEnteredUrl;
}
Url& SipLine::getIdentity()
{
    return mIdentity;
}

Url& SipLine::getCanonicalUrl()
{
    return mCanonicalUrl;
}

void SipLine::setAutoEnableStatus( UtlBoolean isAutoEnabled)
{
    mIsAutoEnabled = isAutoEnabled;
}

UtlBoolean SipLine::getAutoEnableStatus()
{
    return mIsAutoEnabled ;
}

void SipLine::setVisibility(UtlBoolean isEnable)
{
    mIsVisible = isEnable;
}

UtlBoolean SipLine::getVisibility()
{
    return mIsVisible;
}
void SipLine::setCallHandling(UtlBoolean useCallHandling)
{
    mIsUsingCallHandling = useCallHandling;
}

UtlBoolean SipLine::getCallHandling()
{
    return mIsUsingCallHandling;
}

UtlBoolean SipLine::addCredentials( const UtlString& strRealm,
                             const UtlString& strUserID,
                             const UtlString& strPasswd,
                             const UtlString& Type)
{
   UtlBoolean isAdded = FALSE;

   if(!IsDuplicateRealm(strRealm, Type))
   {
      SipLineCredentials* credential = new SipLineCredentials(strRealm , strUserID, strPasswd, Type);
      mCredentials.insert((UtlString*)credential);
      isAdded = TRUE;
#ifdef TEST_PRINT
      OsSysLog::add(FAC_AUTH, PRI_DEBUG,
          "SipLine::addCredentials(realm=%s, userId=%s, password=%s, type=%s) number of credentials: %d for line: %s",
          strRealm.data(), strUserID.data(), strPasswd.isNull() ? "" : "******",
          Type.data(), mCredentials.entries(), mIdentity.toString().data());
#endif
   }
   else
   {
      OsSysLog::add(FAC_AUTH, PRI_DEBUG,
          "SipLine::addCredentials(realm=%s, userId=%s, ...) not added as its a duplicate",
          strRealm.data(), strUserID.data());
   }
   return isAdded;
}

int SipLine::GetNumOfCredentials()
{
   return mCredentials.entries();

}

UtlBoolean SipLine::getCredentials(const UtlString& type /*[in]*/,
                             const UtlString& realm /*[in]*/,
                             UtlString* userID /*[out]*/,
                             UtlString* MD5_token /*[out]*/)
{
   UtlBoolean credentialsFound = FALSE;
   UtlString matchRealm(realm);
   UtlString emptyRealm(NULL);
   UtlString userPassword;
   *MD5_token = "";

#ifdef TEST_PRINT
   OsSysLog::add(FAC_AUTH, PRI_DEBUG, "SipLine::getCredentials credential count: %d for line: %s",
                 mCredentials.entries(), mIdentity.toString().data());
#endif

   SipLineCredentials* credential = (SipLineCredentials*) mCredentials.find(&matchRealm);
   if (credential)
   {
#ifdef TEST_PRINT
      OsSysLog::add(FAC_AUTH, PRI_DEBUG, "SipLine::getCredentials found credentials for realm: <%s>", matchRealm.data());
#endif
      credential->getUserId(userID);
      credential->getPasswordToken(&userPassword);
      credentialsFound = TRUE;
      credential = NULL;
      HttpMessage::buildMd5UserPasswordDigest(userID->data(), matchRealm.data(), userPassword.data(), *MD5_token);
   }
   else
   {
      credential = (SipLineCredentials*) mCredentials.find(&emptyRealm);
      if (credential)
      {
#ifdef TEST_PRINT
          OsSysLog::add(FAC_AUTH, PRI_DEBUG, "SipLine::getCredentials found credentials for realm: <%s>", emptyRealm.data());
#endif
          credential->getUserId(userID);
          credential->getPasswordToken(&userPassword);
          credentialsFound = TRUE;
          credential = NULL;
          HttpMessage::buildMd5UserPasswordDigest(userID->data(), realm.data(), userPassword.data(), *MD5_token);
      }
#ifdef TEST_PRINT
      else
      {
          OsSysLog::add(FAC_AUTH, PRI_DEBUG, "SipLine::getCredentials found no credentials");
      }
#endif
   }

   return  credentialsFound ;
}

UtlBoolean SipLine::getDuplicateCredentials(const UtlString& type /*[in]*/,
                                            const UtlString& realm /*[in]*/)
{
   UtlBoolean credentialsFound = FALSE;
   UtlString matchRealm(realm);
   UtlString emptyRealm(NULL);

   if (realm.length() == 0)
   {
      SipLineCredentials* credential = (SipLineCredentials*) mCredentials.find(&emptyRealm);
      if (credential)
      {
          credentialsFound = TRUE;
          credential = NULL;
      }
   }
   else
   {
      SipLineCredentials* credential = (SipLineCredentials*) mCredentials.find(&matchRealm);
      if (credential)
      {
         credentialsFound = TRUE;
         credential = NULL;
      }
   }

   return  credentialsFound ;
}

UtlBoolean SipLine::removeCredential(const UtlString *realm)
{
   UtlString matchRealm(*realm);

#if 0
   OsSysLog::add(FAC_SIP, PRI_INFO,
                 "SipLine::removeCredential mCredentials contains: %d credentials for realm: \"%s\"",
                 mCredentials.entries(), matchRealm.data());
#endif

   UtlContainable* wasRemoved = mCredentials.remove(&matchRealm);

   if(wasRemoved)
   {
      delete wasRemoved;
   }

   return(wasRemoved != NULL);
}

void SipLine::removeAllCredentials()
{
    mCredentials.destroyAll();

}

void SipLine::setPreferredContactUri(const Url& preferredContactUri)
{
    mPreferredContactUri = preferredContactUri ;
}

UtlBoolean SipLine::getPreferredContactUri(Url& preferredContactUri) const
{
    UtlString host ;

    preferredContactUri = mPreferredContactUri ;
    preferredContactUri.getHostAddress(host) ;

    return (host.length() > 0) ;
}

LINE_CONTACT_TYPE SipLine::getContactType() const
{
    return meContactType ;
}

void SipLine::setContactType(LINE_CONTACT_TYPE eContactType)
{
    meContactType = eContactType ;
}

UtlBoolean SipLine::getAllCredentials( int MaxEnteries/*[in]*/ ,
      int& actualEnteries /*[out/int]*/,
      UtlString realm[]/*[out/int]*/,
      UtlString userId[]/*[out/int]*/,
      UtlString type[]/*[out/int]*/,
      UtlString passtoken[]/*[out/int]*/)
{
    UtlBoolean credentialsFound = FALSE;
    UtlString Realm;
    UtlString UserID;
    UtlString Type;
    UtlString Password;
    UtlString PassToken;
    int i = 0;

    UtlHashBagIterator observerIterator(mCredentials);
    SipLineCredentials* credential = NULL;

    do
    {
        credential = (SipLineCredentials*) observerIterator();
        if ( credential)
        {
            credential->getRealm(&Realm);
            credential->getUserId(&UserID);
            credential->getType(&Type);
            credential->getPasswordToken(&Password) ;
            PassToken = "";
            HttpMessage::buildMd5UserPasswordDigest(UserID.data(), Realm.data(), Password.data(), PassToken);

            realm[i].remove(0);
            realm[i].append(Realm);

            userId[i].remove(0);
            userId[i].append(UserID);

            type[i].remove(0);
            type[i].append(Type);

            passtoken[i].remove(0) ;
            passtoken[i].append(PassToken) ;

            i++;
            credentialsFound = TRUE;
        }
    }
    while(credential != NULL && i< MaxEnteries) ;
    actualEnteries = i;
    return  credentialsFound ;
}

UtlBoolean SipLine::IsDuplicateRealm(const UtlString realm, const UtlString scheme)
{
   UtlString userID;
   UtlString passToken;
   if (getDuplicateCredentials(scheme, realm))
      return TRUE;
   else
      return FALSE;
}

void SipLine::generateLineID(UtlString& lineId)
{
   NetMd5Codec::encode(mIdentity.toString().data(), lineId);

   // Shorten the line Ids to 12 chars (from 32)
   lineId.remove(12) ;
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
// stock_loan.cpp
// --------------
//
// Author: Parsiad Azimzadeh
////////////////////////////////////////////////////////////////////////////////

#include <QuantPDE/Core>
#include <QuantPDE/Modules/Lambdas>
#include <QuantPDE/Modules/Operators>
#include <QuantPDE/Modules/Utilities>

using namespace QuantPDE;
using namespace QuantPDE::Modules;

////////////////////////////////////////////////////////////////////////////////

#include <algorithm>     // max, min
#include <cassert>       // assert
#include <cmath>         // exp
#include <limits>        // numeric_limits
#include <numeric>       // accumulate
#include <tuple>         // tie
#include <unordered_map> // unordered_map

using namespace std;

////////////////////////////////////////////////////////////////////////////////

Real
	T, r, divs, vol, S_0,
	q_hat, xi, rho,
	lockout_time,
	liquidation_trigger, margin_call_trigger, post_margin_call_ratio,
	jump_arrival, up_probability, up_mean_r, down_mean_r
;
bool
	explicit_impulses,
	margin_call_enabled, liquidation_enabled,
	event_at_zero
;
int N;
RectilinearGrid1 *grid;

////////////////////////////////////////////////////////////////////////////////
// Helper functions
////////////////////////////////////////////////////////////////////////////////

constexpr Real inf = numeric_limits<Real>::infinity();

/**
 * Interpolation function for similarity reduction.
 * @param v The value of the stock loan for fixed q_hat.
 * @param s Collateral value.
 * @param q The outstanding loan.
 * @param q_hat A fixed, positive number.
 * @return The interpolated value of v at (s, q).
 */
inline Real v_similarity_reduction(
	const Interpolant1 &v,
	Real s, Real q, Real q_hat
) {
	const Real alpha = q_hat / q;
	return v(alpha * s) / alpha;
}

unordered_map<Real, Real> growth_cache;

/**
 * Computes the loan growth factor for some time.
 * @param t A time.
 * @return The growth factor.
 */
inline Real growth(Real t) {
	if(growth_cache.count(t) > 0) {
		return growth_cache[t];
	}
	growth_cache[t] = exp((r+xi) * t);
}

/**
 * Computes the loan-to-value ratio.
 * @param t A time.
 * @param s Collateral value.
 * @return The ratio.
 */
inline Real loan_to_value_ratio(Real t, Real s) {
	const Real g = growth(t);
	return g * q_hat / s;
}

/**
 * Computes the payoff for prepayment.
 * @param t A time.
 * @param s Collateral value.
 * @return The payoff or -infinity if t < lockout time.
 */
inline Real client_obstacle(Real t, Real s) {
	if(t < lockout_time) { return -inf; }
	return max(s - rho * growth(t) * q_hat, 0. );
}

/**
 * Computes cash flow to the client when the lender performs an action.
 * @param t A time.
 * @param s Collateral value.
 * @param z The control. Zero indicates liquidation, positive indicates a margin
 *          call.
 */
inline Real flow_to_client(Real t, Real s, Real z) {
	const Real g = growth(t);

	// Loan-to-value ratio
	const Real ratio = g * q_hat / s;

	if(
		liquidation_enabled
		&& z <= epsilon && ratio >= liquidation_trigger
	) {
		// Liquidate
		return max(s - g * q_hat, 0.);
	} else if(
		margin_call_enabled
		&& z > epsilon && ratio >= margin_call_trigger && s > 0.
	) {
		// Margin call
		return -(g * q_hat - z * s);
	}

	// Cannot issue a margin call or liquidate
	return inf;
}

/**
 * Computes the post margin call loan value.
 * @param t A time.
 * @param s Collateral value.
 * @param z The control.
 */
inline Real post_margin_call_loan(Real t, Real s, Real z) {
	const Real g = growth(t);
	return z * s / g;
}

/**
 * Computes the payoff at expiry.
 * @param s Collateral value.
 * @return Payoff.
 */
Real payoff(Real s) {
	return max(s - growth(T) * q_hat, 0.);
}

////////////////////////////////////////////////////////////////////////////////
// Lender intervention
////////////////////////////////////////////////////////////////////////////////

class LenderIntervention final : public RawControlledLinearSystem<1, 1> {

	const RectilinearGrid1 &grid;

	virtual Matrix A(Real t) {
		// S axis
		const Axis &S = grid[0];

		// Reserve matrix (at most 2 elements per row)
		Matrix M = grid.matrix();
		M.reserve(IntegerVector::Constant( grid.size(), 2 ));

		Index k = 0;
		for(auto node : grid) {
			// s-Coordinate
			const Real s = node[0];

			// Get control
			const Real z = (this->control(0))(k);

			// Loan-to-value ratio
			const Real ratio = loan_to_value_ratio(t, s);

			// Either liquidating or not past margin call trigger
			if(
				!(
					margin_call_enabled
					&& z > epsilon
					&& ratio >= margin_call_trigger
				)
			) {
				++k;
				continue;
			}

			// Loan value after margin call
			const Real q_plus = post_margin_call_loan(t, s, z);

			// Similarity reduction factor
			const Real alpha = q_hat / q_plus;

			// Approximate
			//   V(alpha * s) / alpha
			// via linear interpolation

			Index j;
			Real w;
			tie(j, w) = linearInterpolationData(S, alpha * s);

			M.insert(k, j  ) =    w  / alpha;
			M.insert(k, j+1) = (1-w) / alpha;

			++k;
		}

		M.makeCompressed();

		return grid.identity() - M;
	}

	virtual Vector b(Real t) {
		Vector b(grid.vector());

		Index k = 0;
		for(auto node : grid) {
			// s-Coordinate
			const Real s = node[0];

			// Get control
			const Real z = (this->control(0))(k);

			// Flow to client due to lender action
			b(k) = flow_to_client(t, s, z);

			++k;
		}

		return b;
	}

public:

	template <typename G>
	LenderIntervention(G &grid) : grid(grid) {}

};

////////////////////////////////////////////////////////////////////////////////

ResultsTuple1 run(int k) {

	// 2^k
	int factor = 1;
	for(int i = 0; i < k; ++i) {
		factor *= 4;
	}
	const int Nck = N * factor;

	////////////////////////////////////////////////////////////////////////
	// Spatial grid
	////////////////////////////////////////////////////////////////////////

	auto refined_grid = grid->refined(k); // Refine grid R times

	////////////////////////////////////////////////////////////////////////
	// Iteration tree
	////////////////////////////////////////////////////////////////////////

	const Real dt = T / Nck;
	ReverseConstantStepper stepper(0., T, dt);
	ToleranceIteration tolerance;

	// Explicit events
	const int n0 = event_at_zero ? 0 : 1;
	for(int n = n0; n < Nck; ++n) { // Skip n = Nck as it has no effect
		const Real t = n * dt;

		// Client
		stepper.add(
			t,
			[=] (const Interpolant1 &v, Real s) {
				// Do nothing
				const Real v0 = v(s);

				// Prepay
				const Real v1 = client_obstacle(t, s);

				// Maximum
				return max(v0, v1);
			},
			refined_grid
		);

		// Lender
		if(
			explicit_impulses
			&& (liquidation_enabled || margin_call_enabled)
		) {
			stepper.add(
				t,
				[=] (const Interpolant1 &v, Real s) {
					// Do nothing
					const Real v0 = v(s);

					// Liquidate
					const Real v1 = flow_to_client(
						t, s,
						0.
					);

					// Margin call
					const Real v2 = v_similarity_reduction(
						v, s,
						post_margin_call_loan(
							t,
							s,
							post_margin_call_ratio
						),
						q_hat
					) + flow_to_client(
						t, s,
						post_margin_call_ratio
					);

					// Minimum
					return min(v0, min(v1, v2));
				},
				refined_grid
			);
		}
	}

	////////////////////////////////////////////////////////////////////////
	// Linear system tree
	////////////////////////////////////////////////////////////////////////

	IterationNode *root;
	LinearSystem *bsptr;

	// Black-Scholes operator
	BlackScholesJumpDiffusion1 bsj(
		refined_grid, r, vol, divs,
		jump_arrival,
		doubleExponential(
			up_probability,
			up_mean_r,
			down_mean_r
		)
	);
	BlackScholes1 bs(refined_grid, r, vol, divs);
	if(jump_arrival < epsilon) {
		bsptr = &bs;
	} else {
		bsptr = &bsj;
		bsj.setIteration(stepper);
	}

	// Discretization
	typedef ReverseBDFOne Discretization;
	Discretization discretization(refined_grid, *bsptr);
	discretization.setIteration(stepper);

	// Policy iteration on lender control
	LenderIntervention lender_intervention(refined_grid);
	auto control_grid = RectilinearGrid1(
		Axis { 0., post_margin_call_ratio }
	);
	MaxPolicyIteration1_1 policy(
		refined_grid,
		control_grid,
		lender_intervention
	);
	policy.setIteration(tolerance);
	MaxPenaltyMethod penalty(
		refined_grid,
		discretization,
		policy
	);
	penalty.setIteration(tolerance);

	// Pick root element
	if(explicit_impulses) {
		root = &discretization;
	} else {
		stepper.setInnerIteration(tolerance);
		root = &penalty;
	}

	////////////////////////////////////////////////////////////////////////
	// Running
	////////////////////////////////////////////////////////////////////////

	SparseLUSolver solver;

	auto solution = stepper.solve(
		refined_grid, // Domain
		payoff,       // Initial condition
		*root,        // Root of linear system tree
		solver        // Linear system solver
	);

	////////////////////////////////////////////////////////////////////////

	// Timesteps
	unsigned timesteps = stepper.iterations()[0];

	// Average number of policy iterations
	Real policy_its = nan("");
	auto its = tolerance.iterations();
	policy_its = accumulate(its.begin(), its.end(), 0.) / its.size();

	return ResultsTuple1(
		{(Real) refined_grid.size(), (Real) timesteps, policy_its },
		solution, S_0
	);
}

int main(int argc, char **argv) {
	// Parse configuration file
	Configuration configuration = getConfiguration(argc, argv);

	// Get options
	int kn, k0;
	Real S_max, S_min, dS;
	kn = getInt(configuration, "maximum_refinement", 7);
	k0 = getInt(configuration, "minimum_refinement", 0);
	T = getReal(configuration, "time_to_expiry", 10.);
	r = getReal(configuration, "interest_rate", .05);
	divs = getReal(configuration, "dividend_rate", 0.02);
	vol = getReal(configuration, "volatility", .15);
	S_0 = getReal(configuration, "asset_price", 100.);
	q_hat = getReal(configuration, "loan_value", 80.);
	xi = getReal(configuration, "spread", 0.02);
	rho = getReal(configuration, "penalty_scaling", 1.);
	lockout_time = getReal(configuration, "lockout_time", 0.);
	liquidation_trigger = getReal(configuration, "liquidation_trigger", 80. / 90.);
	margin_call_trigger = getReal(configuration, "margin_call_trigger", 80. / 95.);
	jump_arrival = getReal(configuration, "jump_arrival_rate", 0.5);
	up_probability = getReal(configuration, "jump_up_probability", 0.09);
	up_mean_r = getReal(configuration, "jump_up_mean_reciprocal", 2.3);
	down_mean_r = getReal(configuration, "jump_down_mean_reciprocal", 1.8);
	post_margin_call_ratio = getReal(configuration, "post_margin_call_ratio", 80. / 100.);
	S_min = getReal(configuration, "print_asset_price_minimum", 0.);
	S_max = getReal(configuration, "print_asset_price_maximum", 300.);
	dS = getReal(configuration, "print_asset_price_step_size", 10.);
	N = getInt(configuration, "initial_number_of_timesteps", 2);
	explicit_impulses = getInt(configuration, "fully_explicit", false);
	event_at_zero = getInt(configuration, "apply_event_at_time_zero", true);
	margin_call_enabled = getInt(configuration, "margin_call_enabled", false);
	liquidation_enabled = getInt(configuration, "liquidation_enabled", true);
	RectilinearGrid1 default_grid( S_0 * Axis::special );
	RectilinearGrid1 tmp = getGrid(configuration, "initial_grid", default_grid);
	grid = &tmp;

	// Print configuration file
	cerr << configuration << endl << endl;

	// Run and print results
	ResultsBuffer1 buffer(
		run,
		{ "Nodes", "Steps", "Mean Policy Iterations" },
		kn, k0
	);
	buffer.addPrintGrid( RectilinearGrid1(Axis::range(S_min, dS, S_max)) );
	buffer.stream();

	return 0;
}

<commit_msg>stock_loan.cpp: added regular coupon payments.<commit_after>////////////////////////////////////////////////////////////////////////////////
// stock_loan.cpp
// --------------
//
// Author: Parsiad Azimzadeh
////////////////////////////////////////////////////////////////////////////////

#include <QuantPDE/Core>
#include <QuantPDE/Modules/Lambdas>
#include <QuantPDE/Modules/Operators>
#include <QuantPDE/Modules/Utilities>

using namespace QuantPDE;
using namespace QuantPDE::Modules;

////////////////////////////////////////////////////////////////////////////////

#include <algorithm>     // max, min
#include <cassert>       // assert
#include <cmath>         // ceil, exp
#include <limits>        // numeric_limits
#include <numeric>       // accumulate
#include <tuple>         // tie
#include <unordered_map> // unordered_map
#include <vector>        // vector

using namespace std;

////////////////////////////////////////////////////////////////////////////////

Real
	T, r, divs, vol, S_0,
	q_hat, spread,
	prepayment_penalty, liquidation_penalty,
	lockout_time,
	liquidation_trigger, margin_call_trigger, post_margin_call_ratio,
	jump_arrival, up_probability, up_mean_r, down_mean_r
;
bool
	explicit_impulses,
	margin_call_enabled, liquidation_enabled
;
int
	N,
	coupon_payments
;
RectilinearGrid1 *grid;

////////////////////////////////////////////////////////////////////////////////
// Helper functions
////////////////////////////////////////////////////////////////////////////////

constexpr Real inf = numeric_limits<Real>::infinity();

/**
 * Interpolation function for similarity reduction.
 * @param v The value of the stock loan for fixed q_hat.
 * @param s Collateral value.
 * @param q The outstanding loan.
 * @param q_hat A fixed, positive number.
 * @return The interpolated value of v at (s, q).
 */
inline Real v_similarity_reduction(
	const Interpolant1 &v,
	Real s, Real q, Real q_hat
) {
	const Real alpha = q_hat / q;
	return v(alpha * s) / alpha;
}

/**
 * Computes the loan growth factor minus unity for some fixed increment in time.
 * @param delta A time increment.
 * @return The growth factor.
 */
inline Real growth_delta(Real delta) {
	return (r+spread) * delta;
}

/**
 * Computes the loan growth factor for some time.
 * @param t A time.
 * @return The growth factor.
 */
inline Real growth(Real t) {
	// Get last coupon payment time (or initial time)
	const Real d = (t / T) * (coupon_payments + 1);
	int n = floor(d);
	if(n > 0 && abs(n - d) < epsilon) { --n; }
	const Real t_n = n * (T / (coupon_payments + 1));
	return 1. + growth_delta(t - t_n);
}

/**
 * Computes the loan-to-value ratio.
 * @param t A time.
 * @param s Collateral value.
 * @return The ratio.
 */
inline Real loan_to_value_ratio(Real t, Real s) {
	const Real g = growth(t);
	return g * q_hat / s;
}

/**
 * Computes the payoff for prepayment.
 * @param t A time.
 * @param s Collateral value.
 * @return The payoff or -infinity if t < lockout time.
 */
inline Real client_obstacle(Real t, Real s) {
	if(t < lockout_time) { return -inf; }
	return max(s - prepayment_penalty * growth(t) * q_hat, 0. );
}

/**
 * Computes cash flow to the client when the lender performs an action.
 * @param t A time.
 * @param s Collateral value.
 * @param control The control. Zero indicates liquidation, positive indicates a
 *                margin call.
 */
inline Real flow_to_client(Real t, Real s, Real control) {

	const Real g = growth(t);

	// Loan-to-value ratio
	const Real ratio = loan_to_value_ratio(t, s);

	if(
		liquidation_enabled
		&& control <= epsilon && ratio >= liquidation_trigger
	) {
		// Liquidate
		return max(s - liquidation_penalty * g * q_hat, 0.);
	} else if(
		margin_call_enabled
		&& control > epsilon && ratio >= margin_call_trigger
	) {
		// Margin call
		return -(g * q_hat - control * s);
	}

	// Cannot issue a margin call or liquidate
	return inf;
}

/**
 * Computes the post margin call loan value.
 * @param t A time.
 * @param s Collateral value.
 * @param control The control.
 */
inline Real post_margin_call_loan(Real t, Real s, Real control) {
	const Real g = growth(t);
	return control * s / g;
}

/**
 * Computes the payoff at expiry.
 * @param s Collateral value.
 * @return Payoff.
 */
Real payoff(Real s) {
	const Real coupon_dt = T / (coupon_payments + 1);
	return max(s - (1. + growth_delta(coupon_dt)) * q_hat, 0.);
}

////////////////////////////////////////////////////////////////////////////////
// Lender intervention
////////////////////////////////////////////////////////////////////////////////

class LenderIntervention final : public RawControlledLinearSystem<1, 1> {

	const RectilinearGrid1 &grid;

	virtual Matrix A(Real t) {
		// S axis
		const Axis &S = grid[0];

		// Reserve matrix (at most 2 elements per row)
		Matrix M = grid.matrix();
		M.reserve(IntegerVector::Constant( grid.size(), 2 ));

		Index k = 0;
		for(auto node : grid) {
			// s-Coordinate
			const Real s = node[0];

			// Get control
			const Real control = (this->control(0))(k);

			// Loan-to-value ratio
			const Real ratio = loan_to_value_ratio(t, s);

			// Either liquidating or not past margin call trigger
			if(
				!(
					margin_call_enabled
					&& control > epsilon
					&& ratio >= margin_call_trigger
				)
			) {
				++k;
				continue;
			}

			// Loan value after margin call
			const Real q_plus = post_margin_call_loan(
				t,
				s,
				control
			);

			// Similarity reduction factor
			const Real alpha = q_hat / q_plus;

			// Approximate
			//   V(alpha * s) / alpha
			// via linear interpolation

			Index j;
			Real w;
			tie(j, w) = linearInterpolationData(S, alpha * s);

			M.insert(k, j  ) =    w  / alpha;
			M.insert(k, j+1) = (1-w) / alpha;

			++k;
		}

		M.makeCompressed();

		return grid.identity() - M;
	}

	virtual Vector b(Real t) {
		Vector b(grid.vector());

		Index k = 0;
		for(auto node : grid) {
			// s-Coordinate
			const Real s = node[0];

			// Get control
			const Real control = (this->control(0))(k);

			// Flow to client due to lender action
			b(k) = flow_to_client(t, s, control);

			++k;
		}

		return b;
	}

public:

	template <typename G>
	LenderIntervention(G &grid) : grid(grid) {}

};

////////////////////////////////////////////////////////////////////////////////

ResultsTuple1 run(int k) {

	// 2^k
	int factor = 1;
	for(int i = 0; i < k; ++i) {
		factor *= 4;
	}
	const int Nck = N * factor;

	////////////////////////////////////////////////////////////////////////
	// Spatial grid
	////////////////////////////////////////////////////////////////////////

	auto refined_grid = grid->refined(k); // Refine grid R times

	////////////////////////////////////////////////////////////////////////
	// Iteration tree
	////////////////////////////////////////////////////////////////////////

	const Real dt = T / Nck;
	ReverseConstantStepper stepper(0., T, dt);
	ToleranceIteration tolerance;

	// Explicit events
	for(int n = 0; n < Nck; ++n) { // Skip n = Nck as it has no effect
		const Real t = n * dt;

		// Client
		stepper.add(
			t,
			[=] (const Interpolant1 &v, Real s) {
				// Do nothing
				const Real v0 = v(s);

				// Prepay
				const Real v1 = client_obstacle(t, s);

				// Maximum
				return max(v0, v1);
			},
			refined_grid
		);

		// Lender
		if(
			explicit_impulses
			&& (liquidation_enabled || margin_call_enabled)
		) {
			stepper.add(
				t,
				[=] (const Interpolant1 &v, Real s) {
					// Do nothing
					const Real v0 = v(s);

					// Liquidate
					const Real v1 = flow_to_client(
						t, s,
						0.
					);

					// Margin call
					const Real v2 = v_similarity_reduction(
						v, s,
						post_margin_call_loan(
							t,
							s,
							post_margin_call_ratio
						),
						q_hat
					) + flow_to_client(
						t, s,
						post_margin_call_ratio
					);

					// Minimum
					return min(v0, min(v1, v2));
				},
				refined_grid
			);
		}
	}

	// Coupon payments
	const Real coupon_dt = T / (coupon_payments + 1);
	for(int n = 1; n <= coupon_payments; ++n) {
		const Real t = n * coupon_dt;

		stepper.add(
			t,
			[=] (const Interpolant1 &v, Real s) {
				return v(s) - q_hat * growth_delta(coupon_dt);
			},
			refined_grid
		);
	}

	////////////////////////////////////////////////////////////////////////
	// Linear system tree
	////////////////////////////////////////////////////////////////////////

	IterationNode *root;
	LinearSystem *bsptr;

	// Black-Scholes operator
	BlackScholesJumpDiffusion1 bsj(
		refined_grid, r, vol, divs,
		jump_arrival,
		doubleExponential(
			up_probability,
			up_mean_r,
			down_mean_r
		)
	);
	BlackScholes1 bs(refined_grid, r, vol, divs);
	if(jump_arrival < epsilon) {
		bsptr = &bs;
	} else {
		bsptr = &bsj;
		bsj.setIteration(stepper);
	}

	// Discretization
	typedef ReverseBDFOne Discretization;
	Discretization discretization(refined_grid, *bsptr);
	discretization.setIteration(stepper);

	// Policy iteration on lender control
	LenderIntervention lender_intervention(refined_grid);
	auto control_grid = RectilinearGrid1(
		Axis { 0., post_margin_call_ratio }
	);
	MaxPolicyIteration1_1 policy(
		refined_grid,
		control_grid,
		lender_intervention
	);
	policy.setIteration(tolerance);
	MaxPenaltyMethod penalty(
		refined_grid,
		discretization,
		policy,
		1e-2 * dt
	);
	penalty.setIteration(tolerance);

	// Pick root element
	if(explicit_impulses) {
		root = &discretization;
	} else {
		stepper.setInnerIteration(tolerance);
		root = &penalty;
	}

	////////////////////////////////////////////////////////////////////////
	// Running
	////////////////////////////////////////////////////////////////////////

	SparseLUSolver solver;

	auto solution = stepper.solve(
		refined_grid, // Domain
		payoff,       // Initial condition
		*root,        // Root of linear system tree
		solver        // Linear system solver
	);

	////////////////////////////////////////////////////////////////////////

	// Timesteps
	unsigned timesteps = stepper.iterations()[0];

	// Average number of policy iterations
	Real policy_its = nan("");
	auto its = tolerance.iterations();
	policy_its = accumulate(its.begin(), its.end(), 0.) / its.size();

	return ResultsTuple1(
		{(Real) refined_grid.size(), (Real) timesteps, policy_its },
		solution, S_0
	);
}

int main(int argc, char **argv) {
	// Parse configuration file
	Configuration configuration = getConfiguration(argc, argv);

	// Get options
	int kn, k0;
	Real S_max, S_min, dS;
	kn = getInt(configuration, "maximum_refinement", 7);
	k0 = getInt(configuration, "minimum_refinement", 0);
	T = getReal(configuration, "time_to_expiry", 10.);
	r = getReal(configuration, "interest_rate", .05);
	divs = getReal(configuration, "dividend_rate", 0.02);
	vol = getReal(configuration, "volatility", .15);
	S_0 = getReal(configuration, "asset_price", 100.);
	q_hat = getReal(configuration, "loan_value", 80.);
	spread = getReal(configuration, "spread", 0.02);
	prepayment_penalty = getReal(configuration, "prepayment_penalty", 1.);
	liquidation_penalty = getReal(configuration, "liquidation_penalty", 1.);
	lockout_time = getReal(configuration, "lockout_time", 0.);
	liquidation_trigger = getReal(configuration, "liquidation_trigger", 80. / 90.);
	margin_call_trigger = getReal(configuration, "margin_call_trigger", 80. / 95.);
	jump_arrival = getReal(configuration, "jump_arrival_rate", 0.5);
	up_probability = getReal(configuration, "jump_up_probability", 0.09);
	up_mean_r = getReal(configuration, "jump_up_mean_reciprocal", 2.3);
	down_mean_r = getReal(configuration, "jump_down_mean_reciprocal", 1.8);
	post_margin_call_ratio = getReal(configuration, "post_margin_call_ratio", 80. / 100.);
	S_min = getReal(configuration, "print_asset_price_minimum", 0.);
	S_max = getReal(configuration, "print_asset_price_maximum", 300.);
	dS = getReal(configuration, "print_asset_price_step_size", 10.);
	N = getInt(configuration, "initial_number_of_timesteps", 2);
	coupon_payments = getInt(configuration, "coupon_payments", 0);
	explicit_impulses = getInt(configuration, "fully_explicit", false);
	margin_call_enabled = getInt(configuration, "margin_call_enabled", false);
	liquidation_enabled = getInt(configuration, "liquidation_enabled", true);
	RectilinearGrid1 default_grid( S_0 * Axis::special );
	RectilinearGrid1 tmp = getGrid(configuration, "initial_grid", default_grid);
	grid = &tmp;

	// Ensure that N is picked appropriately
	N = max(N, coupon_payments + 1);

	// Print configuration file
	cerr << configuration << endl << endl;

	// Run and print results
	ResultsBuffer1 buffer(
		run,
		{ "Nodes", "Steps", "Mean Policy Iterations" },
		kn, k0
	);
	buffer.addPrintGrid( RectilinearGrid1(Axis::range(S_min, dS, S_max)) );
	buffer.stream();

	return 0;
}

<|endoftext|>


<commit_before>#ifndef SAVE_STATE_H
# define SAVE_STATE_H
# pragma once

struct statebuf
{
  void* sp;
  void* label;
};

#if defined(__GNUC__)
inline bool __attribute__((always_inline)) savestate(statebuf& ssb) noexcept
{
	bool r;

#if defined(i386) || defined(__i386) || defined(__i386__)
	asm volatile (
		"movl %%esp, %0\n\t" // store sp
		"movl $1f, %1\n\t" // store label
		"movb $0, %2\n\t" // return false
		"jmp 2f\n\t"
		"1:movb $1, %2\n\t" // return true
		"2:"
		: "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
		:
		: "memory"
	);
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
	asm volatile (
		"movq %%rsp, %0\n\t" // store sp
		"movq $1f, %1\n\t" // store label
		"movb $0, %2\n\t" // return false
		"jmp 2f\n\t"
		"1:movb $1, %2\n\t" // return true
		"2:"
		: "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
		:
		: "memory"
	);
#elif defined(__arm__)
  asm volatile (
    "mov %0, sp\n\t" // store sp
    "mov %1, $1f\n\t" // store label
		"mov %2, $0\n\t" // return false
    "b 2f\n\t"
    "1:mov %2, $1\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "memory"
  );
#endif

	return r;
}
#elif defined(_MSC_VER)
__forceinline bool savestate(statebuf& ssb) noexcept
{
	bool r;

	__asm {
		push ebp
		mov ebx, ssb
		mov [ebx]ssb.sp, esp
		mov [ebx]ssb.label, offset _1f
		mov r, 0x0
		jmp _2f
		_1f: pop ebp
			 mov r, 0x1
		_2f:
	}

	return r;
}
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
#if defined(i386) || defined(__i386) || defined(__i386__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movl %0, %%esp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movq %0, %%rsp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__arm__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "mov sp, %0\n\t"             \
    "b *%1"                        \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#else
# error "unsupported architecture"
#endif
#elif defined(_MSC_VER)
#define restorestate(SSB)   \
  __asm mov ebx, this       \
  __asm add ebx, [SSB]      \
  __asm mov esp, [ebx]SSB.sp\
  __asm jmp [ebx]SSB.label
#else
# error "unsupported compiler"
#endif

#endif // SAVE_STATE_H
<commit_msg>some fixes<commit_after>#ifndef SAVE_STATE_H
# define SAVE_STATE_H
# pragma once

struct statebuf
{
  void* sp;
  void* label;
};

#if defined(__GNUC__)
inline bool __attribute__((always_inline)) savestate(statebuf& ssb) noexcept
{
	bool r;

#if defined(i386) || defined(__i386) || defined(__i386__)
	asm volatile (
		"movl %%esp, %0\n\t" // store sp
		"movl $1f, %1\n\t" // store label
		"movb $0, %2\n\t" // return false
		"jmp 2f\n\t"
		"1:movb $1, %2\n\t" // return true
		"2:"
		: "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
		:
		: "memory"
	);
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
	asm volatile (
		"movq %%rsp, %0\n\t" // store sp
		"movq $1f, %1\n\t" // store label
		"movb $0, %2\n\t" // return false
		"jmp 2f\n\t"
		"1:movb $1, %2\n\t" // return true
		"2:"
		: "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
		:
		: "memory"
	);
#elif defined(__arm__)
  asm volatile (
    "mov %0, sp\n\t" // store sp
    "mov %1, $1f\n\t" // store label
		"mov %2, $0\n\t" // return false
    "b 2f\n\t"
    "1:mov %2, $1\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "memory"
  );
#endif

	return r;
}
#elif defined(_MSC_VER)
__forceinline bool savestate(statebuf& ssb) noexcept
{
	bool r;

	__asm {
		push ebp
		mov ebx, ssb
		mov [ebx]ssb.sp, esp
		mov [ebx]ssb.label, offset _1f
		mov r, 0x0
		jmp _2f
		_1f: pop ebp
			 mov r, 0x1
		_2f:
	}

	return r;
}
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
#if defined(i386) || defined(__i386) || defined(__i386__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movl %0, %%esp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movq %0, %%rsp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__arm__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "mov sp, %0\n\t"               \
    "b %1"                         \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#else
# error "unsupported architecture"
#endif
#elif defined(_MSC_VER)
#define restorestate(SSB)   \
  __asm mov ebx, this       \
  __asm add ebx, [SSB]      \
  __asm mov esp, [ebx]SSB.sp\
  __asm jmp [ebx]SSB.label
#else
# error "unsupported compiler"
#endif

#endif // SAVE_STATE_H
<|endoftext|>


<commit_before>#ifndef SAVE_STATE_H
# define SAVE_STATE_H
# pragma once

struct statebuf
{
  void* sp;
  void* label;
};

#if defined(__GNUC__)
static inline bool __attribute__((always_inline)) savestate(
  statebuf& ssb) noexcept
{
  bool r;

#if defined(i386) || defined(__i386) || defined(__i386__)
  asm volatile (
    "push %%ebp\n\t"
    "movl %%esp, %0\n\t" // store sp
    "movl $1f, %1\n\t" // store label
    "movb $0, %2\n\t" // return false
    "jmp 2f\n\t"
    "1:pop %%ebp\n\t"
    "movb $1, %2\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "memory"
  );
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
  asm volatile (
    "movq %%rsp, %0\n\t" // store sp
    "movq $1f, %1\n\t" // store label
    "movb $0, %2\n\t" // return false
    "jmp 2f\n\t"
    "1:movb $1, %2\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "memory"
  );
#elif defined(__arm__)
  asm volatile (
    "push {fp}\n\t" // push fp
    "str sp, %0\n\t" // store sp
    "ldr r3, =1f\n\t" // load label into r0
    "str r3, %1\n\t" // store r0 into label
    "mov %2, $0\n\t" // store 0 into result
    "b 2f\n\t"
    "1:pop {fp}\n\t" // restore fp
    "mov %2, $1\n\t" // store 1 into result
    "2:"
    : "=r3", "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "memory"
  );
#endif

  return r;
}
#elif defined(_MSC_VER)
__forceinline bool savestate(statebuf& ssb) noexcept
{
  bool r;

  __asm {
    push ebp
    mov ebx, ssb
    mov [ebx]ssb.sp, esp
    mov [ebx]ssb.label, offset _1f
    mov r, 0x0
    jmp _2f
    _1f: pop ebp
       mov r, 0x1
    _2f:
  }

  return r;
}
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
#if defined(i386) || defined(__i386) || defined(__i386__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movl %0, %%esp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movq %0, %%rsp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__arm__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "ldr sp, %0\n\t"               \
    "ldr pc, %1"                   \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#else
# error "unsupported architecture"
#endif
#elif defined(_MSC_VER)
#define restorestate(SSB)   \
  __asm mov ebx, this       \
  __asm add ebx, [SSB]      \
  __asm mov esp, [ebx]SSB.sp\
  __asm jmp [ebx]SSB.label
#else
# error "unsupported compiler"
#endif

#endif // SAVE_STATE_H
<commit_msg>some fixes<commit_after>#ifndef SAVE_STATE_H
# define SAVE_STATE_H
# pragma once

struct statebuf
{
  void* sp;
  void* label;
};

#if defined(__GNUC__)
static inline bool __attribute__((always_inline)) savestate(
  statebuf& ssb) noexcept
{
  bool r;

#if defined(i386) || defined(__i386) || defined(__i386__)
  asm volatile (
    "push %%ebp\n\t"
    "movl %%esp, %0\n\t" // store sp
    "movl $1f, %1\n\t" // store label
    "movb $0, %2\n\t" // return false
    "jmp 2f\n\t"
    "1:pop %%ebp\n\t"
    "movb $1, %2\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "memory"
  );
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
  asm volatile (
    "movq %%rsp, %0\n\t" // store sp
    "movq $1f, %1\n\t" // store label
    "movb $0, %2\n\t" // return false
    "jmp 2f\n\t"
    "1:movb $1, %2\n\t" // return true
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "memory"
  );
#elif defined(__arm__)
  asm volatile (
    "push {fp}\n\t" // push fp
    "str sp, %0\n\t" // store sp
    "ldr r3, =1f\n\t" // load label into r0
    "str r3, %1\n\t" // store r0 into label
    "mov %2, $0\n\t" // store 0 into result
    "b 2f\n\t"
    "1:pop {fp}\n\t" // restore fp
    "mov %2, $1\n\t" // store 1 into result
    "2:"
    : "=m" (ssb.sp), "=m" (ssb.label), "=r" (r)
    :
    : "r3, ""memory"
  );
#endif

  return r;
}
#elif defined(_MSC_VER)
__forceinline bool savestate(statebuf& ssb) noexcept
{
  bool r;

  __asm {
    push ebp
    mov ebx, ssb
    mov [ebx]ssb.sp, esp
    mov [ebx]ssb.label, offset _1f
    mov r, 0x0
    jmp _2f
    _1f: pop ebp
       mov r, 0x1
    _2f:
  }

  return r;
}
#else
# error "unsupported compiler"
#endif

#if defined(__GNUC__)
#if defined(i386) || defined(__i386) || defined(__i386__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movl %0, %%esp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#define restorestate(SSB)          \
  asm volatile (                   \
    "movq %0, %%rsp\n\t"           \
    "jmp *%1"                      \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#elif defined(__arm__)
#define restorestate(SSB)          \
  asm volatile (                   \
    "ldr sp, %0\n\t"               \
    "ldr pc, %1"                   \
    :                              \
    : "m" (SSB.sp), "m" (SSB.label)\
  );
#else
# error "unsupported architecture"
#endif
#elif defined(_MSC_VER)
#define restorestate(SSB)   \
  __asm mov ebx, this       \
  __asm add ebx, [SSB]      \
  __asm mov esp, [ebx]SSB.sp\
  __asm jmp [ebx]SSB.label
#else
# error "unsupported compiler"
#endif

#endif // SAVE_STATE_H
<|endoftext|>


<commit_before>#include <iostream>
#include <random>
#include <thread>

using std::cout;
using std::cin;
using std::random_device;
using std::mt19937_64;
using std::uniform_real_distribution;
using std::vector;
using std::thread;

#define SIZEF 500

typedef struct Info{
	int board[SIZEF][SIZEF];
	int x;
	int y;
} Info;

int size;

int iPasso[8] = { -2, -1,  1,  2,  2,  1, -1, -2 };
int jPasso[8] = {  1,  2,  2,  1, -1, -2, -2, -1 };

double Random(int n){
	//https://stackoverflow.com/questions/5008804/generating-random-integer-from-a-range
	random_device rd;
	mt19937_64 gen(rd());
	//http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
	uniform_real_distribution<> uni(0,n);
	return uni(gen);
}

void InitMatrix(int matrix[SIZEF][SIZEF], int x, int y){
	for (int i = 0; i < size; ++i){
		for (int j = 0; j < size; ++j){
			matrix[i][j] = 0;
		}
	}
	matrix[x][y] = 1;
}

void PrintBoard(int board[SIZEF][SIZEF]){
	for (int i = 0; i < size; ++i){
		for (int j = 0; j < size; ++j)
			cout << board[i][j] << "\t";
		cout << "\n\n";
	}
}

void populate(vector<Info> &p, int threads){
	int count = 0;

	while (count != threads){
		int flag = 1;
		Info tmp;
		tmp.x = Random(size-1);
		tmp.y = Random(size-1);
		InitMatrix(tmp.board, tmp.x, tmp.y);

		for (unsigned int i = 0; i < p.size(); i++) {
			if (p[i].x == tmp.x && p[i].y == tmp.y) {
				flag = 0;
				break;
			}
		}

		if (flag) {
			p.push_back(tmp);
			count ++;
		}
	}
}

bool Valid(Info p, int i){
  int x = (p.x) + iPasso[i];
  int y = (p.y) + jPasso[i];

  if( x >= 0 && x < size && y >= 0 && y < size && p.board[x][y] == 0 )
    return true;
  return false;
}

void SaveMove(Info p, int i){
  p.x+=iPasso[i];
  p.y+=jPasso[i];
}

int walk(Info p){
	double random = Random(99.9);
	int pass = 0;

	while(1){
		random = fmod(random,100);
		if (0 <= random && random < 12.5) { // move 1
			if(Valid(p, 0)) {
				SaveMove(p, 0);
				return 0;
			}
			pass++;

		}else if (12.5 <= random && random < 25){ // move 2
			if(Valid(p, 1)) {
				SaveMove(p, 1);
				return 0;
			}
			pass++;

		}else if (25 <= random && random< 37.5){ // move 3
			if(Valid(p, 2)){
				SaveMove(p, 2);
					return 0;
			}
			pass++;

		}else if (37.5 <= random && random < 50){ // move 4
			if(Valid(p, 3)){
				SaveMove(p, 3);
				return 0;
			}
			pass++;

		}else if (50 <= random && random < 62.5){ // move 5
			if(Valid(p, 4)) {
				SaveMove(p, 4);
				return 0;
			}
			pass++;

		}else if (62.5 <= random && random < 75){ // move 6
			if(Valid(p, 5)) {
				SaveMove(p, 5);
				return 0;
			}
			pass++;

		}else if (75 <= random && random < 87.5){ // move 7
			if(Valid(p, 6)) {
				SaveMove(p, 6);
				return 0;
			}
			pass++;

		}else{
			if(Valid(p, 7)) {
				SaveMove(p, 7);
				return 0;
			}
			pass++;
		}

		random+=12.5;
		if (pass == 8)
			return 1;
	}
}

int Tour(Info p){
	int flag = 0, iter = 0,
			x0 = p.x, y0 = p.y;
	while (1) {
		InitMatrix(p.board, x0, y0);

		int count = 2;
		for (int k = 0; k < size*size; k++){
			int end = walk(p);

			if (end == 1) {
				flag = 0;

				for (int i = 0; i < size; i++) {
					for (int j = 0; j < size; j++) {
						if (p.board[i][j] == 0)
							flag++;
					}
				}

				if (flag == 0) {
					cout << "random is good! Iteration:"<< iter << '\n';
					PrintBoard(p.board);
					return 0;
				}
				break;
			}

			p.board[p.x][p.y] = count;
			count++;
		}

		if(flag != 0){
			p.x=x0;
			p.y=y0;
		}
		iter++;
	}
}

int main(int argc, char const *argv[]){

	cin >> size;

	int nthreads;
	cin >> nthreads;

	vector<Info> p;
	populate(p,nthreads);

	// for (unsigned int i = 0; i < p.size(); i++) {
	//     cout << i << ": x=" << p[i].x << ", y=" << p[i].y << '\n';
 	//    	PrintBoard(p[i].board);
	// }

	thread t[nthreads];
  for (int i = 0; i < nthreads; i++)
      t[i] = thread(Tour, p[i]);

  for (int i = 0; i < nthreads; i++) {
    t[i].join();
  }

	return 0;
}<commit_msg>parallel, but slow<commit_after>#include <iostream>
#include <random>
#include <thread>

using std::cout;
using std::cin;
using std::random_device;
using std::mt19937_64;
using std::uniform_real_distribution;
using std::vector;
using std::thread;

#define SIZEF 500

typedef struct Info{
	int board[SIZEF][SIZEF];
	int x;
	int y;
} Info;

int size;

static const int iPasso[8] = { -2, -1,  1,  2,  2,  1, -1, -2 };
static const int jPasso[8] = {  1,  2,  2,  1, -1, -2, -2, -1 };

double Random(int n){
	//https://stackoverflow.com/questions/5008804/generating-random-integer-from-a-range
	random_device rd;
	mt19937_64 gen(rd());
	//http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution
	uniform_real_distribution<> uni(0,n);
	return uni(gen);
}

void InitMatrix(Info &p, int x, int y){
	for (int i = 0; i < size; ++i){
		for (int j = 0; j < size; ++j){
			p.board[i][j] = 0;
		}
	}
	p.board[x][y] = 1;
}

void PrintBoard(int board[SIZEF][SIZEF]){
	for (int i = 0; i < size; ++i){
		for (int j = 0; j < size; ++j)
			cout << board[i][j] << "\t";
		cout << "\n\n";
	}
}

void populate(vector<Info> &p, int threads){
	int count = 0;

	while (count != threads){
		int flag = 1;
		Info tmp;
		tmp.x = Random(size-1);
		tmp.y = Random(size-1);

		for (unsigned int i = 0; i < p.size(); i++) {
			if (p[i].x == tmp.x && p[i].y == tmp.y) {
				flag = 0;
				break;
			}
		}

		if (flag) {
			InitMatrix(tmp, tmp.x, tmp.y);
			p.push_back(tmp);
			count ++;
		}
	}
}

bool Valid(Info p, int i){
  int x = (p.x) + iPasso[i];
  int y = (p.y) + jPasso[i];

  if( x >= 0 && x < size && y >= 0 && y < size && p.board[x][y] == 0 )
    return true;
  return false;
}

void SaveMove(Info &p, int i){
	// cout << "PRIMEIRO:"<<p.x << '\n';
  p.x+=iPasso[i];
	// cout << "segundo:"<<p.x << '\n';
  p.y+=jPasso[i];
}

int walk(Info &p){
	double random = Random(99.9);
	int pass = 0;

	while(1){
		// PrintBoard(p.board);
		random = fmod(random,100);
		if (0 <= random && random < 12.5) { // move 1
			if(Valid(p, 0)) {
				SaveMove(p, 0);
				return 0;
			}
			pass++;

		}else if (12.5 <= random && random < 25){ // move 2
			if(Valid(p, 1)) {
				SaveMove(p, 1);
				return 0;
			}
			pass++;

		}else if (25 <= random && random< 37.5){ // move 3
			if(Valid(p, 2)){
				SaveMove(p, 2);
					return 0;
			}
			pass++;

		}else if (37.5 <= random && random < 50){ // move 4
			if(Valid(p, 3)){
				SaveMove(p, 3);
				return 0;
			}
			pass++;

		}else if (50 <= random && random < 62.5){ // move 5
			if(Valid(p, 4)) {
				SaveMove(p, 4);
				return 0;
			}
			pass++;

		}else if (62.5 <= random && random < 75){ // move 6
			if(Valid(p, 5)) {
				SaveMove(p, 5);
				return 0;
			}
			pass++;

		}else if (75 <= random && random < 87.5){ // move 7
			if(Valid(p, 6)) {
				SaveMove(p, 6);
				return 0;
			}
			pass++;

		}else{
			if(Valid(p, 7)) {
				SaveMove(p, 7);
				return 0;
			}
			pass++;
		}

		random+=12.5;
		if (pass == 8)
			return 1;
	}
}

void Tour(Info p){
	int flag = 0, iter = 0,
			x0 = p.x, y0 = p.y;
	while (1) {
		InitMatrix(p, x0, y0);

		int count = 2;
		for (int k = 0; k < size*size; k++){
			int end = walk(p);

			if (end == 1) {
				flag = 0;

				for (int i = 0; i < size; i++) {
					for (int j = 0; j < size; j++) {
						if (p.board[i][j] == 0)
							flag++;
					}
				}

				if (flag == 0) {
					cout << "random is good! Iteration:"<< iter << '\n';
					PrintBoard(p.board);
				  return;
				}
				break;
			}

			p.board[p.x][p.y] = count;
			count++;
		}

		if(flag != 0){
			p.x=x0;
			p.y=y0;
		}
		iter++;
	}
}

int main(int argc, char const *argv[]){

	cin >> size;

	int nthreads;
	cin >> nthreads;

	vector<Info> p;
	populate(p,nthreads);

	for (unsigned int i = 0; i < p.size(); i++) {
	    cout << i << ": x=" << p[i].x << ", y=" << p[i].y << '\n';
			//   	PrintBoard(p[i].board);
	}

	thread t[nthreads];
  for (int i = 0; i < nthreads; i++)
      t[i] = thread(Tour, p[i]);
	cout << "Threads em execução" << '\n';
  for (int i = 0; i < nthreads; i++) {
		// cout << "Opa" << '\n';
    t[i].join();
  }
	return 0;
}
<|endoftext|>


<commit_before>#include "cuiserve.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include "json/json_spirit_writer_template.h"
using namespace json_spirit;
bool CUIServer::HasConnection(){
	if(NULL == instance)
		return false;

	return instance->m_bConnect;
}

void CUIServer::StartServer(boost::thread_group & group) {
	group.create_thread(boost::bind(&CUIServer::RunThreadPorc, CUIServer::getInstance()));
}

void CUIServer::StopServer(){
	if(NULL == instance)
		return ;
	instance->m_iosev.stop();
	instance->m_bRunFlag = false;
}

void CUIServer::RunThreadPorc(CUIServer* pThis) {
	if (NULL == pThis)
		return;

	pThis->RunServer();
}

CUIServer* CUIServer::getInstance() {
	if (NULL == instance)
		instance = new CUIServer();
	return instance;
}

void CUIServer::Send(const string& strData) {
	if(NULL == instance)
		return ;
//	LogPrint("TOUI","send message: %s\n", strData);
	string sendData(strData);
	PackageData(sendData);
	LogPrint("TOUI","send message: %s\n", sendData);
	instance->SendData(strData);
}

bool CUIServer::IsInitalEnd = false;
void CUIServer::SendData(const string& strData) {
	system::error_code ignored_error;
	if(m_bConnect&&m_socket.get() ){
		m_socket->write_some(asio::buffer(strData), ignored_error);
	}
}

void CUIServer::Accept() {
	sock_pt sock(new tcp::socket(m_iosev));
	m_acceptor.async_accept(*sock, bind(&CUIServer::Accept_handler, this, sock));
}

void CUIServer::Accept_handler(sock_pt sock) {
	if(m_bConnect)
	{
		//only save one connection
		Accept();
		return;
	}
	m_socket = sock;
	m_bConnect = true;
	Object obj;
	if (CUIServer::IsInitalEnd == true) {
		obj.push_back(Pair("type", "init"));
		obj.push_back(Pair("msg", "initialize end"));
	} else {
		obj.push_back(Pair("type", "hello"));
		obj.push_back(Pair("msg", "hello asio"));
	}

	Accept();
	sock->async_write_some(asio::buffer(write_string(Value(std::move(obj)),true)), bind(&CUIServer::write_handler, this));
	std::shared_ptr<vector<char> > str(new vector<char>(100, 0));
	memset(data_,0,max_length);
	sock->async_read_some(asio::buffer(data_,max_length),
			bind(&CUIServer::read_handler, this, asio::placeholders::error, data_, sock));
}

void CUIServer::read_handler(const system::error_code& ec, char* pstr, sock_pt sock) {
	if (ec) {
		sock->shutdown(boost::asio::ip::tcp::socket::shutdown_both, const_cast<system::error_code&>(ec));
		sock->close(const_cast<system::error_code&>(ec));
		m_bConnect = false;
		return;
	}
}

void CUIServer::RunServer(){
	Accept();
	m_iosev.run();
	if(instance != NULL && !instance->m_bRunFlag) {
		delete instance;
			instance = NULL;
	}
}

CUIServer* CUIServer::instance = NULL;

void CUIServer::PackageData(string &strData) {
	string dataIn("");
	unsigned short nDataLen = strData.length();
	if(0 == nDataLen)
		return;
	char *cLen[3]={0};
	memcpy(cLen, &nDataLen, 2);
	strprintf(dataIn, "<%s%s>", cLen, strData.c_str());
	strData = dataIn;
}
<commit_msg>fixed serverui bug<commit_after>#include "cuiserve.h"
#include "json/json_spirit_utils.h"
#include "json/json_spirit_value.h"
#include "json/json_spirit_writer_template.h"
using namespace json_spirit;
bool CUIServer::HasConnection(){
	if(NULL == instance)
		return false;

	return instance->m_bConnect;
}

void CUIServer::StartServer(boost::thread_group & group) {
	group.create_thread(boost::bind(&CUIServer::RunThreadPorc, CUIServer::getInstance()));
}

void CUIServer::StopServer(){
	if(NULL == instance)
		return ;
	instance->m_iosev.stop();
	instance->m_bRunFlag = false;
}

void CUIServer::RunThreadPorc(CUIServer* pThis) {
	if (NULL == pThis)
		return;

	pThis->RunServer();
}

CUIServer* CUIServer::getInstance() {
	if (NULL == instance)
		instance = new CUIServer();
	return instance;
}

void CUIServer::Send(const string& strData) {
	if(NULL == instance)
		return ;
//	LogPrint("TOUI","send message: %s\n", strData);
	string sendData(strData);
	PackageData(sendData);
	LogPrint("TOUI","send message: %s\n", sendData);
	instance->SendData(strData);
}

bool CUIServer::IsInitalEnd = false;
void CUIServer::SendData(const string& strData) {
	system::error_code ignored_error;
	if(m_bConnect&&m_socket.get() ){
		m_socket->write_some(asio::buffer(strData), ignored_error);
	}
}

void CUIServer::Accept() {
	sock_pt sock(new tcp::socket(m_iosev));
	m_acceptor.async_accept(*sock, bind(&CUIServer::Accept_handler, this, sock));
}

void CUIServer::Accept_handler(sock_pt sock) {
	if(m_bConnect)
	{
		//only save one connection
		Accept();
		return;
	}
	m_socket = sock;
	m_bConnect = true;
	Object obj;
	if (CUIServer::IsInitalEnd == true) {
		obj.push_back(Pair("type", "init"));
		obj.push_back(Pair("msg", "initialize end"));
	} else {
		obj.push_back(Pair("type", "hello"));
		obj.push_back(Pair("msg", "hello asio"));
	}

	Accept();
	string sendData = write_string(Value(std::move(obj)),true);
	PackageData(sendData);
	sock->async_write_some(asio::buffer(sendData), bind(&CUIServer::write_handler, this));
	std::shared_ptr<vector<char> > str(new vector<char>(100, 0));
	memset(data_,0,max_length);
	sock->async_read_some(asio::buffer(data_,max_length),
			bind(&CUIServer::read_handler, this, asio::placeholders::error, data_, sock));
}

void CUIServer::read_handler(const system::error_code& ec, char* pstr, sock_pt sock) {
	if (ec) {
		sock->shutdown(boost::asio::ip::tcp::socket::shutdown_both, const_cast<system::error_code&>(ec));
		sock->close(const_cast<system::error_code&>(ec));
		m_bConnect = false;
		return;
	}
}

void CUIServer::RunServer(){
	Accept();
	m_iosev.run();
	if(instance != NULL && !instance->m_bRunFlag) {
		delete instance;
			instance = NULL;
	}
}

CUIServer* CUIServer::instance = NULL;

void CUIServer::PackageData(string &strData) {
	string dataIn("");
	unsigned short nDataLen = strData.length();
	if(0 == nDataLen)
		return;
	char *cLen[3]={0};
	memcpy(cLen, &nDataLen, 2);
	strprintf(dataIn, "<%s%s>", cLen, strData.c_str());
	strData = dataIn;
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2006, IBM                                               *
 *                                                                         *
 *   Maintained By:                                                        *
 *   Eric Munson and Brad Peters                                           *
 *   munsone@us.ibm.com, bpeters@us.ibm.com                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the Lesser GNU 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 program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Lesser General Public License for more details.                   *
 *                                                                         *
 *   You should have received a copy of the Lesser GNU General Public      *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#define TRACE_ON

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <libvpd-2/dataitem.hpp>
#include <libvpd-2/debug.hpp>

#include <cstring> // for memcpy
#include <ctype.h> // for isspace

using namespace std;

namespace lsvpd
{
	DataItem::DataItem( const DataItem& copyMe ) : humanName( copyMe.humanName ),
		ac( copyMe.ac ), dataValue( copyMe.dataValue ),
		packedLength( 0 ), prefLevelUsed(copyMe.prefLevelUsed)
	{}

	DataItem::DataItem( ) : dataValue( " " ), packedLength( 0 )
	{
		prefLevelUsed = 0;
	}

	DataItem::~DataItem( )
	{
		vector<Source*>::iterator i, end;
		for( i = sources.begin( ), end = sources.end( ); i != end; ++i )
		{
			Source* s = *i;
			delete s;
		}
	}

	int DataItem::getNumSources() const
	{
		return sources.size();
	}

	Source * DataItem::getSource(int i) const
	{
		if (i < getNumSources() || i == 0) {
			return sources[i];
		}
		else {
			return NULL;
		}
	}

	void DataItem::addSource(Source *in)
	{
		vector<Source*>::iterator i, end;
		for( i = sources.begin( ), end = sources.end( ); i != end; ++i )
		{
			if( (*i)->getPrefLvl( ) < in->getPrefLvl( ) )
			{
				sources.insert( i, in );
				return;
			}
		}

		sources.push_back( in );
	}

	void DataItem::removeSource(int i)
	{
		vector<Source*>::iterator cur, end;
		int j = 0;

		for( cur = sources.begin( ), end = sources.end( ); cur != end; ++cur, j++ )
		{
			if( j == i )
			{
				Source * s = *cur;
				sources.erase( cur );
				delete s;
				return;
			}
		}
	}

	const string& DataItem::getHumanName( ) const
	{
		return humanName;
	}

	void DataItem::setHumanName( const string& in )
	{
		humanName = in;
		packedLength = 0;
	}

	const string& DataItem::getAC( ) const
	{
		return ac;
	}

	void DataItem::setAC( const string& in )
	{
		ac = in;
		packedLength = 0;
	}

	const string& DataItem::getValue() const
	{
		return dataValue;
	}

	int DataItem::setValue( const string& in, int prefLevelUsed_t,
									 const char *file, int lineNum)
	{
		unsigned int i;

		if ((prefLevelUsed_t > prefLevelUsed) && (!in.empty()))
		{
			string val( in );
			// Get rid of any NULL bytes, new lines or carriage returns
			i = 0;
			unsigned int pos;
			while( ( pos = val.find( '\0' ) ) != string::npos ||
				( pos = val.find( '\n' ) ) != string::npos ||
				( pos = val.find( '\r' ) ) != string::npos )
			{
				val.erase( pos, 1 );
			}

			// Get rid of leading and trailing whitespace
			for( i = 0; i < val.length( ) && isspace( val.at( i ) ); i++ )
				val.erase( i, 1 );
			for( i = val.length( ) - 1; i >= 0 && isspace( val.at( i ) ); i-- )
				val.erase( i, 1 );

			/*
			if (ac == "AX") {
				coutd << "Attempting to set [" << ac << "]: " << endl
						<< "Request src: " << file<< ", line " << lineNum << endl
						<<" Old PrefLevel: " << prefLevelUsed << endl
						<<" New PrefLevel: " << prefLevelUsed_t << endl
						<< " Old dataVal: " << dataValue << endl
						<<" Attempting to set to dataVal to: '" << in << "'" << endl
						<< endl;
				coutd << "DataVal Set!  New Val: '" << val << "'" << endl;
			}
			*/
			/*
			if (humanName == "Device Bus") {
				coutd << "Attempting to set [" << ac << "]: " << endl
						<< "Request src: " << file<< ", line " << lineNum << endl
						<<" Old PrefLevel: " << prefLevelUsed << endl
						<<" New PrefLevel: " << prefLevelUsed_t << endl
						<< " Old dataVal: " << dataValue << endl
						<<" Attempting to set to dataVal to: '" << in << "'" << endl
						<< endl;
				coutd << "DataVal Set!  New Val: '" << val << "'" << endl;
			}
			*/
			dataValue = val;
			packedLength = 0;
			prefLevelUsed = prefLevelUsed_t;
			return 0;
		}
		else return -1;
	}

	int DataItem::getPrefLevel()
	{
		return prefLevelUsed;
	}

	/**
	 * Method reports the number of bytes that would be required to "serialize" (in the Java
	 * sense of the word) this object into a character buffer.  The result of the computation
	 * is stored to make multiple calls to this method move a little faster.  Each time an item
	 * is changed with a set method, the packedLength member is invalidated, forcing the method
	 * to sum the length again.
	 */
	int DataItem::getPackedLength( )
	{
		if( packedLength != 0 )
			return packedLength;

		int ret = 3; // 3 bytes is the smallest a packed DataItem can be.

		ret += ac.length( );
		ret += humanName.length( );
		ret += dataValue.length( );
		packedLength = ret;

		return ret;
	}

	/**
	 * Like the pack method from Component, this method takes the contents
	 * of this DataItem and packs them into the data buffer provided.  It will return
	 * the number of bytes packed into that buffer.  Each field is followed by a '\0'
	 * character to make unpacking easier.
	 */
	int DataItem::pack( void* buf )
	{
		char * buffer = (char*)buf;
		int ret = getPackedLength( );

		memcpy( buffer, ac.c_str( ), ac.length( ) );
		buffer += ac.length( );

		*buffer = '\0';
		buffer++;

		memcpy( buffer, humanName.c_str( ), humanName.length( ) );
		buffer += humanName.length( );

		*buffer = '\0';
		buffer++;

		memcpy( buffer, dataValue.c_str( ), dataValue.length( ) );
		buffer += dataValue.length( );

		*buffer = '\0';
		buffer++;
		return ret;
	}

	/**
	 * Also like the like-named method within Component, this method loads this
	 * DataItem object from the provided data buffer.
	 */
	void DataItem::unpack( const void * data )
	{
		char * buf = (char*) data;
		ac = buf;
		buf += ( ac.length( ) + 1 );
		humanName = buf;
		buf += ( humanName.length( ) + 1 );
		dataValue = buf;
	}

	/*
	 * Prints this DataItem to the ostream in a meaningful way.
	 */
	/*
	ostream& operator<<( ostream& os, const DataItem& in )
	{
		os << " Human Name: " <<  in.getHumanName() << endl;
		os << "    Acronym: " << in.getAC() << endl;
		os << "      Value: " <<  in.getValue() << endl;

		return os;
	}
	*/
}
<commit_msg>libvpd: Fix out of range issue<commit_after>/***************************************************************************
 *   Copyright (C) 2006, IBM                                               *
 *                                                                         *
 *   Maintained By:                                                        *
 *   Eric Munson and Brad Peters                                           *
 *   munsone@us.ibm.com, bpeters@us.ibm.com                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the Lesser GNU 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 program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Lesser General Public License for more details.                   *
 *                                                                         *
 *   You should have received a copy of the Lesser GNU General Public      *
 *   License along with this program; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#define TRACE_ON

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <libvpd-2/dataitem.hpp>
#include <libvpd-2/debug.hpp>

#include <cstring> // for memcpy
#include <ctype.h> // for isspace

using namespace std;

namespace lsvpd
{
	DataItem::DataItem( const DataItem& copyMe ) : humanName( copyMe.humanName ),
		ac( copyMe.ac ), dataValue( copyMe.dataValue ),
		packedLength( 0 ), prefLevelUsed(copyMe.prefLevelUsed)
	{}

	DataItem::DataItem( ) : dataValue( "" ), packedLength( 0 )
	{
		prefLevelUsed = 0;
	}

	DataItem::~DataItem( )
	{
		vector<Source*>::iterator i, end;
		for( i = sources.begin( ), end = sources.end( ); i != end; ++i )
		{
			Source* s = *i;
			delete s;
		}
	}

	int DataItem::getNumSources() const
	{
		return sources.size();
	}

	Source * DataItem::getSource(int i) const
	{
		if (i < getNumSources() || i == 0) {
			return sources[i];
		}
		else {
			return NULL;
		}
	}

	void DataItem::addSource(Source *in)
	{
		vector<Source*>::iterator i, end;
		for( i = sources.begin( ), end = sources.end( ); i != end; ++i )
		{
			if( (*i)->getPrefLvl( ) < in->getPrefLvl( ) )
			{
				sources.insert( i, in );
				return;
			}
		}

		sources.push_back( in );
	}

	void DataItem::removeSource(int i)
	{
		vector<Source*>::iterator cur, end;
		int j = 0;

		for( cur = sources.begin( ), end = sources.end( ); cur != end; ++cur, j++ )
		{
			if( j == i )
			{
				Source * s = *cur;
				sources.erase( cur );
				delete s;
				return;
			}
		}
	}

	const string& DataItem::getHumanName( ) const
	{
		return humanName;
	}

	void DataItem::setHumanName( const string& in )
	{
		humanName = in;
		packedLength = 0;
	}

	const string& DataItem::getAC( ) const
	{
		return ac;
	}

	void DataItem::setAC( const string& in )
	{
		ac = in;
		packedLength = 0;
	}

	const string& DataItem::getValue() const
	{
		return dataValue;
	}

	int DataItem::setValue( const string& in, int prefLevelUsed_t,
									 const char *file, int lineNum)
	{
		int i;

		if ((prefLevelUsed_t > prefLevelUsed) && (!in.empty()))
		{
			string val( in );
			// Get rid of any NULL bytes, new lines or carriage returns
			i = 0;
			int pos;
			while( ( pos = val.find( '\0' ) ) != (int)string::npos ||
				( pos = val.find( '\n' ) ) != (int)string::npos ||
				( pos = val.find( '\r' ) ) != (int)string::npos )
			{
				val.erase( pos, 1 );
			}

			// Get rid of leading and trailing whitespace
			for( i = 0; i < (int)val.length( ) && isspace( val.at( i ) ); i++ )
				val.erase( i, 1 );
			for( i = val.length( ) - 1; i >= 0 && isspace( val.at( i ) ); i-- )
				val.erase( i, 1 );

			/*
			if (ac == "AX") {
				coutd << "Attempting to set [" << ac << "]: " << endl
						<< "Request src: " << file<< ", line " << lineNum << endl
						<<" Old PrefLevel: " << prefLevelUsed << endl
						<<" New PrefLevel: " << prefLevelUsed_t << endl
						<< " Old dataVal: " << dataValue << endl
						<<" Attempting to set to dataVal to: '" << in << "'" << endl
						<< endl;
				coutd << "DataVal Set!  New Val: '" << val << "'" << endl;
			}
			*/
			/*
			if (humanName == "Device Bus") {
				coutd << "Attempting to set [" << ac << "]: " << endl
						<< "Request src: " << file<< ", line " << lineNum << endl
						<<" Old PrefLevel: " << prefLevelUsed << endl
						<<" New PrefLevel: " << prefLevelUsed_t << endl
						<< " Old dataVal: " << dataValue << endl
						<<" Attempting to set to dataVal to: '" << in << "'" << endl
						<< endl;
				coutd << "DataVal Set!  New Val: '" << val << "'" << endl;
			}
			*/
			dataValue = val;
			packedLength = 0;
			prefLevelUsed = prefLevelUsed_t;
			return 0;
		}
		else return -1;
	}

	int DataItem::getPrefLevel()
	{
		return prefLevelUsed;
	}

	/**
	 * Method reports the number of bytes that would be required to "serialize" (in the Java
	 * sense of the word) this object into a character buffer.  The result of the computation
	 * is stored to make multiple calls to this method move a little faster.  Each time an item
	 * is changed with a set method, the packedLength member is invalidated, forcing the method
	 * to sum the length again.
	 */
	int DataItem::getPackedLength( )
	{
		if( packedLength != 0 )
			return packedLength;

		int ret = 3; // 3 bytes is the smallest a packed DataItem can be.

		ret += ac.length( );
		ret += humanName.length( );
		ret += dataValue.length( );
		packedLength = ret;

		return ret;
	}

	/**
	 * Like the pack method from Component, this method takes the contents
	 * of this DataItem and packs them into the data buffer provided.  It will return
	 * the number of bytes packed into that buffer.  Each field is followed by a '\0'
	 * character to make unpacking easier.
	 */
	int DataItem::pack( void* buf )
	{
		char * buffer = (char*)buf;
		int ret = getPackedLength( );

		memcpy( buffer, ac.c_str( ), ac.length( ) );
		buffer += ac.length( );

		*buffer = '\0';
		buffer++;

		memcpy( buffer, humanName.c_str( ), humanName.length( ) );
		buffer += humanName.length( );

		*buffer = '\0';
		buffer++;

		memcpy( buffer, dataValue.c_str( ), dataValue.length( ) );
		buffer += dataValue.length( );

		*buffer = '\0';
		buffer++;
		return ret;
	}

	/**
	 * Also like the like-named method within Component, this method loads this
	 * DataItem object from the provided data buffer.
	 */
	void DataItem::unpack( const void * data )
	{
		char * buf = (char*) data;
		ac = buf;
		buf += ( ac.length( ) + 1 );
		humanName = buf;
		buf += ( humanName.length( ) + 1 );
		dataValue = buf;
	}

	/*
	 * Prints this DataItem to the ostream in a meaningful way.
	 */
	/*
	ostream& operator<<( ostream& os, const DataItem& in )
	{
		os << " Human Name: " <<  in.getHumanName() << endl;
		os << "    Acronym: " << in.getAC() << endl;
		os << "      Value: " <<  in.getValue() << endl;

		return os;
	}
	*/
}
<|endoftext|>