<commit_before>//
// Copyright (c) 2010-2012 Linaro Limited
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the MIT License which accompanies
// this distribution, and is available at
// http://www.opensource.org/licenses/mit-license.php
//
// Contributors:
//     Alexandros Frantzis <alexandros.frantzis@linaro.org>
//     Jesse Barker <jesse.barker@linaro.org>
//
#include <cstdio>
#include <cstdarg>
#include <string>
#include <sstream>
#include <iostream>
#include "log.h"

#ifdef ANDROID
#include <android/log.h>
#endif

using std::string;

const string Log::continuation_prefix("\x10");
string Log::appname;
bool Log::do_debug_(false);

#ifndef ANDROID

static const string terminal_color_normal("\033[0m");
static const string terminal_color_red("\033[1;31m");
static const string terminal_color_cyan("\033[36m");
static const string terminal_color_yellow("\033[33m");
static const string empty;

static void
print_prefixed_message(std::ostream& stream, const string& color, const string& prefix,
                       const string& fmt, va_list ap)
{
    va_list aq;

    /* Estimate message size */
    va_copy(aq, ap);
    int msg_size = vsnprintf(NULL, 0, fmt.c_str(), aq);
    va_end(aq);

    /* Create the buffer to hold the message */
    char *buf = new char[msg_size + 1];

    /* Store the message in the buffer */
    va_copy(aq, ap);
    vsnprintf(buf, msg_size + 1, fmt.c_str(), aq);
    va_end(aq);

    /*
     * Print the message lines prefixed with the supplied prefix.
     * If the target stream is a terminal make the prefix colored.
     */
    string linePrefix;
    if (!prefix.empty())
    {
        static const string colon(": ");
        string start_color;
        string end_color;
        if (!color.empty())
        {
            start_color = color;
            if (color[0] != 0)
            {
                end_color = terminal_color_normal;
            }
        }
        linePrefix = start_color + prefix + end_color + colon;
    }

    std::string line;
    std::stringstream ss(buf);

    while(std::getline(ss, line)) {
        /*
         * If this line is a continuation of a previous log message
         * just print the line plainly.
         */
        if (line[0] == Log::continuation_prefix[0]) {
            stream << line.c_str() + 1;
        }
        else {
            /* Normal line, emit the prefix. */
            stream << linePrefix << line;
        }

        /* Only emit a newline if the original message has it. */
        if (!(ss.rdstate() & std::stringstream::eofbit))
            stream << std::endl;
    }

    delete[] buf;
}

void
Log::info(const char *fmt, ...)
{
    static const string infoprefix("Info");
    static const string& infocolor(isatty(fileno(stdout)) ? terminal_color_cyan : empty);
    va_list ap;
    va_start(ap, fmt);
    if (do_debug_)
        print_prefixed_message(std::cout, infocolor, infoprefix, fmt, ap);
    else
        print_prefixed_message(std::cout, empty, empty, fmt, ap);
    va_end(ap);
}

void
Log::debug(const char *fmt, ...)
{
    static const string dbgprefix("Debug");
    static const string& dbgcolor(isatty(fileno(stdout)) ? terminal_color_yellow : empty);
    if (!do_debug_)
        return;
    va_list ap;
    va_start(ap, fmt);
    print_prefixed_message(std::cout, dbgcolor, dbgprefix, fmt, ap);
    va_end(ap);
}

void
Log::error(const char *fmt, ...)
{
    static const string errprefix("Error");
    static const string& errcolor(isatty(fileno(stderr)) ? terminal_color_red : empty);
    va_list ap;
    va_start(ap, fmt);
    print_prefixed_message(std::cerr, errcolor, errprefix, fmt, ap);
    va_end(ap);
}

void
Log::flush()
{
    std::cout.flush();
    std::cerr.flush();
}
#else
void
Log::info(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    __android_log_vprint(ANDROID_LOG_INFO, appname.c_str(), fmt, ap);
    va_end(ap);
}q

void
Log::debug(const char *fmt, ...)
{
    if (!Options::show_debug)
        return;
    va_list ap;
    va_start(ap, fmt);
    __android_log_vprint(ANDROID_LOG_DEBUG, appname.c_str(), fmt, ap);
    va_end(ap);
}

void
Log::error(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    __android_log_vprint(ANDROID_LOG_ERROR, appname.c_str(), fmt, ap);
    va_end(ap);
}

void
Log::flush()
{
}

#endif
<commit_msg>log: Remove stray character<commit_after>//
// Copyright (c) 2010-2012 Linaro Limited
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the MIT License which accompanies
// this distribution, and is available at
// http://www.opensource.org/licenses/mit-license.php
//
// Contributors:
//     Alexandros Frantzis <alexandros.frantzis@linaro.org>
//     Jesse Barker <jesse.barker@linaro.org>
//
#include <cstdio>
#include <cstdarg>
#include <string>
#include <sstream>
#include <iostream>
#include "log.h"

#ifdef ANDROID
#include <android/log.h>
#endif

using std::string;

const string Log::continuation_prefix("\x10");
string Log::appname;
bool Log::do_debug_(false);

#ifndef ANDROID

static const string terminal_color_normal("\033[0m");
static const string terminal_color_red("\033[1;31m");
static const string terminal_color_cyan("\033[36m");
static const string terminal_color_yellow("\033[33m");
static const string empty;

static void
print_prefixed_message(std::ostream& stream, const string& color, const string& prefix,
                       const string& fmt, va_list ap)
{
    va_list aq;

    /* Estimate message size */
    va_copy(aq, ap);
    int msg_size = vsnprintf(NULL, 0, fmt.c_str(), aq);
    va_end(aq);

    /* Create the buffer to hold the message */
    char *buf = new char[msg_size + 1];

    /* Store the message in the buffer */
    va_copy(aq, ap);
    vsnprintf(buf, msg_size + 1, fmt.c_str(), aq);
    va_end(aq);

    /*
     * Print the message lines prefixed with the supplied prefix.
     * If the target stream is a terminal make the prefix colored.
     */
    string linePrefix;
    if (!prefix.empty())
    {
        static const string colon(": ");
        string start_color;
        string end_color;
        if (!color.empty())
        {
            start_color = color;
            if (color[0] != 0)
            {
                end_color = terminal_color_normal;
            }
        }
        linePrefix = start_color + prefix + end_color + colon;
    }

    std::string line;
    std::stringstream ss(buf);

    while(std::getline(ss, line)) {
        /*
         * If this line is a continuation of a previous log message
         * just print the line plainly.
         */
        if (line[0] == Log::continuation_prefix[0]) {
            stream << line.c_str() + 1;
        }
        else {
            /* Normal line, emit the prefix. */
            stream << linePrefix << line;
        }

        /* Only emit a newline if the original message has it. */
        if (!(ss.rdstate() & std::stringstream::eofbit))
            stream << std::endl;
    }

    delete[] buf;
}

void
Log::info(const char *fmt, ...)
{
    static const string infoprefix("Info");
    static const string& infocolor(isatty(fileno(stdout)) ? terminal_color_cyan : empty);
    va_list ap;
    va_start(ap, fmt);
    if (do_debug_)
        print_prefixed_message(std::cout, infocolor, infoprefix, fmt, ap);
    else
        print_prefixed_message(std::cout, empty, empty, fmt, ap);
    va_end(ap);
}

void
Log::debug(const char *fmt, ...)
{
    static const string dbgprefix("Debug");
    static const string& dbgcolor(isatty(fileno(stdout)) ? terminal_color_yellow : empty);
    if (!do_debug_)
        return;
    va_list ap;
    va_start(ap, fmt);
    print_prefixed_message(std::cout, dbgcolor, dbgprefix, fmt, ap);
    va_end(ap);
}

void
Log::error(const char *fmt, ...)
{
    static const string errprefix("Error");
    static const string& errcolor(isatty(fileno(stderr)) ? terminal_color_red : empty);
    va_list ap;
    va_start(ap, fmt);
    print_prefixed_message(std::cerr, errcolor, errprefix, fmt, ap);
    va_end(ap);
}

void
Log::flush()
{
    std::cout.flush();
    std::cerr.flush();
}
#else
void
Log::info(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    __android_log_vprint(ANDROID_LOG_INFO, appname.c_str(), fmt, ap);
    va_end(ap);
}

void
Log::debug(const char *fmt, ...)
{
    if (!Options::show_debug)
        return;
    va_list ap;
    va_start(ap, fmt);
    __android_log_vprint(ANDROID_LOG_DEBUG, appname.c_str(), fmt, ap);
    va_end(ap);
}

void
Log::error(const char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    __android_log_vprint(ANDROID_LOG_ERROR, appname.c_str(), fmt, ap);
    va_end(ap);
}

void
Log::flush()
{
}

#endif
<|endoftext|>


