<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fonthdl.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 14:41:48 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _XMLOFF_PROPERTYHANDLER_FONTTYPES_HXX
#include <fonthdl.hxx>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _VCL_VCLENUM_HXX
#include <vcl/vclenum.hxx>
#endif

#ifndef _XMLOFF_XMLEMENT_HXX
#include "xmlelement.hxx"
#endif

#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::xmloff::token;

static SvXMLEnumMapEntry __READONLY_DATA aFontFamilyGenericMapping[] =
{
    { XML_DECORATIVE,       FAMILY_DECORATIVE },

    { XML_MODERN,           FAMILY_MODERN   },
    { XML_ROMAN,            FAMILY_ROMAN    },
    { XML_SCRIPT,           FAMILY_SCRIPT   },
    { XML_SWISS,            FAMILY_SWISS    },
    { XML_SYSTEM,           FAMILY_SYSTEM   },
    { XML_TOKEN_INVALID,    0               }
};

static SvXMLEnumMapEntry __READONLY_DATA aFontPitchMapping[] =
{
    { XML_FIXED,            PITCH_FIXED     },
    { XML_VARIABLE,         PITCH_VARIABLE  },
    { XML_TOKEN_INVALID,    0               }
};
///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontFamilyNamePropHdl
//

XMLFontFamilyNamePropHdl::~XMLFontFamilyNamePropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontFamilyNamePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    String sValue;
    sal_Int32 nPos = 0;

    do
    {
        sal_Int32 nFirst = nPos;
        nPos = SvXMLUnitConverter::indexOfComma( rStrImpValue, nPos );
        sal_Int32 nLast = (-1 == nPos ? rStrImpValue.getLength() : nPos);
        if( nLast > 0 )
            nLast--;

        // skip trailing blanks
        while( sal_Unicode(' ') == rStrImpValue[nLast] && nLast > nFirst )
            nLast--;

        // skip leading blanks
        while( sal_Unicode(' ') == rStrImpValue[nFirst] && nFirst <= nLast )
            nFirst++;

        // remove quotes
        sal_Unicode c = rStrImpValue[nFirst];
        if( nFirst < nLast && (sal_Unicode('\'') == c || sal_Unicode('\"') == c) && rStrImpValue[nLast] == c )
        {
            nFirst++;
            nLast--;
        }

        if( nFirst <= nLast )
        {
            if( sValue.Len() != 0 )
                sValue += sal_Unicode(';');

            OUString sTemp = rStrImpValue.copy( nFirst, nLast-nFirst+1 );
            sValue += sTemp.getStr();
        }

        if( -1 != nPos )
            nPos++;
    }
    while( -1 != nPos );

    if( sValue.Len() )
    {
        rValue <<= OUString(sValue.GetBuffer());
        bRet = sal_True;
    }

    return bRet;
}

sal_Bool XMLFontFamilyNamePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    OUString aStrFamilyName;

    if( rValue >>= aStrFamilyName )
    {
        OUStringBuffer sValue( aStrFamilyName.getLength() + 2L );
        sal_Int32 nPos = 0L;
        do
        {
            sal_Int32 nFirst = nPos;
            nPos = aStrFamilyName.indexOf( sal_Unicode(';'), nPos );
            sal_Int32 nLast = (-1L == nPos ? aStrFamilyName.getLength() : nPos);

            // Set position to the character behind the ';', so we won't
            // forget this.
            if( -1L != nPos )
                nPos++;

            // If the property value was empty, we stop now.
            // If there is a ';' at the first position, the empty name
            // at the start will be removed.
            if( 0L == nLast )
                continue;

            // nFirst and nLast now denote the first and last character of
            // one font name.
            nLast--;

            // skip trailing blanks
            while( sal_Unicode(' ') == aStrFamilyName[nLast] && nLast > nFirst )
                nLast--;

            // skip leading blanks
            while( sal_Unicode(' ') == aStrFamilyName[nFirst] && nFirst <= nLast )
                nFirst++;

            if( nFirst <= nLast )
            {
                if( sValue.getLength() != 0L )
                {
                    sValue.append( sal_Unicode( ',' ) );
                    sValue.append( sal_Unicode( ' ' ));
                }
                sal_Int32 nLen = nLast-nFirst+1L;
                OUString sFamily( aStrFamilyName.copy( nFirst, nLen ) );
                sal_Bool bQuote = sal_False;
                for( sal_Int32 i=0; i < nLen; i++ )
                {
                    sal_Unicode c = sFamily[i];
                    if( sal_Unicode(' ') == c || sal_Unicode(',') == c )
                    {
                        bQuote = sal_True;
                        break;
                    }
                }
                if( bQuote )
                    sValue.append( sal_Unicode('\'') );
                sValue.append( sFamily );
                if( bQuote )
                    sValue.append( sal_Unicode('\'') );
            }
        }
        while( -1L != nPos );

        rStrExpValue = sValue.makeStringAndClear();

        bRet = sal_True;
    }

    return bRet;
}

///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontFamilyPropHdl
//

XMLFontFamilyPropHdl::~XMLFontFamilyPropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontFamilyPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    sal_uInt16 eNewFamily;

    if( ( bRet = rUnitConverter.convertEnum( eNewFamily, rStrImpValue, aFontFamilyGenericMapping ) ) )
        rValue <<= (sal_Int16)eNewFamily;

    return bRet;
}

sal_Bool XMLFontFamilyPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    OUStringBuffer aOut;

    sal_Int16 nFamily;
    if( rValue >>= nFamily )
    {
        FontFamily eFamily = (FontFamily)nFamily;
        if( eFamily != FAMILY_DONTKNOW )
            bRet = rUnitConverter.convertEnum( aOut, eFamily, aFontFamilyGenericMapping );
    }

    rStrExpValue = aOut.makeStringAndClear();

    return bRet;
}

///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontEncodingPropHdl
//

XMLFontEncodingPropHdl::~XMLFontEncodingPropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontEncodingPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_True;

    if( IsXMLToken( rStrImpValue, XML_X_SYMBOL ) )
        rValue <<= (sal_Int16) RTL_TEXTENCODING_SYMBOL;

    return bRet;
}

sal_Bool XMLFontEncodingPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    OUStringBuffer aOut;
    sal_Int16 nSet;

    if( rValue >>= nSet )
    {
        if( (rtl_TextEncoding)nSet == RTL_TEXTENCODING_SYMBOL )
        {
            aOut.append( GetXMLToken(XML_X_SYMBOL) );
            rStrExpValue = aOut.makeStringAndClear();
            bRet = sal_True;
        }
    }

    return bRet;
}

///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontPitchPropHdl
//

XMLFontPitchPropHdl::~XMLFontPitchPropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontPitchPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    USHORT eNewPitch;

    if( ( bRet = rUnitConverter.convertEnum( eNewPitch, rStrImpValue, aFontPitchMapping ) ) )
        rValue <<= (sal_Int16)eNewPitch;

    return bRet;
}

sal_Bool XMLFontPitchPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    sal_Int16 nPitch;
    OUStringBuffer aOut;

    FontPitch ePitch = PITCH_DONTKNOW;
    if( rValue >>= nPitch )
        ePitch =  (FontPitch)nPitch;

    if( PITCH_DONTKNOW != ePitch )
    {
        bRet = rUnitConverter.convertEnum( aOut, ePitch, aFontPitchMapping, XML_FIXED );
        rStrExpValue = aOut.makeStringAndClear();
    }

    return bRet;
}
<commit_msg>INTEGRATION: CWS warnings01 (1.8.34); FILE MERGED 2005/11/16 22:47:25 pl 1.8.34.1: #i55991# removed warnings<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: fonthdl.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 18:32:40 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

#ifndef _XMLOFF_PROPERTYHANDLER_FONTTYPES_HXX
#include <fonthdl.hxx>
#endif

#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif

#ifndef _RTL_USTRBUF_HXX_
#include <rtl/ustrbuf.hxx>
#endif

#ifndef _COM_SUN_STAR_UNO_ANY_HXX_
#include <com/sun/star/uno/Any.hxx>
#endif

#ifndef _VCL_VCLENUM_HXX
#include <vcl/vclenum.hxx>
#endif

#ifndef _XMLOFF_XMLEMENT_HXX
#include "xmlelement.hxx"
#endif

#ifndef _STRING_HXX
#include <tools/string.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::xmloff::token;

static SvXMLEnumMapEntry __READONLY_DATA aFontFamilyGenericMapping[] =
{
    { XML_DECORATIVE,       FAMILY_DECORATIVE },

    { XML_MODERN,           FAMILY_MODERN   },
    { XML_ROMAN,            FAMILY_ROMAN    },
    { XML_SCRIPT,           FAMILY_SCRIPT   },
    { XML_SWISS,            FAMILY_SWISS    },
    { XML_SYSTEM,           FAMILY_SYSTEM   },
    { XML_TOKEN_INVALID,    0               }
};

static SvXMLEnumMapEntry __READONLY_DATA aFontPitchMapping[] =
{
    { XML_FIXED,            PITCH_FIXED     },
    { XML_VARIABLE,         PITCH_VARIABLE  },
    { XML_TOKEN_INVALID,    0               }
};
///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontFamilyNamePropHdl
//