<commit_before><commit_msg>Include trivial definition of method in release mode (where we don't do tracking)<commit_after><|endoftext|>


<commit_before><commit_msg>introduced Date::IsValidDate() and Date::Normalize()<commit_after><|endoftext|>


<commit_before>#ifndef BLOCK_MASKS_HPP__
#define BLOCK_MASKS_HPP__

#include <cassert>

namespace clotho {
namespace utility {

template < class Block >
class block_masks {
public:
    static const unsigned int bits_per_block = sizeof( Block ) * 8;

    typedef Block block_type;
    typedef Block mask_type;

    static const mask_type (&lookupLowBitMask())[bits_per_block] {
        static bool i = init_low_order(low_order_bit_masks);
        assert( i );
        return low_order_bit_masks;
    }

    static const mask_type (&lookupPositionMask())[bits_per_block] {
        static bool i = init_positions(bit_position_masks);
        assert( i );
        return bit_position_masks;
    }

    static mask_type low_order_mask( unsigned int idx ) {
        assert( idx < bits_per_block );
        return ((idx == bits_per_block - 1) ? (mask_type)-1 : (( (mask_type)1 << (idx + 1) ) - 1));
    }

    static mask_type position_mask( unsigned int idx ) {
        assert( idx < bits_per_block );
        return ((mask_type)1 << idx);
    }

private:

    ///  LOW_BIT_MASK => bits_{[0, n]} = 1
    static mask_type low_order_bit_masks[ bits_per_block ];

    /// OFFSET_BIT_MASK => bit_[n] = 1
    static mask_type bit_position_masks[ bits_per_block ];

    static bool init_low_order( mask_type * masks ) {
        for( unsigned int i = 0; i < bits_per_block; ++i ) {
            (*masks++) = low_order_mask( i );
        }
        return true;
    }

    static bool init_positions( mask_type * masks ) {
        for( unsigned int i = 0; i < bits_per_block; ++i ) {
            (*masks++) = position_mask( i );
        }
        return true;
    }
};

template < class Block >
typename block_masks< Block >::mask_type block_masks< Block >::low_order_bit_masks[ block_masks< Block >::bits_per_block ];

template < class Block >
typename block_masks< Block >::mask_type block_masks< Block >::bit_position_masks[ block_masks< Block >::bits_per_block ];
}   // namespace utility {
}   // namespace clotho {
#endif  // BLOCK_MASKS_HPP__
<commit_msg>Formatting<commit_after>#ifndef BLOCK_MASKS_HPP__
#define BLOCK_MASKS_HPP__

#include <cassert>

namespace clotho {
namespace utility {

template < class Block >
class block_masks {
public:
    static const unsigned int bits_per_block = sizeof( Block ) * 8;

    typedef Block block_type;
    typedef Block mask_type;

    static const mask_type (&lookupLowBitMask())[bits_per_block] {
        static bool i = init_low_order(low_order_bit_masks);
        assert( i );
        return low_order_bit_masks;
    }

    static const mask_type (&lookupPositionMask())[bits_per_block] {
        static bool i = init_positions(bit_position_masks);
        assert( i );
        return bit_position_masks;
    }

    static mask_type low_order_mask( unsigned int idx ) {
        assert( idx < bits_per_block );
        return ((idx == bits_per_block - 1) ? (mask_type)-1 : (( (mask_type)1 << (idx + 1) ) - 1));
    }

    static mask_type position_mask( unsigned int idx ) {
        assert( idx < bits_per_block );
        return ((mask_type)1 << idx);
    }

private:

    ///  LOW_BIT_MASK => bits_{[0, n]} = 1
    static mask_type low_order_bit_masks[ bits_per_block ];

    /// OFFSET_BIT_MASK => bit_[n] = 1
    static mask_type bit_position_masks[ bits_per_block ];

    static bool init_low_order( mask_type * masks ) {
        for( unsigned int i = 0; i < bits_per_block; ++i ) {
            (*masks++) = low_order_mask( i );
        }
        return true;
    }

    static bool init_positions( mask_type * masks ) {
        for( unsigned int i = 0; i < bits_per_block; ++i ) {
            (*masks++) = position_mask( i );
        }
        return true;
    }
};

template < class Block >
typename block_masks< Block >::mask_type block_masks< Block >::low_order_bit_masks[ block_masks< Block >::bits_per_block ];

template < class Block >
typename block_masks< Block >::mask_type block_masks< Block >::bit_position_masks[ block_masks< Block >::bits_per_block ];
}   // namespace utility {
}   // namespace clotho {
#endif  // BLOCK_MASKS_HPP__
<|endoftext|>


<commit_before>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program 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 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 GNU Lesser 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, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreFileSystem.h"
#include "OgreLogManager.h"
#include "OgreException.h"
#include "OgreStringVector.h"
#include "OgreRoot.h"

#include <sys/types.h>
#include <sys/stat.h>

#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#   include "OgreSearchOps.h"
#   include <sys/param.h>
#   define MAX_PATH MAXPATHLEN
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#   include <windows.h>
#   include <direct.h>
#   include <io.h>
#endif

namespace Ogre {

	bool FileSystemArchive::ms_IgnoreHidden = true;

    //-----------------------------------------------------------------------
    FileSystemArchive::FileSystemArchive(const String& name, const String& archType )
        : Archive(name, archType)
    {
    }
    //-----------------------------------------------------------------------
    bool FileSystemArchive::isCaseSensitive(void) const
    {
        #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            return false;
        #else
            return true;
        #endif

    }
    //-----------------------------------------------------------------------
    static bool is_reserved_dir (const char *fn)
    {
        return (fn [0] == '.' && (fn [1] == 0 || (fn [1] == '.' && fn [2] == 0)));
    }
    //-----------------------------------------------------------------------
    static bool is_absolute_path(const char* path)
    {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        if (isalpha(uchar(path[0])) && path[1] == ':')
            return true;
#endif
        return path[0] == '/' || path[0] == '\\';
    }
    //-----------------------------------------------------------------------
    static String concatenate_path(const String& base, const String& name)
    {
        if (base.empty() || is_absolute_path(name.c_str()))
            return name;
        else
            return base + '/' + name;
    }
    //-----------------------------------------------------------------------
    void FileSystemArchive::findFiles(const String& pattern, bool recursive,
        bool dirs, StringVector* simpleList, FileInfoList* detailList)
    {
        long lHandle, res;
        struct _finddata_t tagData;

        // pattern can contain a directory name, separate it from mask
        size_t pos1 = pattern.rfind ('/');
        size_t pos2 = pattern.rfind ('\\');
        if (pos1 == pattern.npos || ((pos2 != pattern.npos) && (pos1 < pos2)))
            pos1 = pos2;
        String directory;
        if (pos1 != pattern.npos)
            directory = pattern.substr (0, pos1 + 1);

        String full_pattern = concatenate_path(mName, pattern);

        lHandle = _findfirst(full_pattern.c_str(), &tagData);
        res = 0;
        while (lHandle != -1 && res != -1)
        {
            if ((dirs == ((tagData.attrib & _A_SUBDIR) != 0)) &&
				( !ms_IgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0 ) &&
                (!dirs || !is_reserved_dir (tagData.name)))
            {
                if (simpleList)
                {
                    simpleList->push_back(directory + tagData.name);
                }
                else if (detailList)
                {
                    FileInfo fi;
                    fi.archive = this;
                    fi.filename = directory + tagData.name;
                    fi.basename = tagData.name;
                    fi.path = directory;
                    fi.compressedSize = tagData.size;
                    fi.uncompressedSize = tagData.size;
                    detailList->push_back(fi);
                }
            }
            res = _findnext( lHandle, &tagData );
        }
        // Close if we found any files
        if(lHandle != -1)
            _findclose(lHandle);

        // Now find directories
        if (recursive)
        {
            String base_dir = mName;
            if (!directory.empty ())
            {
                base_dir = concatenate_path(mName, directory);
                // Remove the last '/'
                base_dir.erase (base_dir.length () - 1);
            }
            base_dir.append ("/*");

            // Remove directory name from pattern
            String mask ("/");
            if (pos1 != pattern.npos)
                mask.append (pattern.substr (pos1 + 1));
            else
                mask.append (pattern);

            lHandle = _findfirst(base_dir.c_str (), &tagData);
            res = 0;
            while (lHandle != -1 && res != -1)
            {
                if ((tagData.attrib & _A_SUBDIR) &&
					( !ms_IgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0 ) &&
                    !is_reserved_dir (tagData.name))
                {
                    // recurse
                    base_dir = directory;
                    base_dir.append (tagData.name).append (mask);
                    findFiles(base_dir, recursive, dirs, simpleList, detailList);
                }
                res = _findnext( lHandle, &tagData );
            }
            // Close if we found any files
            if(lHandle != -1)
                _findclose(lHandle);
        }
    }
    //-----------------------------------------------------------------------
    FileSystemArchive::~FileSystemArchive()
    {
        unload();
    }
    //-----------------------------------------------------------------------
    void FileSystemArchive::load()
    {
        // do nothing here, what has to be said will be said later
    }
    //-----------------------------------------------------------------------
    void FileSystemArchive::unload()
    {
        // nothing to see here, move along
    }
    //-----------------------------------------------------------------------
    DataStreamPtr FileSystemArchive::open(const String& filename) const
    {
        String full_path = concatenate_path(mName, filename);

        // Use filesystem to determine size
        // (quicker than streaming to the end and back)
        struct stat tagStat;
	int ret = stat(full_path.c_str(), &tagStat);
        assert(ret == 0 && "Problem getting file size" );

        // Always open in binary mode
        std::ifstream *origStream = new std::ifstream();
        origStream->open(full_path.c_str(), std::ios::in | std::ios::binary);

        // Should check ensure open succeeded, in case fail for some reason.
        if (origStream->fail())
        {
            delete origStream;
            OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,
                "Cannot open file: " + filename,
                "FileSystemArchive::open");
        }

        /// Construct return stream, tell it to delete on destroy
        FileStreamDataStream* stream = new FileStreamDataStream(filename,
            origStream, tagStat.st_size, true);
        return DataStreamPtr(stream);
    }
    //-----------------------------------------------------------------------
    StringVectorPtr FileSystemArchive::list(bool recursive, bool dirs)
    {
		// directory change requires locking due to saved returns
        StringVectorPtr ret(new StringVector());

        findFiles("*", recursive, dirs, ret.getPointer(), 0);

        return ret;
    }
    //-----------------------------------------------------------------------
    FileInfoListPtr FileSystemArchive::listFileInfo(bool recursive, bool dirs)
    {
        FileInfoListPtr ret(new FileInfoList());

        findFiles("*", recursive, dirs, 0, ret.getPointer());

        return ret;
    }
    //-----------------------------------------------------------------------
    StringVectorPtr FileSystemArchive::find(const String& pattern,
                                            bool recursive, bool dirs)
    {
        StringVectorPtr ret(new StringVector());

        findFiles(pattern, recursive, dirs, ret.getPointer(), 0);

        return ret;

    }
    //-----------------------------------------------------------------------
    FileInfoListPtr FileSystemArchive::findFileInfo(const String& pattern,
        bool recursive, bool dirs)
    {
        FileInfoListPtr ret(new FileInfoList());

        findFiles(pattern, recursive, dirs, 0, ret.getPointer());

        return ret;
    }
    //-----------------------------------------------------------------------
	bool FileSystemArchive::exists(const String& filename)
	{
        String full_path = concatenate_path(mName, filename);

        struct stat tagStat;
        bool ret = (stat(full_path.c_str(), &tagStat) == 0);

		// stat will return true if the filename is absolute, but we need to check
		// the file is actually in this archive
        if (ret && is_absolute_path(filename.c_str()))
		{
			// only valid if full path starts with our base
			ret = Ogre::StringUtil::startsWith(full_path, mName);
		}

		return ret;
	}
    //-----------------------------------------------------------------------
    const String& FileSystemArchiveFactory::getType(void) const
    {
        static String name = "FileSystem";
        return name;
    }

}
<commit_msg>Directory comparisons should be case insensitive on non-Windows platforms<commit_after>/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html

This program 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 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 GNU Lesser 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, or go to
http://www.gnu.org/copyleft/lesser.txt.

You may alternatively use this source under the terms of a specific version of
the OGRE Unrestricted License provided you have obtained such a license from
Torus Knot Software Ltd.
-----------------------------------------------------------------------------
*/
#include "OgreStableHeaders.h"
#include "OgreFileSystem.h"
#include "OgreLogManager.h"
#include "OgreException.h"
#include "OgreStringVector.h"
#include "OgreRoot.h"

#include <sys/types.h>
#include <sys/stat.h>

#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
#   include "OgreSearchOps.h"
#   include <sys/param.h>
#   define MAX_PATH MAXPATHLEN
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#   include <windows.h>
#   include <direct.h>
#   include <io.h>
#endif

namespace Ogre {

	bool FileSystemArchive::ms_IgnoreHidden = true;

    //-----------------------------------------------------------------------
    FileSystemArchive::FileSystemArchive(const String& name, const String& archType )
        : Archive(name, archType)
    {
    }
    //-----------------------------------------------------------------------
    bool FileSystemArchive::isCaseSensitive(void) const
    {
        #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            return false;
        #else
            return true;
        #endif

    }
    //-----------------------------------------------------------------------
    static bool is_reserved_dir (const char *fn)
    {
        return (fn [0] == '.' && (fn [1] == 0 || (fn [1] == '.' && fn [2] == 0)));
    }
    //-----------------------------------------------------------------------
    static bool is_absolute_path(const char* path)
    {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
        if (isalpha(uchar(path[0])) && path[1] == ':')
            return true;
#endif
        return path[0] == '/' || path[0] == '\\';
    }
    //-----------------------------------------------------------------------
    static String concatenate_path(const String& base, const String& name)
    {
        if (base.empty() || is_absolute_path(name.c_str()))
            return name;
        else
            return base + '/' + name;
    }
    //-----------------------------------------------------------------------
    void FileSystemArchive::findFiles(const String& pattern, bool recursive,
        bool dirs, StringVector* simpleList, FileInfoList* detailList)
    {
        long lHandle, res;
        struct _finddata_t tagData;

        // pattern can contain a directory name, separate it from mask
        size_t pos1 = pattern.rfind ('/');
        size_t pos2 = pattern.rfind ('\\');
        if (pos1 == pattern.npos || ((pos2 != pattern.npos) && (pos1 < pos2)))
            pos1 = pos2;
        String directory;
        if (pos1 != pattern.npos)
            directory = pattern.substr (0, pos1 + 1);

        String full_pattern = concatenate_path(mName, pattern);

        lHandle = _findfirst(full_pattern.c_str(), &tagData);
        res = 0;
        while (lHandle != -1 && res != -1)
        {
            if ((dirs == ((tagData.attrib & _A_SUBDIR) != 0)) &&
				( !ms_IgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0 ) &&
                (!dirs || !is_reserved_dir (tagData.name)))
            {
                if (simpleList)
                {
                    simpleList->push_back(directory + tagData.name);
                }
                else if (detailList)
                {
                    FileInfo fi;
                    fi.archive = this;
                    fi.filename = directory + tagData.name;
                    fi.basename = tagData.name;
                    fi.path = directory;
                    fi.compressedSize = tagData.size;
                    fi.uncompressedSize = tagData.size;
                    detailList->push_back(fi);
                }
            }
            res = _findnext( lHandle, &tagData );
        }
        // Close if we found any files
        if(lHandle != -1)
            _findclose(lHandle);

        // Now find directories
        if (recursive)
        {
            String base_dir = mName;
            if (!directory.empty ())
            {
                base_dir = concatenate_path(mName, directory);
                // Remove the last '/'
                base_dir.erase (base_dir.length () - 1);
            }
            base_dir.append ("/*");

            // Remove directory name from pattern
            String mask ("/");
            if (pos1 != pattern.npos)
                mask.append (pattern.substr (pos1 + 1));
            else
                mask.append (pattern);

            lHandle = _findfirst(base_dir.c_str (), &tagData);
            res = 0;
            while (lHandle != -1 && res != -1)
            {
                if ((tagData.attrib & _A_SUBDIR) &&
					( !ms_IgnoreHidden || (tagData.attrib & _A_HIDDEN) == 0 ) &&
                    !is_reserved_dir (tagData.name))
                {
                    // recurse
                    base_dir = directory;
                    base_dir.append (tagData.name).append (mask);
                    findFiles(base_dir, recursive, dirs, simpleList, detailList);
                }
                res = _findnext( lHandle, &tagData );
            }
            // Close if we found any files
            if(lHandle != -1)
                _findclose(lHandle);
        }
    }
    //-----------------------------------------------------------------------
    FileSystemArchive::~FileSystemArchive()
    {
        unload();
    }
    //-----------------------------------------------------------------------
    void FileSystemArchive::load()
    {
        // do nothing here, what has to be said will be said later
    }
    //-----------------------------------------------------------------------
    void FileSystemArchive::unload()
    {
        // nothing to see here, move along
    }
    //-----------------------------------------------------------------------
    DataStreamPtr FileSystemArchive::open(const String& filename) const
    {
        String full_path = concatenate_path(mName, filename);

        // Use filesystem to determine size
        // (quicker than streaming to the end and back)
        struct stat tagStat;
	int ret = stat(full_path.c_str(), &tagStat);
        assert(ret == 0 && "Problem getting file size" );

        // Always open in binary mode
        std::ifstream *origStream = new std::ifstream();
        origStream->open(full_path.c_str(), std::ios::in | std::ios::binary);

        // Should check ensure open succeeded, in case fail for some reason.
        if (origStream->fail())
        {
            delete origStream;
            OGRE_EXCEPT(Exception::ERR_FILE_NOT_FOUND,
                "Cannot open file: " + filename,
                "FileSystemArchive::open");
        }

        /// Construct return stream, tell it to delete on destroy
        FileStreamDataStream* stream = new FileStreamDataStream(filename,
            origStream, tagStat.st_size, true);
        return DataStreamPtr(stream);
    }
    //-----------------------------------------------------------------------
    StringVectorPtr FileSystemArchive::list(bool recursive, bool dirs)
    {
		// directory change requires locking due to saved returns
        StringVectorPtr ret(new StringVector());

        findFiles("*", recursive, dirs, ret.getPointer(), 0);

        return ret;
    }
    //-----------------------------------------------------------------------
    FileInfoListPtr FileSystemArchive::listFileInfo(bool recursive, bool dirs)
    {
        FileInfoListPtr ret(new FileInfoList());

        findFiles("*", recursive, dirs, 0, ret.getPointer());

        return ret;
    }
    //-----------------------------------------------------------------------
    StringVectorPtr FileSystemArchive::find(const String& pattern,
                                            bool recursive, bool dirs)
    {
        StringVectorPtr ret(new StringVector());

        findFiles(pattern, recursive, dirs, ret.getPointer(), 0);

        return ret;

    }
    //-----------------------------------------------------------------------
    FileInfoListPtr FileSystemArchive::findFileInfo(const String& pattern,
        bool recursive, bool dirs)
    {
        FileInfoListPtr ret(new FileInfoList());

        findFiles(pattern, recursive, dirs, 0, ret.getPointer());

        return ret;
    }
    //-----------------------------------------------------------------------
	bool FileSystemArchive::exists(const String& filename)
	{
        String full_path = concatenate_path(mName, filename);

        struct stat tagStat;
        bool ret = (stat(full_path.c_str(), &tagStat) == 0);

		// stat will return true if the filename is absolute, but we need to check
		// the file is actually in this archive
        if (ret && is_absolute_path(filename.c_str()))
		{
			// only valid if full path starts with our base
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
			bool caseInsensitive = true;
#else
			bool caseInsensitive = false;
#endif
			ret = Ogre::StringUtil::startsWith(full_path, mName, caseInsensitive);
		}

		return ret;
	}
    //-----------------------------------------------------------------------
    const String& FileSystemArchiveFactory::getType(void) const
    {
        static String name = "FileSystem";
        return name;
    }

}
<|endoftext|>


<commit_before>// 01TextView.cpp : implementation of the CMy01TextView class
//

#include "stdafx.h"
#include "01Text.h"