XMLFontFamilyNamePropHdl::~XMLFontFamilyNamePropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontFamilyNamePropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_False;
    String sValue;
    sal_Int32 nPos = 0;

    do
    {
        sal_Int32 nFirst = nPos;
        nPos = SvXMLUnitConverter::indexOfComma( rStrImpValue, nPos );
        sal_Int32 nLast = (-1 == nPos ? rStrImpValue.getLength() : nPos);
        if( nLast > 0 )
            nLast--;

        // skip trailing blanks
        while( sal_Unicode(' ') == rStrImpValue[nLast] && nLast > nFirst )
            nLast--;

        // skip leading blanks
        while( sal_Unicode(' ') == rStrImpValue[nFirst] && nFirst <= nLast )
            nFirst++;

        // remove quotes
        sal_Unicode c = rStrImpValue[nFirst];
        if( nFirst < nLast && (sal_Unicode('\'') == c || sal_Unicode('\"') == c) && rStrImpValue[nLast] == c )
        {
            nFirst++;
            nLast--;
        }

        if( nFirst <= nLast )
        {
            if( sValue.Len() != 0 )
                sValue += sal_Unicode(';');

            OUString sTemp = rStrImpValue.copy( nFirst, nLast-nFirst+1 );
            sValue += sTemp.getStr();
        }

        if( -1 != nPos )
            nPos++;
    }
    while( -1 != nPos );

    if( sValue.Len() )
    {
        rValue <<= OUString(sValue.GetBuffer());
        bRet = sal_True;
    }

    return bRet;
}

sal_Bool XMLFontFamilyNamePropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_False;
    OUString aStrFamilyName;

    if( rValue >>= aStrFamilyName )
    {
        OUStringBuffer sValue( aStrFamilyName.getLength() + 2L );
        sal_Int32 nPos = 0L;
        do
        {
            sal_Int32 nFirst = nPos;
            nPos = aStrFamilyName.indexOf( sal_Unicode(';'), nPos );
            sal_Int32 nLast = (-1L == nPos ? aStrFamilyName.getLength() : nPos);

            // Set position to the character behind the ';', so we won't
            // forget this.
            if( -1L != nPos )
                nPos++;

            // If the property value was empty, we stop now.
            // If there is a ';' at the first position, the empty name
            // at the start will be removed.
            if( 0L == nLast )
                continue;

            // nFirst and nLast now denote the first and last character of
            // one font name.
            nLast--;

            // skip trailing blanks
            while( sal_Unicode(' ') == aStrFamilyName[nLast] && nLast > nFirst )
                nLast--;

            // skip leading blanks
            while( sal_Unicode(' ') == aStrFamilyName[nFirst] && nFirst <= nLast )
                nFirst++;

            if( nFirst <= nLast )
            {
                if( sValue.getLength() != 0L )
                {
                    sValue.append( sal_Unicode( ',' ) );
                    sValue.append( sal_Unicode( ' ' ));
                }
                sal_Int32 nLen = nLast-nFirst+1L;
                OUString sFamily( aStrFamilyName.copy( nFirst, nLen ) );
                sal_Bool bQuote = sal_False;
                for( sal_Int32 i=0; i < nLen; i++ )
                {
                    sal_Unicode c = sFamily[i];
                    if( sal_Unicode(' ') == c || sal_Unicode(',') == c )
                    {
                        bQuote = sal_True;
                        break;
                    }
                }
                if( bQuote )
                    sValue.append( sal_Unicode('\'') );
                sValue.append( sFamily );
                if( bQuote )
                    sValue.append( sal_Unicode('\'') );
            }
        }
        while( -1L != nPos );

        rStrExpValue = sValue.makeStringAndClear();

        bRet = sal_True;
    }

    return bRet;
}

///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontFamilyPropHdl
//

XMLFontFamilyPropHdl::~XMLFontFamilyPropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontFamilyPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    sal_uInt16 eNewFamily;

    if( ( bRet = rUnitConverter.convertEnum( eNewFamily, rStrImpValue, aFontFamilyGenericMapping ) ) )
        rValue <<= (sal_Int16)eNewFamily;

    return bRet;
}

sal_Bool XMLFontFamilyPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    OUStringBuffer aOut;

    sal_Int16 nFamily;
    if( rValue >>= nFamily )
    {
        FontFamily eFamily = (FontFamily)nFamily;
        if( eFamily != FAMILY_DONTKNOW )
            bRet = rUnitConverter.convertEnum( aOut, eFamily, aFontFamilyGenericMapping );
    }

    rStrExpValue = aOut.makeStringAndClear();

    return bRet;
}

///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontEncodingPropHdl
//

XMLFontEncodingPropHdl::~XMLFontEncodingPropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontEncodingPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_True;

    if( IsXMLToken( rStrImpValue, XML_X_SYMBOL ) )
        rValue <<= (sal_Int16) RTL_TEXTENCODING_SYMBOL;

    return bRet;
}

sal_Bool XMLFontEncodingPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& ) const
{
    sal_Bool bRet = sal_False;
    OUStringBuffer aOut;
    sal_Int16 nSet;

    if( rValue >>= nSet )
    {
        if( (rtl_TextEncoding)nSet == RTL_TEXTENCODING_SYMBOL )
        {
            aOut.append( GetXMLToken(XML_X_SYMBOL) );
            rStrExpValue = aOut.makeStringAndClear();
            bRet = sal_True;
        }
    }

    return bRet;
}

///////////////////////////////////////////////////////////////////////////////
//
// class XMLFontPitchPropHdl
//

XMLFontPitchPropHdl::~XMLFontPitchPropHdl()
{
    // Nothing to do
}

sal_Bool XMLFontPitchPropHdl::importXML( const OUString& rStrImpValue, uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    USHORT eNewPitch;

    if( ( bRet = rUnitConverter.convertEnum( eNewPitch, rStrImpValue, aFontPitchMapping ) ) )
        rValue <<= (sal_Int16)eNewPitch;

    return bRet;
}

sal_Bool XMLFontPitchPropHdl::exportXML( OUString& rStrExpValue, const uno::Any& rValue, const SvXMLUnitConverter& rUnitConverter ) const
{
    sal_Bool bRet = sal_False;
    sal_Int16 nPitch;
    OUStringBuffer aOut;

    FontPitch ePitch = PITCH_DONTKNOW;
    if( rValue >>= nPitch )
        ePitch =  (FontPitch)nPitch;

    if( PITCH_DONTKNOW != ePitch )
    {
        bRet = rUnitConverter.convertEnum( aOut, ePitch, aFontPitchMapping, XML_FIXED );
        rStrExpValue = aOut.makeStringAndClear();
    }

    return bRet;
}
<|endoftext|>


<commit_before>/*
** Copyright 2009-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include <ctime>
#include <limits>
#include <QMutexLocker>
#include <sstream>
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/temporary.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/internal.hh"
#include "com/centreon/broker/multiplexing/subscriber.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::multiplexing;

unsigned int subscriber::_event_queue_max_size = std::numeric_limits<unsigned int>::max();

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] temporary_name Temporary name to build temporary.
 */
subscriber::subscriber(QString const& temporary_name)
  : _process_in(true),
    _process_out(true),
    _recovery_temporary(false),
    _temporary_name(temporary_name),
    _total_events(0) {
  unsigned int size(0);

  {
    QMutexLocker lock2(&_mutex);

    // Register self in subscriber list.
    {
      QMutexLocker lock1(&gl_subscribersm);
      gl_subscribers.push_back(this);
      size = gl_subscribers.size();
    }

    // if necessary load last temporary for recovery.
    _temporary = io::temporary::instance().create(_temporary_name);
    if (_temporary) {
      misc::shared_ptr<io::data> event;
      while (_total_events < event_queue_max_size()) {
        _recovery_temporary = _get_event_from_temporary(event);
        if (!_recovery_temporary) {
          // All temporary event was loaded into the memory event queue.
          // The recovery mode is disable.
          break;
        }
        else {
          // Push temporary event to the memory event queue.
          _events.enqueue(event);
          ++_total_events;
        }
      }
    }
  }

  logging::debug(logging::low)
    << "multiplexing: " << size << " subscribers are registered after "
    "insertion";

  logging::info(logging::low)
    << "multiplexing: start with " << _total_events << " in queue and "
    "the recovery temporary file is "
    << (_recovery_temporary ? "enable" : "disable");
}

/**
 *  Destructor.
 */
subscriber::~subscriber() {
  clean();
  QMutexLocker lock(&gl_subscribersm);
  for (QVector<subscriber*>::iterator it(gl_subscribers.begin());
       it != gl_subscribers.end();)
    if (*it == this)
      it = gl_subscribers.erase(it);
    else
      ++it;
}

/**
 *  Set the maximume event queue size.
 *
 *  @param[in] max The size limit.
 */
void subscriber::event_queue_max_size(unsigned int max) throw () {
  if (!max)
    max = std::numeric_limits<unsigned int>::max();
  _event_queue_max_size = max;
}

/**
 *  Get the maximum event queue size.
 *
 *  @return The size limit.
 */
unsigned int subscriber::event_queue_max_size() throw () {
  return (_event_queue_max_size);
}

/**
 *  Unregister or re-register from event publishing notifications.
 *
 *  @param[in] in  Process input events.
 *  @param[in] out Process output events.
 */
void subscriber::process(bool in, bool out) {
  // Debug message.
  logging::debug(logging::low) << "multiplexing: subscriber "
    "processing request in=" << in << ", out=" << out;

  // Lock mutex.
  QMutexLocker lock(&_mutex);

  // Set data.
  _process_in = in;
  _process_out = (_process_out && out);

  // Unregister.
  if (!in || !out) {
    _cv.wakeAll();
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after deletion";
  }
  // Re-register.
  else if (in && out) {
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after reregistration";
  }

  return ;
}