#include "01TextDoc.h"
#include "01TextView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView

IMPLEMENT_DYNCREATE(CMy01TextView, CView)

BEGIN_MESSAGE_MAP(CMy01TextView, CView)
	//{{AFX_MSG_MAP(CMy01TextView)
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView construction/destruction

CMy01TextView::CMy01TextView()
{
	// TODO: add construction code here

}

CMy01TextView::~CMy01TextView()
{
}

BOOL CMy01TextView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView drawing

void CMy01TextView::OnDraw(CDC* pDC)
{
	CMy01TextDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
    CString str("VC++ ");
    pDC->TextOut(50, 50, str);

    // ַԴַ
    str.LoadString(IDS_STRINGVC);
    pDC->TextOut(100, 100, str);

    // ·㣬ַΧ
    CSize sz = pDC->GetTextExtent(str);
    pDC->BeginPath();
    pDC->Rectangle(CRect(100, 100, 100 + sz.cx, 100 + sz.cy));
    pDC->EndPath();
}

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView printing

BOOL CMy01TextView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMy01TextView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMy01TextView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView diagnostics

#ifdef _DEBUG
void CMy01TextView::AssertValid() const
{
	CView::AssertValid();
}

void CMy01TextView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMy01TextDoc* CMy01TextView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy01TextDoc)));
	return (CMy01TextDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView message handlers

int CMy01TextView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO: Add your specialized creation code here
    // ֲܶʲôʾ
    // CBitmap bitmap;
    m_bitmap.LoadBitmap(IDB_BITMAP1);
    CreateCaret(&m_bitmap);
    ShowCaret();

	return 0;
}
<commit_msg><需求实现>使视类中的绘图操作对路径层所在的区域无效 需求： 使视类中的绘图操作对路径层所在的区域无效 实现： 以RGN_DIFF模式选择路径层为裁剪区<commit_after>// 01TextView.cpp : implementation of the CMy01TextView class
//

#include "stdafx.h"
#include "01Text.h"

#include "01TextDoc.h"
#include "01TextView.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView

IMPLEMENT_DYNCREATE(CMy01TextView, CView)

BEGIN_MESSAGE_MAP(CMy01TextView, CView)
	//{{AFX_MSG_MAP(CMy01TextView)
	ON_WM_CREATE()
	//}}AFX_MSG_MAP
	// Standard printing commands
	ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
	ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView construction/destruction

CMy01TextView::CMy01TextView()
{
	// TODO: add construction code here

}

CMy01TextView::~CMy01TextView()
{
}

BOOL CMy01TextView::PreCreateWindow(CREATESTRUCT& cs)
{
	// TODO: Modify the Window class or styles here by modifying
	//  the CREATESTRUCT cs

	return CView::PreCreateWindow(cs);
}

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView drawing

void CMy01TextView::OnDraw(CDC* pDC)
{
	CMy01TextDoc* pDoc = GetDocument();
	ASSERT_VALID(pDoc);
	// TODO: add draw code for native data here
    CString str("VC++ ");
    pDC->TextOut(50, 50, str);

    // ַԴַ
    str.LoadString(IDS_STRINGVC);
    pDC->TextOut(100, 100, str);

    // ·㣬ַΧ
    CSize sz = pDC->GetTextExtent(str);
    pDC->BeginPath();
    pDC->Rectangle(CRect(100, 100, 100 + sz.cx, 100 + sz.cy));
    pDC->EndPath();

    pDC->SelectClipPath(RGN_DIFF);
    // еĻͼӰ쵽·ˡ

    for(int i = 0; i < 300; i += 10)
    {
        pDC->MoveTo(0, i);
        pDC->LineTo(300, i);

        pDC->MoveTo(i, 0);
        pDC->LineTo(i, 300);
    }
}

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView printing

BOOL CMy01TextView::OnPreparePrinting(CPrintInfo* pInfo)
{
	// default preparation
	return DoPreparePrinting(pInfo);
}

void CMy01TextView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add extra initialization before printing
}

void CMy01TextView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/)
{
	// TODO: add cleanup after printing
}

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView diagnostics

#ifdef _DEBUG
void CMy01TextView::AssertValid() const
{
	CView::AssertValid();
}

void CMy01TextView::Dump(CDumpContext& dc) const
{
	CView::Dump(dc);
}

CMy01TextDoc* CMy01TextView::GetDocument() // non-debug version is inline
{
	ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMy01TextDoc)));
	return (CMy01TextDoc*)m_pDocument;
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CMy01TextView message handlers

int CMy01TextView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
	if (CView::OnCreate(lpCreateStruct) == -1)
		return -1;

	// TODO: Add your specialized creation code here
    // ֲܶʲôʾ
    // CBitmap bitmap;
    m_bitmap.LoadBitmap(IDB_BITMAP1);
    CreateCaret(&m_bitmap);
    ShowCaret();

	return 0;
}
<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include <iostream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include "bit_index_storage.hpp"

using std::pair;
using std::stringstream;
using std::string;
using std::vector;

namespace jubatus {
namespace core {
namespace storage {

bit_vector make_vector(const string& b) {
  bit_vector v;
  v.resize_and_clear(b.size());
  for (size_t i = 0; i < b.size(); ++i) {
    if (b[i] == '1') {
      v.set_bit(i);
    }
  }
  return v;
}

TEST(bit_index_storage, trivial) {
  bit_index_storage s;
  EXPECT_EQ("bit_index_storage", s.name());

  s.set_row("r1", make_vector("0101"));
  s.set_row("r2", make_vector("1010"));
  s.set_row("r3", make_vector("1110"));
  s.set_row("r4", make_vector("1100"));

  vector<pair<string, float> > ids;
  s.similar_row(make_vector("1100"), ids, 2);

  ASSERT_EQ(2u, ids.size());
  EXPECT_EQ("r4", ids[0].first);
  EXPECT_FLOAT_EQ(1.0, ids[0].second);
  EXPECT_EQ("r3", ids[1].first);
  EXPECT_FLOAT_EQ(0.75, ids[1].second);

  msgpack::sbuffer buf;
  msgpack::packer<msgpack::sbuffer> packer(buf);
  s.pack(packer);
  bit_index_storage t;
  msgpack::unpacked unpacked;
  msgpack::unpack(&unpacked, buf.data(), buf.size());
  t.unpack(unpacked.get());
  ids.clear();
  t.similar_row(make_vector("1100"), ids, 2);
  ASSERT_EQ(2u, ids.size());
  EXPECT_EQ("r4", ids[0].first);

  s.remove_row("r4");
  ids.clear();
  s.similar_row(make_vector("1100"), ids, 2);
  EXPECT_NE("r4", ids[0].first);

  s.clear();
  ids.clear();
  s.similar_row(make_vector("1100"), ids, 2);
  EXPECT_TRUE(ids.empty());
}

TEST(bit_index_storage, diff) {
  bit_index_storage s1, s2;
  s1.set_row("r1", make_vector("0101"));
  s1.set_row("r2", make_vector("1010"));
  bit_table_t d1;
  s1.get_diff(d1);

  s2.set_mixed_and_clear_diff(d1);
  bit_vector v;
  s2.get_row("r1", v);
  EXPECT_TRUE(make_vector("0101") == v);

  v.resize_and_clear(4);
  s2.get_row("r2", v);
  EXPECT_TRUE(make_vector("1010") == v);
}

TEST(bit_index_storage, mix) {
  bit_index_storage s1, s2, s3;
  s1.set_row("r1", make_vector("0101"));
  s1.set_row("r2", make_vector("1010"));
  bit_table_t d1;
  s1.get_diff(d1);

  s2.set_row("r1", make_vector("1110"));
  s2.set_row("r3", make_vector("1100"));
  bit_table_t d2;
  s2.get_diff(d2);

  s1.mix(d1, d2);

  // d2 is
  // r1: 0101 (s1)
  // r2: 1010 (s1)
  // r3: 1100 (s2)

  s3.set_row("r1", make_vector("1111"));
  s3.set_row("r2", make_vector("1111"));
  s3.set_row("r3", make_vector("1111"));
  s3.set_row("r4", make_vector("1111"));
  s3.set_mixed_and_clear_diff(d2);

  // r1, r2 and r3 are overwritten by d2
  // r4 is no longer retained

  bit_vector v;
  s3.get_row("r1", v);
  EXPECT_TRUE(v == make_vector("0101"));
  s3.get_row("r2", v);
  EXPECT_TRUE(v == make_vector("1010"));
  s3.get_row("r3", v);
  EXPECT_TRUE(v == make_vector("1100"));
  s3.get_row("r4", v);
  EXPECT_TRUE(v == bit_vector());

  std::vector<std::string> ids;

  s3.get_all_row_ids(ids);
  EXPECT_EQ(3u, ids.size());

  s3.remove_row("r3");

  // Once MIXed, remove_row does not take affect until next MIX.
  s3.get_all_row_ids(ids);
  EXPECT_EQ(3u, ids.size());

  // do MIX
  bit_table_t d3;
  s3.get_diff(d3);
  s3.set_mixed_and_clear_diff(d3);

  s3.get_all_row_ids(ids);
  EXPECT_EQ(2u, ids.size());
}

}  // namespace storage
}  // namespace core
}  // namespace jubatus
<commit_msg>remove unnecessary namespace prefix<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2012 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include <iostream>
#include <sstream>
#include <string>
#include <utility>
#include <vector>
#include <gtest/gtest.h>
#include "bit_index_storage.hpp"

using std::pair;
using std::stringstream;
using std::string;
using std::vector;

namespace jubatus {
namespace core {
namespace storage {

bit_vector make_vector(const string& b) {
  bit_vector v;
  v.resize_and_clear(b.size());
  for (size_t i = 0; i < b.size(); ++i) {
    if (b[i] == '1') {
      v.set_bit(i);
    }
  }
  return v;
}

TEST(bit_index_storage, trivial) {
  bit_index_storage s;
  EXPECT_EQ("bit_index_storage", s.name());

  s.set_row("r1", make_vector("0101"));
  s.set_row("r2", make_vector("1010"));
  s.set_row("r3", make_vector("1110"));
  s.set_row("r4", make_vector("1100"));

  vector<pair<string, float> > ids;
  s.similar_row(make_vector("1100"), ids, 2);

  ASSERT_EQ(2u, ids.size());
  EXPECT_EQ("r4", ids[0].first);
  EXPECT_FLOAT_EQ(1.0, ids[0].second);
  EXPECT_EQ("r3", ids[1].first);
  EXPECT_FLOAT_EQ(0.75, ids[1].second);

  msgpack::sbuffer buf;
  msgpack::packer<msgpack::sbuffer> packer(buf);
  s.pack(packer);
  bit_index_storage t;
  msgpack::unpacked unpacked;
  msgpack::unpack(&unpacked, buf.data(), buf.size());
  t.unpack(unpacked.get());
  ids.clear();
  t.similar_row(make_vector("1100"), ids, 2);
  ASSERT_EQ(2u, ids.size());
  EXPECT_EQ("r4", ids[0].first);

  s.remove_row("r4");
  ids.clear();
  s.similar_row(make_vector("1100"), ids, 2);
  EXPECT_NE("r4", ids[0].first);

  s.clear();
  ids.clear();
  s.similar_row(make_vector("1100"), ids, 2);
  EXPECT_TRUE(ids.empty());
}

TEST(bit_index_storage, diff) {
  bit_index_storage s1, s2;
  s1.set_row("r1", make_vector("0101"));
  s1.set_row("r2", make_vector("1010"));
  bit_table_t d1;
  s1.get_diff(d1);

  s2.set_mixed_and_clear_diff(d1);
  bit_vector v;
  s2.get_row("r1", v);
  EXPECT_TRUE(make_vector("0101") == v);

  v.resize_and_clear(4);
  s2.get_row("r2", v);
  EXPECT_TRUE(make_vector("1010") == v);
}

TEST(bit_index_storage, mix) {
  bit_index_storage s1, s2, s3;
  s1.set_row("r1", make_vector("0101"));
  s1.set_row("r2", make_vector("1010"));
  bit_table_t d1;
  s1.get_diff(d1);

  s2.set_row("r1", make_vector("1110"));
  s2.set_row("r3", make_vector("1100"));
  bit_table_t d2;
  s2.get_diff(d2);

  s1.mix(d1, d2);

  // d2 is
  // r1: 0101 (s1)
  // r2: 1010 (s1)
  // r3: 1100 (s2)

  s3.set_row("r1", make_vector("1111"));
  s3.set_row("r2", make_vector("1111"));
  s3.set_row("r3", make_vector("1111"));
  s3.set_row("r4", make_vector("1111"));
  s3.set_mixed_and_clear_diff(d2);

  // r1, r2 and r3 are overwritten by d2
  // r4 is no longer retained

  bit_vector v;
  s3.get_row("r1", v);
  EXPECT_TRUE(v == make_vector("0101"));
  s3.get_row("r2", v);
  EXPECT_TRUE(v == make_vector("1010"));
  s3.get_row("r3", v);
  EXPECT_TRUE(v == make_vector("1100"));
  s3.get_row("r4", v);
  EXPECT_TRUE(v == bit_vector());

  vector<string> ids;

  s3.get_all_row_ids(ids);
  EXPECT_EQ(3u, ids.size());

  s3.remove_row("r3");

  // Once MIXed, remove_row does not take affect until next MIX.
  s3.get_all_row_ids(ids);
  EXPECT_EQ(3u, ids.size());

  // do MIX
  bit_table_t d3;
  s3.get_diff(d3);
  s3.set_mixed_and_clear_diff(d3);

  s3.get_all_row_ids(ids);
  EXPECT_EQ(2u, ids.size());
}

}  // namespace storage
}  // namespace core
}  // namespace jubatus
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/QtCore>
#include <QtTest/QtTest>

#ifdef QT_NAMESPACE
#define STRINGIFY_HELPER(s) #s
#define STRINGIFY(s) STRINGIFY_HELPER(s)
QString ns = STRINGIFY(QT_NAMESPACE) + QString("::");
#else
QString ns;
#endif

class tst_Symbols: public QObject
{
    Q_OBJECT
private slots:
    void prefix();
    void globalObjects();
};

/* Computes the line number from a symbol */
static QString symbolToLine(const QString &symbol, const QString &lib)
{
    // nm outputs the symbol name, the type, the address and the size
    QRegExp re("global constructors keyed to ([a-zA-Z_0-9.]*) (.) ([0-f]*) ([0-f]*)");
    if (re.indexIn(symbol) == -1)
        return QString();

    // address and symbolSize are in hex. Convert to integers
    bool ok;
    int symbolAddress = re.cap(3).toInt(&ok, 16);
    if (!ok)
        return QString();
    int symbolSize = re.cap(4).toInt(&ok, 16);
    if (!ok)
        return QString();

    // now, find the start address, which is the address - size
    QString startAddress = QString::number(symbolAddress - symbolSize, 16);

    QProcess proc;
    proc.start("addr2line", QStringList() << "-e" << lib << startAddress);
    if (!proc.waitForFinished())
        return QString();

    QString result = QString::fromLocal8Bit(proc.readLine());
    result.chop(1); // chop tailing newline
    return result;
}

/* This test searches through all Qt libraries and searches for symbols
   starting with "global constructors keyed to "

   These indicate static global objects, which should not be used in shared
   libraries - use Q_GLOBAL_STATIC instead.
*/
void tst_Symbols::globalObjects()
{
#ifndef Q_OS_LINUX
    QSKIP("Linux-specific test", SkipAll);
#endif

    // these are regexps for global objects that are allowed in Qt
    QStringList whitelist = QStringList()
        // ignore qInitResources - they are safe to use
        << "^_Z[0-9]*qInitResources_"
        << "qrc_.*\\.cpp"
        // ignore qRegisterGuiVariant - it's a safe fallback to register GUI Variants
        << "qRegisterGuiVariant";

    bool isFailed = false;

    QDir dir(qgetenv("QTDIR") + "/lib", "*.so");
    QStringList files = dir.entryList();
    QVERIFY(!files.isEmpty());

    foreach (QString lib, files) {

        QProcess proc;
        proc.start("nm",
           QStringList() << "-C" << "--format=posix"
                         << dir.absolutePath() + "/" + lib);
        QVERIFY(proc.waitForFinished());
        QCOMPARE(proc.exitCode(), 0);
        QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());

        QStringList symbols = QString::fromLocal8Bit(proc.readAll()).split("\n");
        QVERIFY(!symbols.isEmpty());
        foreach (QString symbol, symbols) {
            if (symbol.isEmpty())
                continue;

            if (!symbol.startsWith("global constructors keyed to "))
                continue;

            QRegExp re("global constructors keyed to ([a-zA-Z_0-9.]*)");
            QVERIFY(re.indexIn(symbol) != -1);

            QString cap = re.cap(1);

            bool whitelisted = false;
            foreach (QString white, whitelist) {
                if (cap.indexOf(QRegExp(white)) != -1) {
                    whitelisted = true;
                    break;
                }
            }
            if (whitelisted)
                continue;

            QString line = symbolToLine(symbol, dir.absolutePath() + "/" + lib);

            if (cap.contains('.'))
                QWARN(qPrintable("Static global object(s) found in " + lib + " in file " + cap + " (" + line + ")"));
            else
                QWARN(qPrintable("Static global object found in " + lib + " near symbol " + cap + " (" + line + ")"));

            isFailed = true;
        }
    }

    if (isFailed) {
#if QT_VERSION >= 0x040600
        QVERIFY2(!isFailed, "Libraries contain static global objects. See Debug output above.");
#else
        QSKIP("Libraries contains static global objects. See Debug output above. [These errors cannot be fixed in 4.5 in time]", SkipSingle);
#endif
    }
}