/**
 *  Get the next available event.
 *
 *  @param[out] d Next available event.
 */
void subscriber::read(misc::shared_ptr<io::data>& d) {
  this->read(d, (time_t)-1);
  return ;
}

/**
 *  Get the next available event without waiting more than timeout.
 *
 *  @param[out] event     Next available event.
 *  @param[in]  timeout   Date limit.
 *  @param[out] timed_out Set to true if read timed out.
 */
void subscriber::read(
                   misc::shared_ptr<io::data>& event,
                   time_t timeout,
                   bool* timed_out) {
  QMutexLocker lock(&_mutex);

  // No data is directly available.
  if (!_total_events) {
    // Wait a while if subscriber was not shutdown.
    if (_process_in && _process_out) {
      if ((time_t)-1 == timeout)
        _cv.wait(&_mutex);
      else {
        time_t now(time(NULL));
        if (now < timeout) {
          bool timedout(!_cv.wait(&_mutex, (timeout - now) * 1000));
          if (timed_out)
            *timed_out = timedout;
        }
        else if (timed_out)
          *timed_out = true;
      }
      if (_total_events) {
        _get_last_event(event);
        lock.unlock();
        logging::debug(logging::low) << "multiplexing: "
          << _total_events << " events remaining in subcriber";
      }
      else
        event.clear();
    }
    // If subscriber is shutdown, notify caller.
    else
      throw (io::exceptions::shutdown(true, true)
             << "thread is shutdown, cannot get any further event");
  }
  // Data is available, no need to wait.
  else {
    if (!_process_in && _process_out)
      throw (io::exceptions::shutdown(true, false)
             << "thread is shutdown, cannot get any further event");
    _get_last_event(event);
    lock.unlock();
    logging::debug(logging::low) << "multiplexing: " << _total_events
      << " events remaining in subscriber";
  }
  return ;
}

/**
 *  Generate statistics about the subscriber.
 *
 *  @param[out] buffer Output buffer.
 */
void subscriber::statistics(std::string& buffer) const {
  QMutexLocker lock(&_mutex);
  std::ostringstream oss;
  if (_recovery_temporary)
    oss << "queued events=unkown";
  else
    oss << "queued events=" << _total_events << "\n";

  char const* enable(_recovery_temporary ? "yes" : "no");
  oss << "temporary recovery mode=" << enable << "\n";

  buffer.append(oss.str());
  return ;
}

/**
 *  Add a new event to the internal event list.
 *
 *  @param[in] event Event to add.
 */