void tst_Symbols::prefix()
{
#if defined(QT_CROSS_COMPILED)
    QSKIP("Probably no compiler on the target", SkipAll);
#elif defined(Q_OS_LINUX)
    QStringList qtTypes;
    qtTypes << "QString" << "QChar" << "QWidget" << "QObject" << "QVariant" << "QList"
            << "QMap" << "QHash" << "QVector" << "QRect" << "QSize" << "QPoint"
            << "QTextFormat" << "QTextLength" << "QPen" << "QFont" << "QIcon"
            << "QPixmap" << "QImage" << "QRegion" << "QPolygon";
    QStringList qAlgorithmFunctions;
    qAlgorithmFunctions << "qBinaryFind" << "qLowerBound" << "qUpperBound"
                        << "qAbs" << "qMin" << "qMax" << "qBound" << "qSwap"
                        << "qHash" << "qDeleteAll" << "qCopy" << "qSort";

    QStringList exceptionalSymbols;
    exceptionalSymbols << "XRectangle::~XRectangle()"
                       << "XChar2b::~XChar2b()"
                       << "XPoint::~XPoint()"
                       << "glyph_metrics_t::"; // #### Qt 4.2

    QStringList stupidCSymbols;
    stupidCSymbols << "Add_Glyph_Property"
                   << "Check_Property"
                   << "Coverage_Index"
                   << "Get_Class"
                   << "Get_Device"
                   << "rcsid3"
                   << "sfnt_module_class"
                   << "t1cid_driver_class"
                   << "t42_driver_class"
                   << "winfnt_driver_class"
                   << "pshinter_module_class"
                   << "psnames_module_class"
                   ;

    QHash<QString,QStringList> excusedPrefixes;
    excusedPrefixes[QString()] =
        QStringList() << "Ui_Q"; // uic generated, like Ui_QPrintDialog

    excusedPrefixes["QtCore"] =
        QStringList() << "hb_"
                      << "HB_"
                      // zlib symbols, for -qt-zlib ;(
                      << "deflate"
                      << "compress"
                      << "uncompress"
                      << "adler32"
                      << "gz"
                      << "inflate"
                      << "zlib"
                      << "zError"
                      << "get_crc_table"
                      << "crc32";

    excusedPrefixes["QtGui"] =
        QStringList() << "ftglue_"
                      << "Load_"
                      << "otl_"
                      << "TT_"
                      << "tt_"
                      << "t1_"
                      << "Free_"
                      << "FT_"
                      << "FTC_"
                      << "ft_"
                      << "ftc_"
                      << "af_autofitter"
                      << "af_dummy"
                      << "af_latin"
                      << "autofit_"
                      << "XPanorami"
                      << "Xinerama"
                      << "bdf_"
                      << "ccf_"
                      << "gray_raster"
                      << "pcf_"
                      << "cff_"
                      << "otv_"
                      << "pfr_"
                      << "ps_"
                      << "psaux"
                      << "png_";

    excusedPrefixes["QtSql"] =
        QStringList() << "sqlite3";

    excusedPrefixes["QtWebKit"] =
        QStringList() << "WebCore::"
                      << "KJS::"
                      << "kjs"
                      << "kJS"
                      << "JS"
//                      << "OpaqueJS"
                      << "WTF"
                      << "wtf_"
                      << "SVG::"
                      << "NPN_"
                      << "cti"  // ctiTrampoline and ctiVMThrowTrampoline from the JIT
#ifdef QT_NAMESPACE
                      << "QWeb" // Webkit is only 'namespace aware'
#endif
        ;

    excusedPrefixes["phonon"] =
        QStringList() << ns + "Phonon";

    QDir dir(qgetenv("QTDIR") + "/lib", "*.so");
    QStringList files = dir.entryList();
    QVERIFY(!files.isEmpty());

    bool isFailed = false;
    foreach (QString lib, files) {
        if (lib.contains("Designer") || lib.contains("QtCLucene") || lib.contains("XmlPatternsSDK"))
            continue;

        bool isPhonon = lib.contains("phonon");

        QProcess proc;
        proc.start("nm",
           QStringList() << "-g" << "-C" << "-D" << "--format=posix"
                         << "--defined-only" << dir.absolutePath() + "/" + lib);
        QVERIFY(proc.waitForFinished());
        QCOMPARE(proc.exitCode(), 0);
        QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());

        QStringList symbols = QString::fromLocal8Bit(proc.readAll()).split("\n");
        QVERIFY(!symbols.isEmpty());
        foreach (QString symbol, symbols) {
            if (symbol.isEmpty())
                continue;

            if (symbol.startsWith("unsigned "))
                // strip modifiers
                symbol = symbol.mid(symbol.indexOf(' ') + 1);
            if (symbol.startsWith("long long ")) {
                symbol = symbol.mid(10);
            } else if (symbol.startsWith("bool ") || symbol.startsWith("bool* ")
                || symbol.startsWith("char ") || symbol.startsWith("char* ")
                || symbol.startsWith("int ") || symbol.startsWith("int* ") || symbol.startsWith("int*&")
                || symbol.startsWith("short") || symbol.startsWith("long ")
                || symbol.startsWith("void ") || symbol.startsWith("void* ")
                || symbol.startsWith("double ") || symbol.startsWith("double* ")
                || symbol.startsWith("float ") || symbol.startsWith("float* ")) {
                // partial templates have the return type in their demangled name, strip it
                symbol = symbol.mid(symbol.indexOf(' ') + 1);
            }
            if (symbol.startsWith("const ") || symbol.startsWith("const* ") ||
                symbol.startsWith("const& ")) {
                // strip modifiers
                symbol = symbol.mid(symbol.indexOf(' ') + 1);
            }

            if (symbol.startsWith("_") || symbol.startsWith("std::"))
                continue;
            if (symbol.startsWith("vtable ") || symbol.startsWith("VTT for ") ||
                symbol.startsWith("construction vtable for"))
                continue;
            if (symbol.startsWith("typeinfo "))
                continue;
            if (symbol.startsWith("non-virtual thunk ") || symbol.startsWith("virtual thunk"))
                continue;
            if (symbol.startsWith(ns + "operator"))
                continue;
            if (symbol.startsWith("guard variable for "))
                continue;
            if (symbol.contains("(" + ns + "QTextStream"))
                // QTextStream is excused.
                continue;
            if (symbol.contains("(" + ns + "Q3TextStream"))
                // Q3TextStream is excused.
                continue;
            if (symbol.startsWith(ns + "bitBlt") || symbol.startsWith(ns + "copyBlt"))
                // you're excused, too
                continue;

            bool symbolOk = false;

            QHash<QString,QStringList>::ConstIterator it = excusedPrefixes.constBegin();
            for ( ; it != excusedPrefixes.constEnd(); ++it) {
                if (!lib.contains(it.key()))
                    continue;
                foreach (QString prefix, it.value())
                    if (symbol.startsWith(prefix)) {
                        symbolOk = true;
                        break;
                    }
            }

            if (symbolOk)
                continue;

            foreach (QString cSymbolPattern, stupidCSymbols)
                if (symbol.contains(cSymbolPattern)) {
                    symbolOk = true;
                    break;
                }

            if (symbolOk)
                continue;

            QStringList fields = symbol.split(' ');
            // the last two fields are address and size and the third last field is the symbol type
            QVERIFY(fields.count() > 3);
            QString type = fields.at(fields.count() - 3);
            // weak symbol
            if (type == QLatin1String("W")) {
                if (symbol.contains("qAtomic"))
                    continue;

                if (symbol.contains("fstat")
                    || symbol.contains("lstat")
                    || symbol.contains("stat64")
                   )
                    continue;

                foreach (QString acceptedPattern, qAlgorithmFunctions + exceptionalSymbols)
                    if (symbol.contains(acceptedPattern)) {
                        symbolOk = true;
                        break;
                    }

                if (symbolOk)
                    continue;

                QString plainSymbol;
                for (int i = 0; i < fields.count() - 3; ++i) {
                    if (i > 0)
                        plainSymbol += QLatin1Char(' ');
                    plainSymbol += fields.at(i);
                }
                foreach (QString qtType, qtTypes)
                    if (plainSymbol.contains(qtType)) {
                        symbolOk = true;
                        break;
                    }

                if (symbolOk)
                    continue;
            }

            QString prefix = ns + "q";
            if (!symbol.startsWith(prefix, Qt::CaseInsensitive)
                && !(isPhonon && symbol.startsWith("Phonon"))) {
                qDebug("symbol in '%s' does not start with prefix '%s': '%s'",
                    qPrintable(lib), qPrintable(prefix), qPrintable(symbol));
                isFailed = true;
            }
        }
    }

#  if defined(Q_OS_LINUX) && defined(Q_CC_INTEL)
    QEXPECT_FAIL("", "linux-icc* incorrectly exports some QtWebkit symbols, waiting for a fix from Intel.", Continue);
#  endif
    QVERIFY2(!isFailed, "Libraries contain non-prefixed symbols. See Debug output :)");
#else
    QSKIP("Linux-specific test", SkipAll);
#endif
}

QTEST_MAIN(tst_Symbols)
#include "tst_symbols.moc"
<commit_msg>Autotest: disable the globalObjects test.<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtCore/QtCore>
#include <QtTest/QtTest>

#ifdef QT_NAMESPACE
#define STRINGIFY_HELPER(s) #s
#define STRINGIFY(s) STRINGIFY_HELPER(s)
QString ns = STRINGIFY(QT_NAMESPACE) + QString("::");
#else
QString ns;
#endif

class tst_Symbols: public QObject
{
    Q_OBJECT
private slots:
    void prefix();
    void globalObjects();
};

/* Computes the line number from a symbol */
static QString symbolToLine(const QString &symbol, const QString &lib)
{
    // nm outputs the symbol name, the type, the address and the size
    QRegExp re("global constructors keyed to ([a-zA-Z_0-9.]*) (.) ([0-f]*) ([0-f]*)");
    if (re.indexIn(symbol) == -1)
        return QString();

    // address and symbolSize are in hex. Convert to integers
    bool ok;
    int symbolAddress = re.cap(3).toInt(&ok, 16);
    if (!ok)
        return QString();
    int symbolSize = re.cap(4).toInt(&ok, 16);
    if (!ok)
        return QString();

    // now, find the start address, which is the address - size
    QString startAddress = QString::number(symbolAddress - symbolSize, 16);

    QProcess proc;
    proc.start("addr2line", QStringList() << "-e" << lib << startAddress);
    if (!proc.waitForFinished())
        return QString();

    QString result = QString::fromLocal8Bit(proc.readLine());
    result.chop(1); // chop tailing newline
    return result;
}