void subscriber::write(misc::shared_ptr<io::data> const& event) {
  {
    QMutexLocker lock(&_mutex);
    // Check if the event queue limit is reach.
    if (_total_events >= event_queue_max_size()) {
      // Try to create temporary if is necessary.
      if (!_temporary)
        _temporary = io::temporary::instance().create(_temporary_name);

      // Check if we have temporary.
      if (_temporary)
        _temporary->write(event);
      else
        _events.enqueue(event);
    }
    else
      _events.enqueue(event);

    // If the recovery mode is disable increase total events.
    if (!_recovery_temporary)
      ++_total_events;
  }
  _cv.wakeOne();
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  Release all events stored within the internal list.
 */
void subscriber::clean() {
  QMutexLocker lock(&_mutex);
  if (_temporary)
    _temporary = misc::shared_ptr<io::stream>();
  _events.clear();
  _recovery_temporary = false;
  _total_events = 0;
  return ;
}

/**
 *  Get event from temporary file. Warning, lock
 *  _mutex before use this function.
 *
 *  @param[out] event The Last event available.
 *
 *  @return True if have event into the temporary.
 */
bool subscriber::_get_event_from_temporary(
                   misc::shared_ptr<io::data>& event) {
  bool ret(false);
  // If temporary exist, try to get the last event.
  if (_temporary) {
    try {
      do {
        _temporary->read(event);
      } while (event.isNull());
      ret = true;
    }
    catch (io::exceptions::shutdown const& e) {
      // The temporary end was reach.
      (void)e;
      _temporary.clear();
      _recovery_temporary = false;
    }
  }
  return (ret);
}

/**
 *  Get the last event available from the internal queue. Warning, lock
 *  _mutex before use this function.
 *
 *  @param[out] event Last event available.
 */
void subscriber::_get_last_event(misc::shared_ptr<io::data>& event) {
  // Try to get the last temporary event.
  if (_get_event_from_temporary(event))
    _events.enqueue(event);

  // If the recovery mode is disable decrease total events.
  if (!_recovery_temporary)
    --_total_events;

  // Get the last avaiable event.
  event = _events.dequeue();
  return ;
}
<commit_msg>Fix typo into the subscriber statistics.<commit_after>/*
** Copyright 2009-2012 Merethis
**
** This file is part of Centreon Broker.
**
** Centreon Broker is free software: you can redistribute it and/or
** modify it under the terms of the GNU General Public License version 2
** as published by the Free Software Foundation.
**
** Centreon Broker 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
** General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with Centreon Broker. If not, see
** <http://www.gnu.org/licenses/>.
*/

#include <cstdlib>
#include <ctime>
#include <limits>
#include <QMutexLocker>
#include <sstream>
#include "com/centreon/broker/io/exceptions/shutdown.hh"
#include "com/centreon/broker/io/temporary.hh"
#include "com/centreon/broker/logging/logging.hh"
#include "com/centreon/broker/multiplexing/internal.hh"
#include "com/centreon/broker/multiplexing/subscriber.hh"

using namespace com::centreon::broker;
using namespace com::centreon::broker::multiplexing;

unsigned int subscriber::_event_queue_max_size = std::numeric_limits<unsigned int>::max();

/**************************************
*                                     *
*           Public Methods            *
*                                     *
**************************************/

/**
 *  Constructor.
 *
 *  @param[in] temporary_name Temporary name to build temporary.
 */
subscriber::subscriber(QString const& temporary_name)
  : _process_in(true),
    _process_out(true),
    _recovery_temporary(false),
    _temporary_name(temporary_name),
    _total_events(0) {
  unsigned int size(0);

  {
    QMutexLocker lock2(&_mutex);

    // Register self in subscriber list.
    {
      QMutexLocker lock1(&gl_subscribersm);
      gl_subscribers.push_back(this);
      size = gl_subscribers.size();
    }

    // if necessary load last temporary for recovery.
    _temporary = io::temporary::instance().create(_temporary_name);
    if (_temporary) {
      misc::shared_ptr<io::data> event;
      while (_total_events < event_queue_max_size()) {
        _recovery_temporary = _get_event_from_temporary(event);
        if (!_recovery_temporary) {
          // All temporary event was loaded into the memory event queue.
          // The recovery mode is disable.
          break;
        }
        else {
          // Push temporary event to the memory event queue.
          _events.enqueue(event);
          ++_total_events;
        }
      }
    }
  }

  logging::debug(logging::low)
    << "multiplexing: " << size << " subscribers are registered after "
    "insertion";

  logging::info(logging::low)
    << "multiplexing: start with " << _total_events << " in queue and "
    "the recovery temporary file is "
    << (_recovery_temporary ? "enable" : "disable");
}

/**
 *  Destructor.
 */
subscriber::~subscriber() {
  clean();
  QMutexLocker lock(&gl_subscribersm);
  for (QVector<subscriber*>::iterator it(gl_subscribers.begin());
       it != gl_subscribers.end();)
    if (*it == this)
      it = gl_subscribers.erase(it);
    else
      ++it;
}

/**
 *  Set the maximume event queue size.
 *
 *  @param[in] max The size limit.
 */
void subscriber::event_queue_max_size(unsigned int max) throw () {
  if (!max)
    max = std::numeric_limits<unsigned int>::max();
  _event_queue_max_size = max;
}

/**
 *  Get the maximum event queue size.
 *
 *  @return The size limit.
 */
unsigned int subscriber::event_queue_max_size() throw () {
  return (_event_queue_max_size);
}

/**
 *  Unregister or re-register from event publishing notifications.
 *
 *  @param[in] in  Process input events.
 *  @param[in] out Process output events.
 */
void subscriber::process(bool in, bool out) {
  // Debug message.
  logging::debug(logging::low) << "multiplexing: subscriber "
    "processing request in=" << in << ", out=" << out;

  // Lock mutex.
  QMutexLocker lock(&_mutex);

  // Set data.
  _process_in = in;
  _process_out = (_process_out && out);

  // Unregister.
  if (!in || !out) {
    _cv.wakeAll();
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after deletion";
  }
  // Re-register.
  else if (in && out) {
    // Log message.
    logging::debug(logging::low) << "multiplexing: "
      << gl_subscribers.size()
      << " subscribers are registered after reregistration";
  }

  return ;
}

/**
 *  Get the next available event.
 *
 *  @param[out] d Next available event.
 */
void subscriber::read(misc::shared_ptr<io::data>& d) {
  this->read(d, (time_t)-1);
  return ;
}

/**
 *  Get the next available event without waiting more than timeout.
 *
 *  @param[out] event     Next available event.
 *  @param[in]  timeout   Date limit.
 *  @param[out] timed_out Set to true if read timed out.
 */
void subscriber::read(
                   misc::shared_ptr<io::data>& event,
                   time_t timeout,
                   bool* timed_out) {
  QMutexLocker lock(&_mutex);

  // No data is directly available.
  if (!_total_events) {
    // Wait a while if subscriber was not shutdown.
    if (_process_in && _process_out) {
      if ((time_t)-1 == timeout)
        _cv.wait(&_mutex);
      else {
        time_t now(time(NULL));
        if (now < timeout) {
          bool timedout(!_cv.wait(&_mutex, (timeout - now) * 1000));
          if (timed_out)
            *timed_out = timedout;
        }
        else if (timed_out)
          *timed_out = true;
      }
      if (_total_events) {
        _get_last_event(event);
        lock.unlock();
        logging::debug(logging::low) << "multiplexing: "
          << _total_events << " events remaining in subcriber";
      }
      else
        event.clear();
    }
    // If subscriber is shutdown, notify caller.
    else
      throw (io::exceptions::shutdown(true, true)
             << "thread is shutdown, cannot get any further event");
  }
  // Data is available, no need to wait.
  else {
    if (!_process_in && _process_out)
      throw (io::exceptions::shutdown(true, false)
             << "thread is shutdown, cannot get any further event");
    _get_last_event(event);
    lock.unlock();
    logging::debug(logging::low) << "multiplexing: " << _total_events
      << " events remaining in subscriber";
  }
  return ;
}

/**
 *  Generate statistics about the subscriber.
 *
 *  @param[out] buffer Output buffer.
 */
void subscriber::statistics(std::string& buffer) const {
  QMutexLocker lock(&_mutex);
  std::ostringstream oss;
  if (_recovery_temporary)
    oss << "queued events=unkown\n";
  else
    oss << "queued events=" << _total_events << "\n";

  char const* enable(_recovery_temporary ? "yes" : "no");
  oss << "temporary recovery mode=" << enable << "\n";

  buffer.append(oss.str());
  return ;
}

/**
 *  Add a new event to the internal event list.
 *
 *  @param[in] event Event to add.
 */
void subscriber::write(misc::shared_ptr<io::data> const& event) {
  {
    QMutexLocker lock(&_mutex);
    // Check if the event queue limit is reach.
    if (_total_events >= event_queue_max_size()) {
      // Try to create temporary if is necessary.
      if (!_temporary)
        _temporary = io::temporary::instance().create(_temporary_name);

      // Check if we have temporary.
      if (_temporary)
        _temporary->write(event);
      else
        _events.enqueue(event);
    }
    else
      _events.enqueue(event);

    // If the recovery mode is disable increase total events.
    if (!_recovery_temporary)
      ++_total_events;
  }
  _cv.wakeOne();
  return ;
}

/**************************************
*                                     *
*           Private Methods           *
*                                     *
**************************************/

/**
 *  Release all events stored within the internal list.
 */
void subscriber::clean() {
  QMutexLocker lock(&_mutex);
  if (_temporary)
    _temporary = misc::shared_ptr<io::stream>();
  _events.clear();
  _recovery_temporary = false;
  _total_events = 0;
  return ;
}

/**
 *  Get event from temporary file. Warning, lock
 *  _mutex before use this function.
 *
 *  @param[out] event The Last event available.
 *
 *  @return True if have event into the temporary.
 */
bool subscriber::_get_event_from_temporary(
                   misc::shared_ptr<io::data>& event) {
  bool ret(false);
  // If temporary exist, try to get the last event.
  if (_temporary) {
    try {
      do {
        _temporary->read(event);
      } while (event.isNull());
      ret = true;
    }
    catch (io::exceptions::shutdown const& e) {
      // The temporary end was reach.
      (void)e;
      _temporary.clear();
      _recovery_temporary = false;
    }
  }
  return (ret);
}

/**
 *  Get the last event available from the internal queue. Warning, lock
 *  _mutex before use this function.
 *
 *  @param[out] event Last event available.
 */
void subscriber::_get_last_event(misc::shared_ptr<io::data>& event) {
  // Try to get the last temporary event.
  if (_get_event_from_temporary(event))
    _events.enqueue(event);

  // If the recovery mode is disable decrease total events.
  if (!_recovery_temporary)
    --_total_events;

  // Get the last avaiable event.
  event = _events.dequeue();
  return ;
}
<|endoftext|>


<commit_before>#include <mesh_converter/mesh_converter.hpp>
#include <zombye/rendering/mesh.hpp>
#include <zombye/rendering/rendering_system.hpp>

namespace zombye {
    mesh::mesh(rendering_system& rendering_system, const std::vector<char>& source, const std::string& file_name) noexcept
    : vbo_{0, GL_STATIC_DRAW}, ibo_{0, GL_STATIC_DRAW} {
        auto data_ptr = source.data();

        auto head = *reinterpret_cast<const header*>(data_ptr);
        if (head.magic != 0x00659CEF) {
            throw std::runtime_error(file_name + " is not an zombye mesh file");
        }
        auto vertex_size = head.vertex_count * sizeof(vertex);
        auto index_size = head.index_count * sizeof(unsigned int);
        auto size = sizeof(header)
            + vertex_size
            + index_size
            + head.submesh_count * sizeof(devtools::submesh);

        if (size != source.size()) {
            throw std::runtime_error(file_name + " has not the apropriate size");
        }
        data_ptr += sizeof(header);

        vbo_.data(vertex_size, data_ptr);
        data_ptr += vertex_size;

        ibo_.data(index_size, data_ptr);
        data_ptr += index_size;

        for (auto i = 0; i < head.submesh_count; ++i) {
            submesh s;

            s.index_count = *reinterpret_cast<const size_t*>(data_ptr);
            data_ptr += sizeof(size_t);
            s.offset = *reinterpret_cast<const size_t*>(data_ptr);
            data_ptr += sizeof(size_t);

            auto texture_id = *reinterpret_cast<const unsigned long*>(data_ptr);
            auto texture_name = std::to_string(texture_id) + ".dds";
            s.diffuse = rendering_system.texture_manager().load("texture/" + texture_name);
            if (!s.diffuse) {
                throw std::runtime_error("could not load texure " + texture_name);
            }
            data_ptr += sizeof(unsigned long);

            texture_id = *reinterpret_cast<const unsigned long*>(data_ptr);
            texture_name = std::to_string(texture_id) + ".dds";
            s.normal = rendering_system.texture_manager().load("texture/" + texture_name);
            if (!s.normal) {
                throw std::runtime_error("could not load texure " + texture_name);
            }
            data_ptr += sizeof(unsigned long);

            texture_id = *reinterpret_cast<const unsigned long*>(data_ptr);
            texture_name = std::to_string(texture_id) + ".dds";
            s.material = rendering_system.texture_manager().load("texture/" + texture_name);
            if (!s.material) {
                throw std::runtime_error("could not load texure " + texture_name);
            }
            data_ptr += sizeof(unsigned long);

            submeshes_.emplace_back(s);
        }

        vao_.bind_index_buffer(ibo_);
        rendering_system.staticmesh_layout().setup_layout(vao_, &vbo_);
    }

    void mesh::draw() const noexcept {
        vao_.bind();
        for (auto& sub : submeshes_) {
            sub.diffuse->bind(0);
            sub.material->bind(1);
            sub.normal->bind(2);
            glDrawElements(GL_TRIANGLES, sub.index_count, GL_UNSIGNED_INT,
                reinterpret_cast<void*>(sub.offset * sizeof(unsigned int)));
        }
    }
}
<commit_msg>print expected size and calculated size in exception if a size missmatch occours during mesh loading<commit_after>#include <mesh_converter/mesh_converter.hpp>
#include <zombye/rendering/mesh.hpp>
#include <zombye/rendering/rendering_system.hpp>

namespace zombye {
    mesh::mesh(rendering_system& rendering_system, const std::vector<char>& source, const std::string& file_name) noexcept
    : vbo_{0, GL_STATIC_DRAW}, ibo_{0, GL_STATIC_DRAW} {
        auto data_ptr = source.data();

        auto head = *reinterpret_cast<const header*>(data_ptr);
        if (head.magic != 0x00659CEF) {
            throw std::runtime_error(file_name + " is not an zombye mesh file");
        }
        auto vertex_size = head.vertex_count * sizeof(vertex);
        auto index_size = head.index_count * sizeof(unsigned int);
        auto size = sizeof(header)
            + vertex_size
            + index_size
            + head.submesh_count * sizeof(devtools::submesh);

        if (size != source.size()) {
            throw std::runtime_error(file_name + " has not the apropriate size. expected size: "
                + std::to_string(source.size()) + " calculated size: " + std::to_string(size));
        }
        data_ptr += sizeof(header);

        vbo_.data(vertex_size, data_ptr);
        data_ptr += vertex_size;

        ibo_.data(index_size, data_ptr);
        data_ptr += index_size;

        for (auto i = 0; i < head.submesh_count; ++i) {
            submesh s;

            s.index_count = *reinterpret_cast<const size_t*>(data_ptr);
            data_ptr += sizeof(size_t);
            s.offset = *reinterpret_cast<const size_t*>(data_ptr);
            data_ptr += sizeof(size_t);

            auto texture_id = *reinterpret_cast<const unsigned long*>(data_ptr);
            auto texture_name = std::to_string(texture_id) + ".dds";
            s.diffuse = rendering_system.texture_manager().load("texture/" + texture_name);
            if (!s.diffuse) {
                throw std::runtime_error("could not load texure " + texture_name);
            }
            data_ptr += sizeof(unsigned long);

            texture_id = *reinterpret_cast<const unsigned long*>(data_ptr);
            texture_name = std::to_string(texture_id) + ".dds";
            s.normal = rendering_system.texture_manager().load("texture/" + texture_name);
            if (!s.normal) {
                throw std::runtime_error("could not load texure " + texture_name);
            }
            data_ptr += sizeof(unsigned long);

            texture_id = *reinterpret_cast<const unsigned long*>(data_ptr);
            texture_name = std::to_string(texture_id) + ".dds";
            s.material = rendering_system.texture_manager().load("texture/" + texture_name);
            if (!s.material) {
                throw std::runtime_error("could not load texure " + texture_name);
            }
            data_ptr += sizeof(unsigned long);

            submeshes_.emplace_back(s);
        }

        vao_.bind_index_buffer(ibo_);
        rendering_system.staticmesh_layout().setup_layout(vao_, &vbo_);
    }

    void mesh::draw() const noexcept {
        vao_.bind();
        for (auto& sub : submeshes_) {
            sub.diffuse->bind(0);
            sub.material->bind(1);
            sub.normal->bind(2);
            glDrawElements(GL_TRIANGLES, sub.index_count, GL_UNSIGNED_INT,
                reinterpret_cast<void*>(sub.offset * sizeof(unsigned int)));
        }
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010-2014 Jeremy Lainé
 * Contact: https://github.com/jlaine/qdjango
 *
 * This file is part of the QDjango Library.
 *
 * 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.
 */

#include <QDebug>
#include <QLocalServer>
#include <QLocalSocket>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUrl>

#include "QDjangoFastCgiServer.h"
#include "QDjangoFastCgiServer_p.h"
#include "QDjangoHttpController.h"
#include "QDjangoHttpRequest.h"
#include "QDjangoHttpRequest_p.h"
#include "QDjangoHttpResponse.h"
#include "QDjangoHttpResponse_p.h"
#include "QDjangoHttpServer.h"
#include "QDjangoUrlResolver.h"

//#define QDJANGO_DEBUG_FCGI

quint16 FCGI_Header_contentLength(FCGI_Header *header)
{
    return (header->contentLengthB1 << 8) | header->contentLengthB0;
}

quint16 FCGI_Header_requestId(FCGI_Header *header)
{
    return (header->requestIdB1 << 8) | header->requestIdB0;
}

void FCGI_Header_setContentLength(FCGI_Header *header, quint16 contentLength)
{
    header->contentLengthB1 = (contentLength >> 8) & 0xff;
    header->contentLengthB0 = (contentLength & 0xff);
}

void FCGI_Header_setRequestId(FCGI_Header *header, quint16 requestId)
{
    header->requestIdB1 = (requestId >> 8) & 0xff;
    header->requestIdB0 = (requestId & 0xff);
}

#ifdef QDJANGO_DEBUG_FCGI
static void hDebug(FCGI_Header *header, const char *dir)
{
    qDebug("--- FCGI Record %s ---", dir);
    qDebug("version: %i", header->version);
    qDebug("type: %i", header->type);
    qDebug("requestId: %i", FCGI_Header_requestId(header));
    qDebug("contentLength: %i", FCGI_Header_contentLength(header));
    qDebug("paddingLength: %i", header->paddingLength);
}
#endif

/// \cond

QDjangoFastCgiConnection::QDjangoFastCgiConnection(QIODevice *device, QDjangoFastCgiServer *server)
    : QObject(server),
    m_device(device),
    m_inputPos(0),
    m_pendingRequest(0),
    m_pendingRequestId(0),
    m_server(server)
{
    bool check;
    Q_UNUSED(check);

    m_device->setParent(this);
    check = connect(m_device, SIGNAL(disconnected()),
                    this, SIGNAL(closed()));
    Q_ASSERT(check);

    check = connect(m_device, SIGNAL(bytesWritten(qint64)),
                    this, SLOT(_q_bytesWritten(qint64)));
    Q_ASSERT(check);

    check = connect(m_device, SIGNAL(readyRead()),
                    this, SLOT(_q_readyRead()));
    Q_ASSERT(check);
}

QDjangoFastCgiConnection::~QDjangoFastCgiConnection()
{
    if (m_pendingRequest)
        delete m_pendingRequest;
}

void QDjangoFastCgiConnection::writeResponse(quint16 requestId, QDjangoHttpResponse *response)
{
    // serialise HTTP response
    QString httpHeader = QString::fromLatin1("Status: %1 %2\r\n").arg(response->d->statusCode).arg(response->d->reasonPhrase);
    QList<QPair<QString, QString> >::ConstIterator it = response->d->headers.constBegin();
    while (it != response->d->headers.constEnd()) {
        httpHeader += (*it).first + QLatin1String(": ") + (*it).second + QLatin1String("\r\n");
        ++it;
    }
    const QByteArray data = httpHeader.toUtf8() + "\r\n" + response->d->body;

    const char *ptr = data.constData();
    FCGI_Header *header = (FCGI_Header*)m_outputBuffer;
    memset(header, 0, FCGI_HEADER_LEN);
    header->version = 1;
    FCGI_Header_setRequestId(header, requestId);

    for (qint64 bytesRemaining = data.size(); ; ) {
        const quint16 contentLength = qMin(bytesRemaining, qint64(32768));

        header->type = FCGI_STDOUT;
        FCGI_Header_setContentLength(header, contentLength);
        memcpy(m_outputBuffer + FCGI_HEADER_LEN, ptr, contentLength);
        m_device->write(m_outputBuffer, FCGI_HEADER_LEN + contentLength);
#ifdef QDJANGO_DEBUG_FCGI
        hDebug(header, "sent");
        qDebug("[STDOUT]");
#endif

        if (contentLength > 0) {
            ptr += contentLength;
            bytesRemaining -= contentLength;
        } else {
            break;
        }
    }

    quint16 contentLength = 8;
    header->type = FCGI_END_REQUEST;
    FCGI_Header_setContentLength(header, contentLength);
    memset(m_outputBuffer + FCGI_HEADER_LEN, 0, contentLength);
    m_device->write(m_outputBuffer, FCGI_HEADER_LEN + contentLength);
#ifdef QDJANGO_DEBUG_FCGI
    hDebug(header, "sent");
    qDebug("[END REQUEST]");
#endif
}

/** When bytes have been written, check whether we need to close
 *  the connection.
 *
 * @param bytes
 */
void QDjangoFastCgiConnection::_q_bytesWritten(qint64 bytes)
{
    Q_UNUSED(bytes);
    if (!m_device->bytesToWrite()) {
#ifdef QDJANGO_DEBUG_FCGI
        qDebug("Closing connection");
#endif
        m_device->close();
        emit closed();
    }
}

void QDjangoFastCgiConnection::_q_readyRead()
{
    while (m_device->bytesAvailable()) {
        // read record header
        if (m_inputPos < FCGI_HEADER_LEN) {
            const qint64 length = m_device->read(m_inputBuffer + m_inputPos, FCGI_HEADER_LEN - m_inputPos);
            if (length < 0) {
                qWarning("Failed to read header from socket");
                m_device->close();
                emit closed();
                return;
            }
            m_inputPos += length;
            if (m_inputPos < FCGI_HEADER_LEN)
                return;
        }

        // read record body
        FCGI_Header *header = (FCGI_Header*)m_inputBuffer;
        const quint16 contentLength = FCGI_Header_contentLength(header);
        const quint16 bodyLength = contentLength + header->paddingLength;
        const qint64 length = m_device->read(m_inputBuffer + m_inputPos, bodyLength + FCGI_HEADER_LEN - m_inputPos);
        if (length < 0) {
            qWarning("Failed to read body from socket");
            m_device->close();
            emit closed();
            return;
        }
        m_inputPos += length;
        if (m_inputPos < FCGI_HEADER_LEN + bodyLength)
            return;
        m_inputPos = 0;

        // process record
#ifdef QDJANGO_DEBUG_FCGI
        hDebug(header, "received");
#endif
        const quint16 requestId = FCGI_Header_requestId(header);
        if (header->type != FCGI_BEGIN_REQUEST && (!m_pendingRequest || requestId != m_pendingRequestId)) {
            qWarning("Received FastCGI frame for an invalid request");
            m_device->close();
            emit closed();
            return;
        }

        char *p = m_inputBuffer + FCGI_HEADER_LEN;
        switch (header->type) {
        case FCGI_BEGIN_REQUEST: {
#ifdef QDJANGO_DEBUG_FCGI
            const quint16 role = (p[0] << 8) | p[1];
            qDebug("[BEGIN REQUEST]");
            qDebug("role: %i", role);
            qDebug("flags: %i", p[2]);
#endif
            if (m_pendingRequest) {
                qWarning("Received FCGI_BEGIN_REQUEST inside a request");
                m_device->close();
                emit closed();
                break;
            }
            m_pendingRequest = new QDjangoHttpRequest;
            m_pendingRequestId = requestId;
            break;
        }
        case FCGI_ABORT_REQUEST:
            m_device->close();
            emit closed();
            break;
        case FCGI_PARAMS:
#ifdef QDJANGO_DEBUG_FCGI
            qDebug("[PARAMS]");
#endif
            while (p < m_inputBuffer + FCGI_HEADER_LEN + contentLength) {
                quint32 nameLength;
                quint32 valueLength;
                if (p[0] >> 7) {
                    nameLength = ((p[0] & 0x7f) << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
                    p += 4;
                } else {
                    nameLength = p[0];
                    p++;
                }
                if (p[0] >> 7) {
                    valueLength = ((p[0] & 0x7f) << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
                    p += 4;
                } else {
                    valueLength = p[0];
                    p++;
                }
                const QByteArray name(p, nameLength);
                p += nameLength;
                const QByteArray value(p, valueLength);
                p += valueLength;

#ifdef QDJANGO_DEBUG_FCGI
                qDebug() << name << ":" << value;
#endif
                if (name == "PATH_INFO") {
                    m_pendingRequest->d->path = QString::fromUtf8(value);
                } else if (name == "REQUEST_URI") {
                    m_pendingRequest->d->path = QUrl(QString::fromUtf8(value)).path();
                } else if (name == "REQUEST_METHOD") {
                    m_pendingRequest->d->method = QString::fromUtf8(value);
                }
                m_pendingRequest->d->meta.insert(QString::fromLatin1(name), QString::fromUtf8(value));
            }
            break;
        case FCGI_STDIN:
#ifdef QDJANGO_DEBUG_FCGI
            qDebug("[STDIN]");
#endif
            if (contentLength) {
                m_pendingRequest->d->buffer.append(p, contentLength);
            } else {
                QDjangoHttpRequest *request = m_pendingRequest;
                const quint16 requestId = m_pendingRequestId;

                m_pendingRequest = 0;
                m_pendingRequestId = 0;

                QDjangoHttpResponse *response = m_server->urls()->respond(*request, request->path());
                writeResponse(requestId, response);
            }
            break;
        default:
            qWarning("Unhandled request type %i", header->type);
            break;
        }
    }
}

/// \endcond

class QDjangoFastCgiServerPrivate
{
public:
    QDjangoFastCgiServerPrivate(QDjangoFastCgiServer *qq);
    QLocalServer *localServer;
    QTcpServer *tcpServer;
    QDjangoUrlResolver *urlResolver;

private:
    QDjangoFastCgiServer *q;
};

QDjangoFastCgiServerPrivate::QDjangoFastCgiServerPrivate(QDjangoFastCgiServer *qq)
    : localServer(0),
    tcpServer(0),
    q(qq)
{
    urlResolver = new QDjangoUrlResolver(q);
}

/** Constructs a new FastCGI server.
 */
QDjangoFastCgiServer::QDjangoFastCgiServer(QObject *parent)
    : QObject(parent)
{
    d = new QDjangoFastCgiServerPrivate(this);
}

/** Destroys the FastCGI server.
 */
QDjangoFastCgiServer::~QDjangoFastCgiServer()
{
    delete d;
}

/** Closes the server. The server will no longer listen for
 *  incoming connections.
 */
void QDjangoFastCgiServer::close()
{
    if (d->localServer)
        d->localServer->close();
    if (d->tcpServer)
        d->tcpServer->close();
}

/** Tells the server to listen for incoming connections on the given
 *  local socket.
 */
bool QDjangoFastCgiServer::listen(const QString &name)
{
    if (!d->localServer) {
        bool check;
        Q_UNUSED(check);

        d->localServer = new QLocalServer(this);
        check = connect(d->localServer, SIGNAL(newConnection()),
                        this, SLOT(_q_newLocalConnection()));
        Q_ASSERT(check);
    }

    return d->localServer->listen(name);
}

/** Tells the server to listen for incoming TCP connections on the given
 *  \a address and \a port.
 */
bool QDjangoFastCgiServer::listen(const QHostAddress &address, quint16 port)
{
    if (!d->tcpServer) {
        bool check;
        Q_UNUSED(check);

        d->tcpServer = new QTcpServer(this);
        check = connect(d->tcpServer, SIGNAL(newConnection()),
                        this, SLOT(_q_newTcpConnection()));
        Q_ASSERT(check);
    }

    return d->tcpServer->listen(address, port);
}

/** Returns the root URL resolver for the server, which dispatches
 *  requests to handlers.
 */
QDjangoUrlResolver* QDjangoFastCgiServer::urls() const
{
    return d->urlResolver;
}

void QDjangoFastCgiServer::_q_newLocalConnection()
{
    bool check;
    Q_UNUSED(check);

    QLocalSocket *socket;
    while ((socket = d->localServer->nextPendingConnection()) != 0) {
#ifdef QDJANGO_DEBUG_FCGI
        qDebug("New local connection");
#endif
        QDjangoFastCgiConnection *connection = new QDjangoFastCgiConnection(socket, this);
        check = connect(connection, SIGNAL(closed()),
                        connection, SLOT(deleteLater()));
        Q_ASSERT(check);
    }
}
void QDjangoFastCgiServer::_q_newTcpConnection()
{
    bool check;
    Q_UNUSED(check);

    QTcpSocket *socket;
    while ((socket = d->tcpServer->nextPendingConnection()) != 0) {
#ifdef QDJANGO_DEBUG_FCGI
        qDebug("New TCP connection");
#endif
        QDjangoFastCgiConnection *connection = new QDjangoFastCgiConnection(socket, this);
        check = connect(connection, SIGNAL(closed()),
                        connection, SLOT(deleteLater()));
        Q_ASSERT(check);
    }
}
<commit_msg>cleanup bad request handling<commit_after>/*
 * Copyright (C) 2010-2014 Jeremy Lainé
 * Contact: https://github.com/jlaine/qdjango
 *
 * This file is part of the QDjango Library.
 *
 * 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.
 */

#include <QDebug>
#include <QLocalServer>
#include <QLocalSocket>
#include <QTcpServer>
#include <QTcpSocket>
#include <QUrl>

#include "QDjangoFastCgiServer.h"
#include "QDjangoFastCgiServer_p.h"
#include "QDjangoHttpController.h"
#include "QDjangoHttpRequest.h"
#include "QDjangoHttpRequest_p.h"
#include "QDjangoHttpResponse.h"
#include "QDjangoHttpResponse_p.h"
#include "QDjangoHttpServer.h"
#include "QDjangoUrlResolver.h"

//#define QDJANGO_DEBUG_FCGI

quint16 FCGI_Header_contentLength(FCGI_Header *header)
{
    return (header->contentLengthB1 << 8) | header->contentLengthB0;
}

quint16 FCGI_Header_requestId(FCGI_Header *header)
{
    return (header->requestIdB1 << 8) | header->requestIdB0;
}

void FCGI_Header_setContentLength(FCGI_Header *header, quint16 contentLength)
{
    header->contentLengthB1 = (contentLength >> 8) & 0xff;
    header->contentLengthB0 = (contentLength & 0xff);
}

void FCGI_Header_setRequestId(FCGI_Header *header, quint16 requestId)
{
    header->requestIdB1 = (requestId >> 8) & 0xff;
    header->requestIdB0 = (requestId & 0xff);
}

#ifdef QDJANGO_DEBUG_FCGI
static void hDebug(FCGI_Header *header, const char *dir)
{
    qDebug("--- FCGI Record %s ---", dir);
    qDebug("version: %i", header->version);
    qDebug("type: %i", header->type);
    qDebug("requestId: %i", FCGI_Header_requestId(header));
    qDebug("contentLength: %i", FCGI_Header_contentLength(header));
    qDebug("paddingLength: %i", header->paddingLength);
}
#endif

/// \cond

QDjangoFastCgiConnection::QDjangoFastCgiConnection(QIODevice *device, QDjangoFastCgiServer *server)
    : QObject(server),
    m_device(device),
    m_inputPos(0),
    m_pendingRequest(0),
    m_pendingRequestId(0),
    m_server(server)
{
    bool check;
    Q_UNUSED(check);

    m_device->setParent(this);
    check = connect(m_device, SIGNAL(disconnected()),
                    this, SIGNAL(closed()));
    Q_ASSERT(check);

    check = connect(m_device, SIGNAL(bytesWritten(qint64)),
                    this, SLOT(_q_bytesWritten(qint64)));
    Q_ASSERT(check);

    check = connect(m_device, SIGNAL(readyRead()),
                    this, SLOT(_q_readyRead()));
    Q_ASSERT(check);
}

QDjangoFastCgiConnection::~QDjangoFastCgiConnection()
{
    if (m_pendingRequest)
        delete m_pendingRequest;
}

void QDjangoFastCgiConnection::writeResponse(quint16 requestId, QDjangoHttpResponse *response)
{
    // serialise HTTP response
    QString httpHeader = QString::fromLatin1("Status: %1 %2\r\n").arg(response->d->statusCode).arg(response->d->reasonPhrase);
    QList<QPair<QString, QString> >::ConstIterator it = response->d->headers.constBegin();
    while (it != response->d->headers.constEnd()) {
        httpHeader += (*it).first + QLatin1String(": ") + (*it).second + QLatin1String("\r\n");
        ++it;
    }
    const QByteArray data = httpHeader.toUtf8() + "\r\n" + response->d->body;

    const char *ptr = data.constData();
    FCGI_Header *header = (FCGI_Header*)m_outputBuffer;
    memset(header, 0, FCGI_HEADER_LEN);
    header->version = 1;
    FCGI_Header_setRequestId(header, requestId);

    for (qint64 bytesRemaining = data.size(); ; ) {
        const quint16 contentLength = qMin(bytesRemaining, qint64(32768));

        header->type = FCGI_STDOUT;
        FCGI_Header_setContentLength(header, contentLength);
        memcpy(m_outputBuffer + FCGI_HEADER_LEN, ptr, contentLength);
        m_device->write(m_outputBuffer, FCGI_HEADER_LEN + contentLength);
#ifdef QDJANGO_DEBUG_FCGI
        hDebug(header, "sent");
        qDebug("[STDOUT]");
#endif

        if (contentLength > 0) {
            ptr += contentLength;
            bytesRemaining -= contentLength;
        } else {
            break;
        }
    }

    quint16 contentLength = 8;
    header->type = FCGI_END_REQUEST;
    FCGI_Header_setContentLength(header, contentLength);
    memset(m_outputBuffer + FCGI_HEADER_LEN, 0, contentLength);
    m_device->write(m_outputBuffer, FCGI_HEADER_LEN + contentLength);
#ifdef QDJANGO_DEBUG_FCGI
    hDebug(header, "sent");
    qDebug("[END REQUEST]");
#endif
}

/** When bytes have been written, check whether we need to close
 *  the connection.
 *
 * @param bytes
 */
void QDjangoFastCgiConnection::_q_bytesWritten(qint64 bytes)
{
    Q_UNUSED(bytes);
    if (!m_device->bytesToWrite()) {
#ifdef QDJANGO_DEBUG_FCGI
        qDebug("Closing connection");
#endif
        m_device->close();
        emit closed();
    }
}

void QDjangoFastCgiConnection::_q_readyRead()
{
    while (m_device->bytesAvailable()) {
        // read record header
        if (m_inputPos < FCGI_HEADER_LEN) {
            const qint64 length = m_device->read(m_inputBuffer + m_inputPos, FCGI_HEADER_LEN - m_inputPos);
            if (length < 0) {
                qWarning("Failed to read header from socket");
                m_device->close();
                emit closed();
                return;
            }
            m_inputPos += length;
            if (m_inputPos < FCGI_HEADER_LEN)
                return;
        }

        // read record body
        FCGI_Header *header = (FCGI_Header*)m_inputBuffer;
        const quint16 contentLength = FCGI_Header_contentLength(header);
        const quint16 bodyLength = contentLength + header->paddingLength;
        const qint64 length = m_device->read(m_inputBuffer + m_inputPos, bodyLength + FCGI_HEADER_LEN - m_inputPos);
        if (length < 0) {
            qWarning("Failed to read body from socket");
            m_device->close();
            emit closed();
            return;
        }
        m_inputPos += length;
        if (m_inputPos < FCGI_HEADER_LEN + bodyLength)
            return;
        m_inputPos = 0;

        // process record
#ifdef QDJANGO_DEBUG_FCGI
        hDebug(header, "received");
#endif
        const quint16 requestId = FCGI_Header_requestId(header);
        if (header->type != FCGI_BEGIN_REQUEST && (!m_pendingRequest || requestId != m_pendingRequestId)) {
            qWarning("Received FastCGI frame for an invalid request %i", requestId);
            m_device->close();
            emit closed();
            return;
        }

        char *p = m_inputBuffer + FCGI_HEADER_LEN;
        switch (header->type) {
        case FCGI_BEGIN_REQUEST: {
#ifdef QDJANGO_DEBUG_FCGI
            const quint16 role = (p[0] << 8) | p[1];
            qDebug("[BEGIN REQUEST]");
            qDebug("role: %i", role);
            qDebug("flags: %i", p[2]);
#endif
            if (m_pendingRequest) {
                qWarning("Received FCGI_BEGIN_REQUEST inside a request");
                m_device->close();
                emit closed();
                return;
            }
            m_pendingRequest = new QDjangoHttpRequest;
            m_pendingRequestId = requestId;
            break;
        }
        case FCGI_ABORT_REQUEST:
#ifdef QDJANGO_DEBUG_FCGI
            qDebug("[ABORT]");
#endif
            m_device->close();
            emit closed();
            return;
        case FCGI_PARAMS:
#ifdef QDJANGO_DEBUG_FCGI
            qDebug("[PARAMS]");
#endif
            while (p < m_inputBuffer + FCGI_HEADER_LEN + contentLength) {
                quint32 nameLength;
                quint32 valueLength;
                if (p[0] >> 7) {
                    nameLength = ((p[0] & 0x7f) << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
                    p += 4;
                } else {
                    nameLength = p[0];
                    p++;
                }
                if (p[0] >> 7) {
                    valueLength = ((p[0] & 0x7f) << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
                    p += 4;
                } else {
                    valueLength = p[0];
                    p++;
                }
                const QByteArray name(p, nameLength);
                p += nameLength;
                const QByteArray value(p, valueLength);
                p += valueLength;

#ifdef QDJANGO_DEBUG_FCGI
                qDebug() << name << ":" << value;
#endif
                if (name == "PATH_INFO") {
                    m_pendingRequest->d->path = QString::fromUtf8(value);
                } else if (name == "REQUEST_URI") {
                    m_pendingRequest->d->path = QUrl(QString::fromUtf8(value)).path();
                } else if (name == "REQUEST_METHOD") {
                    m_pendingRequest->d->method = QString::fromUtf8(value);
                }
                m_pendingRequest->d->meta.insert(QString::fromLatin1(name), QString::fromUtf8(value));
            }
            break;
        case FCGI_STDIN:
#ifdef QDJANGO_DEBUG_FCGI
            qDebug("[STDIN]");
#endif
            if (contentLength) {
                m_pendingRequest->d->buffer.append(p, contentLength);
            } else {
                QDjangoHttpRequest *request = m_pendingRequest;
                const quint16 requestId = m_pendingRequestId;

                m_pendingRequest = 0;
                m_pendingRequestId = 0;

                QDjangoHttpResponse *response = m_server->urls()->respond(*request, request->path());
                writeResponse(requestId, response);
            }
            break;
        default:
            qWarning("Received FastCGI frame with an invalid type %i", header->type);
            m_device->close();
            emit closed();
            return;
        }
    }
}

/// \endcond

class QDjangoFastCgiServerPrivate
{
public:
    QDjangoFastCgiServerPrivate(QDjangoFastCgiServer *qq);
    QLocalServer *localServer;
    QTcpServer *tcpServer;
    QDjangoUrlResolver *urlResolver;

private:
    QDjangoFastCgiServer *q;
};

QDjangoFastCgiServerPrivate::QDjangoFastCgiServerPrivate(QDjangoFastCgiServer *qq)
    : localServer(0),
    tcpServer(0),
    q(qq)
{
    urlResolver = new QDjangoUrlResolver(q);
}

/** Constructs a new FastCGI server.
 */
QDjangoFastCgiServer::QDjangoFastCgiServer(QObject *parent)
    : QObject(parent)
{
    d = new QDjangoFastCgiServerPrivate(this);
}

/** Destroys the FastCGI server.
 */
QDjangoFastCgiServer::~QDjangoFastCgiServer()
{
    delete d;
}

/** Closes the server. The server will no longer listen for
 *  incoming connections.
 */
void QDjangoFastCgiServer::close()
{
    if (d->localServer)
        d->localServer->close();
    if (d->tcpServer)
        d->tcpServer->close();
}

/** Tells the server to listen for incoming connections on the given
 *  local socket.
 */
bool QDjangoFastCgiServer::listen(const QString &name)
{
    if (!d->localServer) {
        bool check;
        Q_UNUSED(check);

        d->localServer = new QLocalServer(this);
        check = connect(d->localServer, SIGNAL(newConnection()),
                        this, SLOT(_q_newLocalConnection()));
        Q_ASSERT(check);
    }

    return d->localServer->listen(name);
}

/** Tells the server to listen for incoming TCP connections on the given
 *  \a address and \a port.
 */
bool QDjangoFastCgiServer::listen(const QHostAddress &address, quint16 port)
{
    if (!d->tcpServer) {
        bool check;
        Q_UNUSED(check);

        d->tcpServer = new QTcpServer(this);
        check = connect(d->tcpServer, SIGNAL(newConnection()),
                        this, SLOT(_q_newTcpConnection()));
        Q_ASSERT(check);
    }

    return d->tcpServer->listen(address, port);
}

/** Returns the root URL resolver for the server, which dispatches
 *  requests to handlers.
 */
QDjangoUrlResolver* QDjangoFastCgiServer::urls() const
{
    return d->urlResolver;
}

void QDjangoFastCgiServer::_q_newLocalConnection()
{
    bool check;
    Q_UNUSED(check);

    QLocalSocket *socket;
    while ((socket = d->localServer->nextPendingConnection()) != 0) {
#ifdef QDJANGO_DEBUG_FCGI
        qDebug("New local connection");
#endif
        QDjangoFastCgiConnection *connection = new QDjangoFastCgiConnection(socket, this);
        check = connect(connection, SIGNAL(closed()),
                        connection, SLOT(deleteLater()));
        Q_ASSERT(check);
    }
}
void QDjangoFastCgiServer::_q_newTcpConnection()
{
    bool check;
    Q_UNUSED(check);

    QTcpSocket *socket;
    while ((socket = d->tcpServer->nextPendingConnection()) != 0) {
#ifdef QDJANGO_DEBUG_FCGI
        qDebug("New TCP connection");
#endif
        QDjangoFastCgiConnection *connection = new QDjangoFastCgiConnection(socket, this);
        check = connect(connection, SIGNAL(closed()),
                        connection, SLOT(deleteLater()));
        Q_ASSERT(check);
    }
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: txtdropi.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: obo $ $Date: 2006-09-17 11:17:05 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _COM_SUN_STAR_STYLE_DROPCAPFORMAT_HPP_
#include <com/sun/star/style/DropCapFormat.hpp>
#endif
#ifndef _TXTDROPI_HXX
#include "txtdropi.hxx"
#endif
#ifndef _XMLOFF_XMLTKMAP_HXX
#include "xmltkmap.hxx"
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include "xmluconv.hxx"
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include "nmspmap.hxx"
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLIMP_HXX
#include "xmlimp.hxx"
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include "xmltoken.hxx"
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::style;
using namespace ::xmloff::token;

enum SvXMLTokenMapDropAttrs
{
    XML_TOK_DROP_LINES,
    XML_TOK_DROP_LENGTH,
    XML_TOK_DROP_DISTANCE,
    XML_TOK_DROP_STYLE,
    XML_TOK_DROP_END=XML_TOK_UNKNOWN
};

static __FAR_DATA SvXMLTokenMapEntry aDropAttrTokenMap[] =
{
    { XML_NAMESPACE_STYLE, XML_LINES,       XML_TOK_DROP_LINES  },
    { XML_NAMESPACE_STYLE, XML_LENGTH,      XML_TOK_DROP_LENGTH },
    { XML_NAMESPACE_STYLE, XML_DISTANCE,    XML_TOK_DROP_DISTANCE   },
    { XML_NAMESPACE_STYLE, XML_STYLE_NAME,  XML_TOK_DROP_STYLE  },
    XML_TOKEN_MAP_END
};

TYPEINIT1( XMLTextDropCapImportContext, XMLElementPropertyContext );
void XMLTextDropCapImportContext::ProcessAttrs(
        const Reference< xml::sax::XAttributeList >& xAttrList )
{
    SvXMLTokenMap aTokenMap( aDropAttrTokenMap );

    DropCapFormat aFormat;
    sal_Bool bWholeWord = sal_False;

    sal_Int32 nTmp;
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        switch( aTokenMap.Get( nPrefix, aLocalName ) )
        {
        case XML_TOK_DROP_LINES:
            if( GetImport().GetMM100UnitConverter().convertNumber( nTmp, rValue, 0, 255 ) )
            {
                aFormat.Lines = nTmp < 2 ? 0 : (sal_Int8)nTmp;
            }
            break;

        case XML_TOK_DROP_LENGTH:
            if( IsXMLToken( rValue, XML_WORD ) )
            {
                bWholeWord = sal_True;
            }
            else if( GetImport().GetMM100UnitConverter().convertNumber( nTmp, rValue, 1, 255 ) )
            {
                bWholeWord = sal_False;
                aFormat.Count = (sal_Int8)nTmp;
            }
            break;

        case XML_TOK_DROP_DISTANCE:
            if( GetImport().GetMM100UnitConverter().convertMeasure( nTmp, rValue, 0 ) )
            {
                aFormat.Distance = (sal_uInt16)nTmp;
            }
            break;

        case XML_TOK_DROP_STYLE:
            sStyleName = rValue;
            break;
        }
    }

    if( aFormat.Lines > 1 && aFormat.Count < 1 )
        aFormat.Count = 1;

    aProp.maValue <<= aFormat;

    aWholeWordProp.maValue.setValue( &bWholeWord, ::getBooleanCppuType() );
}

XMLTextDropCapImportContext::XMLTextDropCapImportContext(
        SvXMLImport& rImport, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList > & xAttrList,
        const XMLPropertyState& rProp,
        sal_Int32 nWholeWordIdx,
        ::std::vector< XMLPropertyState > &rProps ) :
    XMLElementPropertyContext( rImport, nPrfx, rLName, rProp, rProps ),
    aWholeWordProp( nWholeWordIdx )
{
    ProcessAttrs( xAttrList );
}

XMLTextDropCapImportContext::~XMLTextDropCapImportContext()
{
}

void XMLTextDropCapImportContext::EndElement()
{
    SetInsert( sal_True );
    XMLElementPropertyContext::EndElement();

    if( -1 != aWholeWordProp.mnIndex )
        rProperties.push_back( aWholeWordProp );
}

<commit_msg>INTEGRATION: CWS vgbugs07 (1.5.124); FILE MERGED 2007/06/04 13:23:40 vg 1.5.124.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: txtdropi.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:13:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _COM_SUN_STAR_STYLE_DROPCAPFORMAT_HPP_
#include <com/sun/star/style/DropCapFormat.hpp>
#endif
#ifndef _TXTDROPI_HXX
#include "txtdropi.hxx"
#endif
#ifndef _XMLOFF_XMLTKMAP_HXX
#include <xmloff/xmltkmap.hxx>
#endif
#ifndef _XMLOFF_XMLUCONV_HXX
#include <xmloff/xmluconv.hxx>
#endif
#ifndef _XMLOFF_NMSPMAP_HXX
#include <xmloff/nmspmap.hxx>
#endif
#ifndef _XMLOFF_XMLNMSPE_HXX
#include "xmlnmspe.hxx"
#endif
#ifndef _XMLOFF_XMLIMP_HXX
#include <xmloff/xmlimp.hxx>
#endif
#ifndef _XMLOFF_XMLTOKEN_HXX
#include <xmloff/xmltoken.hxx>
#endif

using namespace ::rtl;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::style;
using namespace ::xmloff::token;

enum SvXMLTokenMapDropAttrs
{
    XML_TOK_DROP_LINES,
    XML_TOK_DROP_LENGTH,
    XML_TOK_DROP_DISTANCE,
    XML_TOK_DROP_STYLE,
    XML_TOK_DROP_END=XML_TOK_UNKNOWN
};

static __FAR_DATA SvXMLTokenMapEntry aDropAttrTokenMap[] =
{
    { XML_NAMESPACE_STYLE, XML_LINES,       XML_TOK_DROP_LINES  },
    { XML_NAMESPACE_STYLE, XML_LENGTH,      XML_TOK_DROP_LENGTH },
    { XML_NAMESPACE_STYLE, XML_DISTANCE,    XML_TOK_DROP_DISTANCE   },
    { XML_NAMESPACE_STYLE, XML_STYLE_NAME,  XML_TOK_DROP_STYLE  },
    XML_TOKEN_MAP_END
};

TYPEINIT1( XMLTextDropCapImportContext, XMLElementPropertyContext );
void XMLTextDropCapImportContext::ProcessAttrs(
        const Reference< xml::sax::XAttributeList >& xAttrList )
{
    SvXMLTokenMap aTokenMap( aDropAttrTokenMap );

    DropCapFormat aFormat;
    sal_Bool bWholeWord = sal_False;

    sal_Int32 nTmp;
    sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0;
    for( sal_Int16 i=0; i < nAttrCount; i++ )
    {
        const OUString& rAttrName = xAttrList->getNameByIndex( i );
        OUString aLocalName;
        sal_uInt16 nPrefix =
            GetImport().GetNamespaceMap().GetKeyByAttrName( rAttrName,
                                                            &aLocalName );
        const OUString& rValue = xAttrList->getValueByIndex( i );

        switch( aTokenMap.Get( nPrefix, aLocalName ) )
        {
        case XML_TOK_DROP_LINES:
            if( GetImport().GetMM100UnitConverter().convertNumber( nTmp, rValue, 0, 255 ) )
            {
                aFormat.Lines = nTmp < 2 ? 0 : (sal_Int8)nTmp;
            }
            break;

        case XML_TOK_DROP_LENGTH:
            if( IsXMLToken( rValue, XML_WORD ) )
            {
                bWholeWord = sal_True;
            }
            else if( GetImport().GetMM100UnitConverter().convertNumber( nTmp, rValue, 1, 255 ) )
            {
                bWholeWord = sal_False;
                aFormat.Count = (sal_Int8)nTmp;
            }
            break;

        case XML_TOK_DROP_DISTANCE:
            if( GetImport().GetMM100UnitConverter().convertMeasure( nTmp, rValue, 0 ) )
            {
                aFormat.Distance = (sal_uInt16)nTmp;
            }
            break;

        case XML_TOK_DROP_STYLE:
            sStyleName = rValue;
            break;
        }
    }

    if( aFormat.Lines > 1 && aFormat.Count < 1 )
        aFormat.Count = 1;

    aProp.maValue <<= aFormat;

    aWholeWordProp.maValue.setValue( &bWholeWord, ::getBooleanCppuType() );
}

XMLTextDropCapImportContext::XMLTextDropCapImportContext(
        SvXMLImport& rImport, sal_uInt16 nPrfx,
        const OUString& rLName,
        const Reference< xml::sax::XAttributeList > & xAttrList,
        const XMLPropertyState& rProp,
        sal_Int32 nWholeWordIdx,
        ::std::vector< XMLPropertyState > &rProps ) :
    XMLElementPropertyContext( rImport, nPrfx, rLName, rProp, rProps ),
    aWholeWordProp( nWholeWordIdx )
{
    ProcessAttrs( xAttrList );
}

XMLTextDropCapImportContext::~XMLTextDropCapImportContext()
{
}

void XMLTextDropCapImportContext::EndElement()
{
    SetInsert( sal_True );
    XMLElementPropertyContext::EndElement();

    if( -1 != aWholeWordProp.mnIndex )
        rProperties.push_back( aWholeWordProp );
}

<|endoftext|>