/* This test searches through all Qt libraries and searches for symbols
   starting with "global constructors keyed to "

   These indicate static global objects, which should not be used in shared
   libraries - use Q_GLOBAL_STATIC instead.
*/
void tst_Symbols::globalObjects()
{
#ifndef Q_OS_LINUX
    QSKIP("Linux-specific test", SkipAll);
#endif
    QSKIP("Test disabled, we're not fixing these issues in this Qt version", SkipAll);

    // these are regexps for global objects that are allowed in Qt
    QStringList whitelist = QStringList()
        // ignore qInitResources - they are safe to use
        << "^_Z[0-9]*qInitResources_"
        << "qrc_.*\\.cpp"
        // ignore qRegisterGuiVariant - it's a safe fallback to register GUI Variants
        << "qRegisterGuiVariant";

    bool isFailed = false;

    QDir dir(qgetenv("QTDIR") + "/lib", "*.so");
    QStringList files = dir.entryList();
    QVERIFY(!files.isEmpty());

    foreach (QString lib, files) {

        QProcess proc;
        proc.start("nm",
           QStringList() << "-C" << "--format=posix"
                         << dir.absolutePath() + "/" + lib);
        QVERIFY(proc.waitForFinished());
        QCOMPARE(proc.exitCode(), 0);
        QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());

        QStringList symbols = QString::fromLocal8Bit(proc.readAll()).split("\n");
        QVERIFY(!symbols.isEmpty());
        foreach (QString symbol, symbols) {
            if (symbol.isEmpty())
                continue;

            if (!symbol.startsWith("global constructors keyed to "))
                continue;

            QRegExp re("global constructors keyed to ([a-zA-Z_0-9.]*)");
            QVERIFY(re.indexIn(symbol) != -1);

            QString cap = re.cap(1);

            bool whitelisted = false;
            foreach (QString white, whitelist) {
                if (cap.indexOf(QRegExp(white)) != -1) {
                    whitelisted = true;
                    break;
                }
            }
            if (whitelisted)
                continue;

            QString line = symbolToLine(symbol, dir.absolutePath() + "/" + lib);

            if (cap.contains('.'))
                QWARN(qPrintable("Static global object(s) found in " + lib + " in file " + cap + " (" + line + ")"));
            else
                QWARN(qPrintable("Static global object found in " + lib + " near symbol " + cap + " (" + line + ")"));

            isFailed = true;
        }
    }

    if (isFailed) {
#if QT_VERSION >= 0x040600
        QVERIFY2(!isFailed, "Libraries contain static global objects. See Debug output above.");
#else
        QSKIP("Libraries contains static global objects. See Debug output above. [These errors cannot be fixed in 4.5 in time]", SkipSingle);
#endif
    }
}

void tst_Symbols::prefix()
{
#if defined(QT_CROSS_COMPILED)
    QSKIP("Probably no compiler on the target", SkipAll);
#elif defined(Q_OS_LINUX)
    QStringList qtTypes;
    qtTypes << "QString" << "QChar" << "QWidget" << "QObject" << "QVariant" << "QList"
            << "QMap" << "QHash" << "QVector" << "QRect" << "QSize" << "QPoint"
            << "QTextFormat" << "QTextLength" << "QPen" << "QFont" << "QIcon"
            << "QPixmap" << "QImage" << "QRegion" << "QPolygon";
    QStringList qAlgorithmFunctions;
    qAlgorithmFunctions << "qBinaryFind" << "qLowerBound" << "qUpperBound"
                        << "qAbs" << "qMin" << "qMax" << "qBound" << "qSwap"
                        << "qHash" << "qDeleteAll" << "qCopy" << "qSort";

    QStringList exceptionalSymbols;
    exceptionalSymbols << "XRectangle::~XRectangle()"
                       << "XChar2b::~XChar2b()"
                       << "XPoint::~XPoint()"
                       << "glyph_metrics_t::"; // #### Qt 4.2

    QStringList stupidCSymbols;
    stupidCSymbols << "Add_Glyph_Property"
                   << "Check_Property"
                   << "Coverage_Index"
                   << "Get_Class"
                   << "Get_Device"
                   << "rcsid3"
                   << "sfnt_module_class"
                   << "t1cid_driver_class"
                   << "t42_driver_class"
                   << "winfnt_driver_class"
                   << "pshinter_module_class"
                   << "psnames_module_class"
                   ;

    QHash<QString,QStringList> excusedPrefixes;
    excusedPrefixes[QString()] =
        QStringList() << "Ui_Q"; // uic generated, like Ui_QPrintDialog

    excusedPrefixes["QtCore"] =
        QStringList() << "hb_"
                      << "HB_"
                      // zlib symbols, for -qt-zlib ;(
                      << "deflate"
                      << "compress"
                      << "uncompress"
                      << "adler32"
                      << "gz"
                      << "inflate"
                      << "zlib"
                      << "zError"
                      << "get_crc_table"
                      << "crc32";

    excusedPrefixes["QtGui"] =
        QStringList() << "ftglue_"
                      << "Load_"
                      << "otl_"
                      << "TT_"
                      << "tt_"
                      << "t1_"
                      << "Free_"
                      << "FT_"
                      << "FTC_"
                      << "ft_"
                      << "ftc_"
                      << "af_autofitter"
                      << "af_dummy"
                      << "af_latin"
                      << "autofit_"
                      << "XPanorami"
                      << "Xinerama"
                      << "bdf_"
                      << "ccf_"
                      << "gray_raster"
                      << "pcf_"
                      << "cff_"
                      << "otv_"
                      << "pfr_"
                      << "ps_"
                      << "psaux"
                      << "png_";

    excusedPrefixes["QtSql"] =
        QStringList() << "sqlite3";

    excusedPrefixes["QtWebKit"] =
        QStringList() << "WebCore::"
                      << "KJS::"
                      << "kjs"
                      << "kJS"
                      << "JS"
//                      << "OpaqueJS"
                      << "WTF"
                      << "wtf_"
                      << "SVG::"
                      << "NPN_"
                      << "cti"  // ctiTrampoline and ctiVMThrowTrampoline from the JIT
#ifdef QT_NAMESPACE
                      << "QWeb" // Webkit is only 'namespace aware'
#endif
        ;

    excusedPrefixes["phonon"] =
        QStringList() << ns + "Phonon";

    QDir dir(qgetenv("QTDIR") + "/lib", "*.so");
    QStringList files = dir.entryList();
    QVERIFY(!files.isEmpty());

    bool isFailed = false;
    foreach (QString lib, files) {
        if (lib.contains("Designer") || lib.contains("QtCLucene") || lib.contains("XmlPatternsSDK"))
            continue;

        bool isPhonon = lib.contains("phonon");

        QProcess proc;
        proc.start("nm",
           QStringList() << "-g" << "-C" << "-D" << "--format=posix"
                         << "--defined-only" << dir.absolutePath() + "/" + lib);
        QVERIFY(proc.waitForFinished());
        QCOMPARE(proc.exitCode(), 0);
        QCOMPARE(QString::fromLocal8Bit(proc.readAllStandardError()), QString());

        QStringList symbols = QString::fromLocal8Bit(proc.readAll()).split("\n");
        QVERIFY(!symbols.isEmpty());
        foreach (QString symbol, symbols) {
            if (symbol.isEmpty())
                continue;

            if (symbol.startsWith("unsigned "))
                // strip modifiers
                symbol = symbol.mid(symbol.indexOf(' ') + 1);
            if (symbol.startsWith("long long ")) {
                symbol = symbol.mid(10);
            } else if (symbol.startsWith("bool ") || symbol.startsWith("bool* ")
                || symbol.startsWith("char ") || symbol.startsWith("char* ")
                || symbol.startsWith("int ") || symbol.startsWith("int* ") || symbol.startsWith("int*&")
                || symbol.startsWith("short") || symbol.startsWith("long ")
                || symbol.startsWith("void ") || symbol.startsWith("void* ")
                || symbol.startsWith("double ") || symbol.startsWith("double* ")
                || symbol.startsWith("float ") || symbol.startsWith("float* ")) {
                // partial templates have the return type in their demangled name, strip it
                symbol = symbol.mid(symbol.indexOf(' ') + 1);
            }
            if (symbol.startsWith("const ") || symbol.startsWith("const* ") ||
                symbol.startsWith("const& ")) {
                // strip modifiers
                symbol = symbol.mid(symbol.indexOf(' ') + 1);
            }

            if (symbol.startsWith("_") || symbol.startsWith("std::"))
                continue;
            if (symbol.startsWith("vtable ") || symbol.startsWith("VTT for ") ||
                symbol.startsWith("construction vtable for"))
                continue;
            if (symbol.startsWith("typeinfo "))
                continue;
            if (symbol.startsWith("non-virtual thunk ") || symbol.startsWith("virtual thunk"))
                continue;
            if (symbol.startsWith(ns + "operator"))
                continue;
            if (symbol.startsWith("guard variable for "))
                continue;
            if (symbol.contains("(" + ns + "QTextStream"))
                // QTextStream is excused.
                continue;
            if (symbol.contains("(" + ns + "Q3TextStream"))
                // Q3TextStream is excused.
                continue;
            if (symbol.startsWith(ns + "bitBlt") || symbol.startsWith(ns + "copyBlt"))
                // you're excused, too
                continue;

            bool symbolOk = false;

            QHash<QString,QStringList>::ConstIterator it = excusedPrefixes.constBegin();
            for ( ; it != excusedPrefixes.constEnd(); ++it) {
                if (!lib.contains(it.key()))
                    continue;
                foreach (QString prefix, it.value())
                    if (symbol.startsWith(prefix)) {
                        symbolOk = true;
                        break;
                    }
            }

            if (symbolOk)
                continue;

            foreach (QString cSymbolPattern, stupidCSymbols)
                if (symbol.contains(cSymbolPattern)) {
                    symbolOk = true;
                    break;
                }

            if (symbolOk)
                continue;

            QStringList fields = symbol.split(' ');
            // the last two fields are address and size and the third last field is the symbol type
            QVERIFY(fields.count() > 3);
            QString type = fields.at(fields.count() - 3);
            // weak symbol
            if (type == QLatin1String("W")) {
                if (symbol.contains("qAtomic"))
                    continue;

                if (symbol.contains("fstat")
                    || symbol.contains("lstat")
                    || symbol.contains("stat64")
                   )
                    continue;

                foreach (QString acceptedPattern, qAlgorithmFunctions + exceptionalSymbols)
                    if (symbol.contains(acceptedPattern)) {
                        symbolOk = true;
                        break;
                    }

                if (symbolOk)
                    continue;

                QString plainSymbol;
                for (int i = 0; i < fields.count() - 3; ++i) {
                    if (i > 0)
                        plainSymbol += QLatin1Char(' ');
                    plainSymbol += fields.at(i);
                }
                foreach (QString qtType, qtTypes)
                    if (plainSymbol.contains(qtType)) {
                        symbolOk = true;
                        break;
                    }

                if (symbolOk)
                    continue;
            }

            QString prefix = ns + "q";
            if (!symbol.startsWith(prefix, Qt::CaseInsensitive)
                && !(isPhonon && symbol.startsWith("Phonon"))) {
                qDebug("symbol in '%s' does not start with prefix '%s': '%s'",
                    qPrintable(lib), qPrintable(prefix), qPrintable(symbol));
                isFailed = true;
            }
        }
    }

#  if defined(Q_OS_LINUX) && defined(Q_CC_INTEL)
    QEXPECT_FAIL("", "linux-icc* incorrectly exports some QtWebkit symbols, waiting for a fix from Intel.", Continue);
#  endif
    QVERIFY2(!isFailed, "Libraries contain non-prefixed symbols. See Debug output :)");
#else
    QSKIP("Linux-specific test", SkipAll);
#endif
}

QTEST_MAIN(tst_Symbols)
#include "tst_symbols.moc"
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * Copyright (c) 2010-2014 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_FLAT_SEGMENT_TREE_ITR_HPP__
#define __MDDS_FLAT_SEGMENT_TREE_ITR_HPP__

namespace mdds { namespace __fst {

/**
 * Handler for forward iterator
 */
template<typename _FstType>
struct itr_forward_handler
{
    typedef _FstType fst_type;

    static const typename fst_type::node* init_pos(const fst_type* _db, bool _end)
    {
        return _end ? _db->m_right_leaf.get() : _db->m_left_leaf.get();
    }

    static void inc(const fst_type* _db, const typename fst_type::node*& p, bool& end)
    {
        if (p == _db->m_right_leaf.get())
            end = true;
        else
            p = p->next.get();
    }

    static void dec(const typename fst_type::node*& p, bool& end)
    {
        if (end)
            end = false;
        else
            p = p->prev.get();
    }
};

/**
 * Handler for reverse iterator
 */
template<typename _FstType>
struct itr_reverse_handler
{
    typedef _FstType fst_type;

    static const typename fst_type::node* init_pos(const fst_type* _db, bool _end)
    {
        return _end ? _db->m_left_leaf.get() : _db->m_right_leaf.get();
    }

    static void inc(const fst_type* _db, const typename fst_type::node*& p, bool& end)
    {
        if (p == _db->m_left_leaf.get())
            end = true;
        else
            p = p->prev.get();
    }

    static void dec(const typename fst_type::node*& p, bool& end)
    {
        if (end)
            end = false;
        else
            p = p->next.get();
    }
};

template<typename _FstType, typename _Hdl>
class const_iterator_base
{
    typedef _Hdl     handler_type;
public:
    typedef _FstType fst_type;

    // iterator traits
    typedef ::std::pair<typename fst_type::key_type, typename fst_type::value_type> value_type;
    typedef value_type*     pointer;
    typedef value_type&     reference;
    typedef ptrdiff_t       difference_type;
    typedef ::std::bidirectional_iterator_tag iterator_category;

    explicit const_iterator_base(const fst_type* _db, bool _end) :
        m_db(_db), m_pos(nullptr), m_end_pos(_end)
    {
        if (!_db)
            return;

        m_pos = handler_type::init_pos(_db, _end);
    }

    explicit const_iterator_base(const fst_type* _db, const typename fst_type::node* pos) :
        m_db(_db), m_pos(pos), m_end_pos(false) {}

    const_iterator_base(const const_iterator_base& r) :
        m_db(r.m_db), m_pos(r.m_pos), m_end_pos(r.m_end_pos) {}

    const_iterator_base& operator=(const const_iterator_base& r)
    {
        m_db = r.m_db;
        m_pos = r.m_pos;
        m_end_pos = r.m_end_pos;
        return *this;
    }

    const value_type* operator++()
    {
        assert(m_pos);
        handler_type::inc(m_db, m_pos, m_end_pos);
        return operator->();
    }

    const value_type* operator--()
    {
        assert(m_pos);
        handler_type::dec(m_pos, m_end_pos);
        return operator->();
    }

    bool operator==(const const_iterator_base& r) const
    {
        if (m_db != r.m_db)
            return false;

        return (m_pos == r.m_pos) && (m_end_pos == r.m_end_pos);
    }

    bool operator!=(const const_iterator_base& r) const
    {
        return !operator==(r);
    }

    const value_type& operator*()
    {
        return get_current_node_pair();
    }

    const value_type* operator->()
    {
        return &get_current_node_pair();
    }

protected:
    const typename fst_type::node* get_pos() const { return m_pos; }
    const fst_type* get_parent() const { return m_db; }

private:
    const value_type& get_current_node_pair()
    {
        m_current_pair = value_type(m_pos->value_leaf.key, m_pos->value_leaf.value);
        return m_current_pair;
    }

    const fst_type* m_db;
    const typename fst_type::node* m_pos;
    value_type      m_current_pair;
    bool            m_end_pos;
};

}}

#endif
<commit_msg>fix return values for the operator++/-- in the flat_segement_tree iterators<commit_after>/*************************************************************************
 *
 * Copyright (c) 2010-2014 Kohei Yoshida
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 ************************************************************************/

#ifndef __MDDS_FLAT_SEGMENT_TREE_ITR_HPP__
#define __MDDS_FLAT_SEGMENT_TREE_ITR_HPP__

namespace mdds { namespace __fst {

/**
 * Handler for forward iterator
 */
template<typename _FstType>
struct itr_forward_handler
{
    typedef _FstType fst_type;

    static const typename fst_type::node* init_pos(const fst_type* _db, bool _end)
    {
        return _end ? _db->m_right_leaf.get() : _db->m_left_leaf.get();
    }

    static void inc(const fst_type* _db, const typename fst_type::node*& p, bool& end)
    {
        if (p == _db->m_right_leaf.get())
            end = true;
        else
            p = p->next.get();
    }

    static void dec(const typename fst_type::node*& p, bool& end)
    {
        if (end)
            end = false;
        else
            p = p->prev.get();
    }
};

/**
 * Handler for reverse iterator
 */
template<typename _FstType>
struct itr_reverse_handler
{
    typedef _FstType fst_type;

    static const typename fst_type::node* init_pos(const fst_type* _db, bool _end)
    {
        return _end ? _db->m_left_leaf.get() : _db->m_right_leaf.get();
    }

    static void inc(const fst_type* _db, const typename fst_type::node*& p, bool& end)
    {
        if (p == _db->m_left_leaf.get())
            end = true;
        else
            p = p->prev.get();
    }

    static void dec(const typename fst_type::node*& p, bool& end)
    {
        if (end)
            end = false;
        else
            p = p->next.get();
    }
};

template<typename _FstType, typename _Hdl>
class const_iterator_base
{
    typedef _Hdl     handler_type;
public:
    typedef _FstType fst_type;

    // iterator traits
    typedef ::std::pair<typename fst_type::key_type, typename fst_type::value_type> value_type;
    typedef value_type*     pointer;
    typedef value_type&     reference;
    typedef ptrdiff_t       difference_type;
    typedef ::std::bidirectional_iterator_tag iterator_category;

    explicit const_iterator_base(const fst_type* _db, bool _end) :
        m_db(_db), m_pos(nullptr), m_end_pos(_end)
    {
        if (!_db)
            return;

        m_pos = handler_type::init_pos(_db, _end);
    }

    explicit const_iterator_base(const fst_type* _db, const typename fst_type::node* pos) :
        m_db(_db), m_pos(pos), m_end_pos(false) {}

    const_iterator_base(const const_iterator_base& r) :
        m_db(r.m_db), m_pos(r.m_pos), m_end_pos(r.m_end_pos) {}

    const_iterator_base& operator=(const const_iterator_base& r)
    {
        m_db = r.m_db;
        m_pos = r.m_pos;
        m_end_pos = r.m_end_pos;
        return *this;
    }

    const_iterator_base& operator++()
    {
        assert(m_pos);
        handler_type::inc(m_db, m_pos, m_end_pos);
        return *this;
    }

    const_iterator_base operator--()
    {
        assert(m_pos);
        handler_type::dec(m_pos, m_end_pos);
        return *this;
    }

    bool operator==(const const_iterator_base& r) const
    {
        if (m_db != r.m_db)
            return false;

        return (m_pos == r.m_pos) && (m_end_pos == r.m_end_pos);
    }

    bool operator!=(const const_iterator_base& r) const
    {
        return !operator==(r);
    }

    const value_type& operator*()
    {
        return get_current_node_pair();
    }

    const value_type* operator->()
    {
        return &get_current_node_pair();
    }

protected:
    const typename fst_type::node* get_pos() const { return m_pos; }
    const fst_type* get_parent() const { return m_db; }

private:
    const value_type& get_current_node_pair()
    {
        m_current_pair = value_type(m_pos->value_leaf.key, m_pos->value_leaf.value);
        return m_current_pair;
    }

    const fst_type* m_db;
    const typename fst_type::node* m_pos;
    value_type      m_current_pair;
    bool            m_end_pos;
};

}}

#endif
<|endoftext|>