Commit 9d41dd8c authored by Ivan.Shulga's avatar Ivan.Shulga Committed by Alexander Trofimov

clipboard parser initial commit

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@56405 954022d7-b5bf-4e40-9824-e11837661b57
parent 4dcf4dfe

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

This diff is collapsed.

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ClipboardParser", "ClipboardParser.vcproj", "{E721277C-B765-4B37-8638-97E6E33DBE75}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{E721277C-B765-4B37-8638-97E6E33DBE75}.Debug|Win32.ActiveCfg = Debug|Win32
{E721277C-B765-4B37-8638-97E6E33DBE75}.Debug|Win32.Build.0 = Debug|Win32
{E721277C-B765-4B37-8638-97E6E33DBE75}.Release|Win32.ActiveCfg = Release|Win32
{E721277C-B765-4B37-8638-97E6E33DBE75}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
<?xml version="1.0" encoding="windows-1251"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="ClipboardParser"
ProjectGUID="{E721277C-B765-4B37-8638-97E6E33DBE75}"
RootNamespace="ClipboardParser"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
</Platforms>
<ToolFiles>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="2"
IgnoreAllDefaultLibraries="true"
GenerateDebugInformation="true"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="$(SolutionDir)$(ConfigurationName)"
IntermediateDirectory="$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
RuntimeLibrary="2"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="true"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCFxCopTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
>
<File
RelativePath=".\ClipboardParser\ClipboardDataFetcher.cpp"
>
</File>
<File
RelativePath=".\ClipboardParser\ClipboardFetcherLinux.cpp"
>
</File>
<File
RelativePath=".\ClipboardParser\ClipboardFetcherMacosx.cpp"
>
</File>
<File
RelativePath=".\ClipboardParser\ClipboardFetcherWin.cpp"
>
</File>
<File
RelativePath=".\ClipboardParser\ClipboardParser.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
ObjectFile="$(IntDir)\$(InputName)1.obj"
XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
/>
</FileConfiguration>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc;xsd"
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
>
<File
RelativePath=".\ClipboardParser\ClipboardDataFetcher.h"
>
</File>
<File
RelativePath=".\ClipboardParser\ClipboardFetcherLinux.h"
>
</File>
<File
RelativePath=".\ClipboardParser\ClipboardFetcherMacosx.h"
>
</File>
<File
RelativePath=".\ClipboardParser\ClipboardFetcherWin.h"
>
</File>
<File
RelativePath=".\ClipboardParser\IClipboardFetcher.h"
>
</File>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
>
</Filter>
<File
RelativePath=".\ReadMe.txt"
>
</File>
</Files>
<Globals>
</Globals>
</VisualStudioProject>
#include "ClipboardDataFetcher.h"
IClipboardFetcher* CClipboardDataFetcher::createClipboardFetcher ()
{
IClipboardFetcher* pFetcher = NULL;
// Windows
#if defined (_WIN32) || defined (__MINGW32__)
pFetcher = new CClipboardFetcherWin ();
#endif
// Macos X
#ifdef __APPLE__
pFetcher = new CClipboardFetcherMacosx ();
#endif
// GCC on Linux
#ifdef __GNUC__
pFetcher = new CClipboardFetcherLinux ();
#endif
return pFetcher;
}
CClipboardDataFetcher::CClipboardDataFetcher(void)
{
}
CClipboardDataFetcher::~CClipboardDataFetcher(void)
{
}
#ifndef _Clipboard_CClipboardDataFetcher_
#define _Clipboard_CClipboardDataFetcher_
#include "IClipboardFetcher.h"
// Windows MSDN
// For MingW on Windows
#if defined (_WIN32) || defined (__MINGW32__)
#include "ClipboardFetcherWin.h"
#endif
// Macos X
#ifdef __APPLE__
#include "ClipboardFetcherMacosx.h"
#endif
// GCC on Linux
#ifdef __GNUC__
#endif
class CClipboardDataFetcher
{
public:
IClipboardFetcher* createClipboardFetcher ();
public:
CClipboardDataFetcher(void);
~CClipboardDataFetcher(void);
};
#endif // #ifndef _Clipboard_CClipboardDataFetcher_
#include "ClipboardFetcherLinux.h"
// GCC on Linux
#ifdef __GNUC__
CClipboardFetcherLinux::CClipboardFetcherLinux(void)
{
}
CClipboardFetcherLinux::~CClipboardFetcherLinux(void)
{
}
#endif // #ifdef __GNUC__
\ No newline at end of file
#ifndef _Clipboard_CClipboardDataFetcherLinux_
#define _Clipboard_CClipboardDataFetcherLinux_
// GCC on Linux
#ifdef __GNUC__
#include "IClipboardFetcher.h"
class CClipboardFetcherLinux: public IClipboardFetcher
{
public:
CClipboardFetcherLinux(void);
~CClipboardFetcherLinux(void);
};
#endif // #ifdef __GNUC__
#endif // #ifndef _Clipboard_CClipboardDataFetcherLinux_
#include "ClipboardFetcherMacosx.h"
#ifdef __APPLE__
CClipboardFetcherMacosx::CClipboardFetcherMacosx(void)
{
}
CClipboardFetcherMacosx::~CClipboardFetcherMacosx(void)
{
}
#endif // #ifdef __APPLE__
\ No newline at end of file
#ifndef _Clipboard_CClipboardDataFetcherMacosx_
#define _Clipboard_CClipboardDataFetcherMacosx_
#ifdef __APPLE__
#include "IClipboardFetcher.h"
class CClipboardFetcherMacosx: public IClipboardFetcher
{
public:
CClipboardFetcherMacosx(void);
~CClipboardFetcherMacosx(void);
};
#endif // #ifdef __APPLE__
#endif // #ifndef _Clipboard_CClipboardDataFetcherMacosx_
#include "ClipboardFetcherWin.h"
#include <vector>
#include <map>
#if defined (_WIN32) || defined (__MINGW32__)
#pragma comment(lib, "User32.lib")
int CClipboardFetcherWin::m_nClipboardFormatID = 0;
CClipboardFetcherWin::CClipboardFetcherWin(void)
{
if (0 == m_nClipboardFormatID)
m_nClipboardFormatID = RegisterClipboardFormatW (L"HTML Format");
}
CClipboardFetcherWin::~CClipboardFetcherWin(void)
{
}
bool CClipboardFetcherWin::getUnicodeTextContent (std::wstring &aContent)
{
bool bResult = false;
if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
return bResult;
BOOL bClipboardOpened = OpenClipboard (NULL);
if (0 == bClipboardOpened)
return bResult;
HANDLE hglb = GetClipboardData(CF_UNICODETEXT);
if (hglb != NULL)
{
LPWSTR pText = (LPWSTR) GlobalLock(hglb);
std::wstring sText = pText;
aContent.assign (sText.begin(), sText.end());
GlobalUnlock(hglb);
bResult = true;
}
CloseClipboard ();
return bResult;
}
bool CClipboardFetcherWin::getTextContent (std::wstring &aContent)
{
bool bResult = false;
if (!IsClipboardFormatAvailable(CF_TEXT))
return bResult;
BOOL bClipboardOpened = OpenClipboard (NULL);
if (0 == bClipboardOpened)
return bResult;
HANDLE hglb = GetClipboardData(CF_TEXT);
if (hglb != NULL)
{
LPSTR pText = (LPSTR) GlobalLock(hglb);
std::string sText = pText;
aContent.assign (sText.begin(), sText.end());
GlobalUnlock(hglb);
bResult = true;
}
CloseClipboard ();
return bResult;
}
bool CClipboardFetcherWin::getHtmlContent (std::wstring &aContent)
{
bool bResult = false;
if (0 == m_nClipboardFormatID || !IsClipboardFormatAvailable(m_nClipboardFormatID))
return bResult;
BOOL bClipboardOpened = OpenClipboard (NULL);
if (0 == bClipboardOpened)
return bResult;
/*
std::vector<UINT> vFormats;
UINT nFormats = EnumClipboardFormats (0);
while (0 != nFormats)
{
vFormats.push_back(nFormats);
nFormats = EnumClipboardFormats (nFormats);
//unsigned int dwError = GetLastError();
}
CloseClipboard ();
bClipboardOpened = OpenClipboard (NULL);
if (0 == bClipboardOpened)
return bResult;
*/
std::string sText;
HANDLE hglb = GetClipboardData(m_nClipboardFormatID);
if (hglb != NULL)
{
LPSTR pText = (LPSTR) GlobalLock(hglb);
sText = pText;
GlobalUnlock(hglb);
bResult = true;
}
CloseClipboard ();
if (bResult)
{
bResult &= extractHtmlClipboard (sText, aContent);
}
return bResult;
}
bool CClipboardFetcherWin::extractHtmlClipboard (const std::string &sText, std::wstring &aContent)
{
bool bResult = true;
try
{
//std::map<std::string, std::string> aParameters;
int nStartFragmentOffset = 0;
int nEndFragmentOffset = 0;
std::string::size_type nStartFragmentPos = sText.find ("StartFragment", 0);
if (nStartFragmentPos >= 0)
{
std::string::size_type nStartFragmentNewLinePos = sText.find ("\n", nStartFragmentPos);
std::string sStartFragmentText = sText.substr (nStartFragmentPos, nStartFragmentNewLinePos - nStartFragmentPos);
std::string::size_type nSeparatorPos = sStartFragmentText.find (":", 0);
if (nSeparatorPos >= 0)
{
std::string sStartFragmentOffset = sStartFragmentText.substr (nSeparatorPos + 1);
nStartFragmentOffset = atoi (sStartFragmentOffset.c_str());
}
if (0 == nStartFragmentOffset)
return false;
}
std::string::size_type nEndFragmentPos = sText.find ("EndFragment", nStartFragmentPos);
if (nEndFragmentPos >= 0)
{
std::string::size_type nEndFragmentNewLinePos = sText.find ("\n", nEndFragmentPos);
std::string sEndFragmentText = sText.substr (nEndFragmentPos, nEndFragmentNewLinePos - nEndFragmentPos);
std::string::size_type nSeparatorPos = sEndFragmentText.find (":", 0);
if (nSeparatorPos >= 0)
{
std::string sEndFragmentOffset = sEndFragmentText.substr (nSeparatorPos + 1);
nEndFragmentOffset = atoi (sEndFragmentOffset.c_str());
}
if (0 == nEndFragmentOffset)
return false;
}
std::string sHtmlContent = sText.substr (nStartFragmentOffset, nEndFragmentOffset - nStartFragmentOffset);
// convert UTF-8 to UTF-16
int nWideStringLength = MultiByteToWideChar (CP_UTF8, 0, sHtmlContent.c_str(), -1, NULL, 0);
WCHAR *pWideStringBuffer = new WCHAR [nWideStringLength + 1];
pWideStringBuffer [nWideStringLength] = 0x00;
int nConversionResult = MultiByteToWideChar (CP_UTF8, 0, sHtmlContent.c_str(), -1, pWideStringBuffer, nWideStringLength);
if (0 == nConversionResult || ERROR_NO_UNICODE_TRANSLATION == nConversionResult)
return false;
aContent = L"<body>";
aContent.append (pWideStringBuffer);
aContent += L"</body>";
delete [] pWideStringBuffer;
}
catch (...)
{
bResult = false;
}
return bResult;
}
bool CClipboardFetcherWin::setHtmlContent (const std::wstring &aContent)
{
bool bResult = false;
return bResult;
}
#endif // #if defined (_WIN32) || defined (__MINGW32__)
\ No newline at end of file
#ifndef _Clipboard_CClipboardDataFetcherWin_
#define _Clipboard_CClipboardDataFetcherWin_
#if defined (_WIN32) || defined (__MINGW32__)
#include <string>
#include "IClipboardFetcher.h"
#include "Windows.h"
class CClipboardFetcherWin: public IClipboardFetcher
{
public:
bool getTextContent (std::wstring &aContent);
bool getUnicodeTextContent (std::wstring &aContent);
bool getHtmlContent (std::wstring &aContent);
bool setHtmlContent (const std::wstring &aContent);
public:
CClipboardFetcherWin(void);
~CClipboardFetcherWin(void);
private:
bool extractHtmlClipboard (const std::string &sText, std::wstring &aContent);
private:
static int m_nClipboardFormatID;
};
#endif // #if defined (_WIN32) || defined (__MINGW32__)
#endif // #ifndef _Clipboard_CClipboardDataFetcherWin_
// ClipboardParser.cpp : Defines the entry point for the console application.
//
#include "ClipboardDataFetcher.h"
#include "IClipboardFetcher.h"
#include <iostream>
int main(int argc, char* argv[])
{
CClipboardDataFetcher fabric;
IClipboardFetcher* fetcher = fabric.createClipboardFetcher ();
std::wstring sContentText;
std::wstring sContentUnicodeText;
std::wstring sContentHtml;
bool bIsTextDataExists = fetcher->getTextContent (sContentText);
bool bIsHtmlDataExists = fetcher->getHtmlContent (sContentHtml);
bool bIsUnicodeTextDataExists = fetcher->getUnicodeTextContent (sContentUnicodeText);
std::wcout << L"Clipboard HTML get data: " << (bIsHtmlDataExists ? L"Success" : L"Failed" ) << std::endl;
if (bIsHtmlDataExists)
{
std::wcout << L"Content: " << sContentHtml << std::endl;
}
std::wcout << L"Clipboard TEXT get data: " << (bIsTextDataExists ? L"Success" : L"Failed" ) << std::endl;
if (bIsTextDataExists)
{
std::wcout << L"Content: " << sContentText << std::endl;
}
std::wcout << L"Clipboard UNICODE TEXT get data: " << (bIsUnicodeTextDataExists ? L"Success" : L"Failed" ) << std::endl;
if (bIsUnicodeTextDataExists)
{
std::wcout << L"Content: " << sContentUnicodeText << std::endl;
}
delete fetcher;
return 0;
}
#ifndef _Clipboard_IClipboardDataFetcher_
#define _Clipboard_IClipboardDataFetcher_
#define CLIPBOARD_FORMAT_TEXT 0x000001
#define CLIPBOARD_FORMAT_HTML 0x000002
// interface for clipboard fetcher. it's a parent for platform-dependent classes
#include <string>
class IClipboardFetcher
{
public:
virtual bool getTextContent (std::wstring &aContent) = 0;
virtual bool getUnicodeTextContent (std::wstring &aContent) = 0;
virtual bool getHtmlContent (std::wstring &aContent) = 0;
virtual bool setHtmlContent (const std::wstring &aContent) = 0;
};
#endif // #ifndef _Clipboard_IClipboardDataFetcher_
\ No newline at end of file
========================================================================
CONSOLE APPLICATION : ClipboardParser Project Overview
========================================================================
AppWizard has created this ClipboardParser application for you.
This file contains a summary of what you will find in each of the files that
make up your ClipboardParser application.
ClipboardParser.vcproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
ClipboardParser.cpp
This is the main application source file.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named ClipboardParser.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////
========================================================================
CONSOLE APPLICATION : ClipboardParser Project Overview
========================================================================
AppWizard has created this ClipboardParser application for you.
This file contains a summary of what you will find in each of the files that
make up your ClipboardParser application.
ClipboardParser.vcproj
This is the main project file for VC++ projects generated using an Application Wizard.
It contains information about the version of Visual C++ that generated the file, and
information about the platforms, configurations, and project features selected with the
Application Wizard.
ClipboardParser.cpp
This is the main application source file.
/////////////////////////////////////////////////////////////////////////////
Other standard files:
StdAfx.h, StdAfx.cpp
These files are used to build a precompiled header (PCH) file
named ClipboardParser.pch and a precompiled types file named StdAfx.obj.
/////////////////////////////////////////////////////////////////////////////
Other notes:
AppWizard uses "TODO:" comments to indicate parts of the source code you
should add to or customize.
/////////////////////////////////////////////////////////////////////////////
include_rules = [
"+jni",
"+native_client/src/untrusted/irt/irt.h",
"+third_party/ashmem",
"+third_party/apple_apsl",
"+third_party/libevent",
"+third_party/dmg_fp",
"+third_party/GTM",
"+third_party/mach_override",
"+third_party/modp_b64",
"+third_party/tcmalloc",
# ICU dependendencies must be separate from the rest of base.
"-i18n",
]
mark@chromium.org
darin@chromium.org
brettw@chromium.org
willchan@chromium.org
jar@chromium.org
per-file *.isolate=csharp@chromium.org
per-file *.isolate=maruel@chromium.org
per-file bind.h=ajwong@chromium.org
per-file bind_helpers.cc=ajwong@chromium.org
per-file bind_helpers.h=ajwong@chromium.org
per-file bind_helpers_unittest.cc=ajwong@chromium.org
per-file bind.h.pump=ajwong@chromium.org
per-file bind_internal.h=ajwong@chromium.org
per-file bind_internal.h.pump=ajwong@chromium.org
per-file bind_internal_win.h=ajwong@chromium.org
per-file bind_internal_win.h.pump=ajwong@chromium.org
per-file bind_unittest.cc=ajwong@chromium.org
per-file bind_unittest.nc=ajwong@chromium.org
per-file callback_forward.h=ajwong@chromium.org
per-file callback.h=ajwong@chromium.org
per-file callback_helpers.h=ajwong@chromium.org
per-file callback.h.pump=ajwong@chromium.org
per-file callback_internal.cc=ajwong@chromium.org
per-file callback_internal.h=ajwong@chromium.org
per-file callback_unittest.cc=ajwong@chromium.org
per-file callback_unittest.h=ajwong@chromium.org
per-file callback_unittest.nc=ajwong@chromium.org
per-file security_unittest.cc=jln@chromium.org
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Chromium presubmit script for src/base.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details on the presubmit API built into gcl.
"""
def _CheckNoInterfacesInBase(input_api, output_api):
"""Checks to make sure no files in libbase.a have |@interface|."""
pattern = input_api.re.compile(r'^\s*@interface', input_api.re.MULTILINE)
files = []
for f in input_api.AffectedSourceFiles(input_api.FilterSourceFile):
if (f.LocalPath().startswith('base/') and
not "/test/" in f.LocalPath() and
not f.LocalPath().endswith('_unittest.mm')):
contents = input_api.ReadFile(f)
if pattern.search(contents):
files.append(f)
if len(files):
return [ output_api.PresubmitError(
'Objective-C interfaces or categories are forbidden in libbase. ' +
'See http://groups.google.com/a/chromium.org/group/chromium-dev/' +
'browse_thread/thread/efb28c10435987fd',
files) ]
return []
def _CommonChecks(input_api, output_api):
"""Checks common to both upload and commit."""
results = []
results.extend(_CheckNoInterfacesInBase(input_api, output_api))
return results
def CheckChangeOnUpload(input_api, output_api):
results = []
results.extend(_CommonChecks(input_api, output_api))
return results
def CheckChangeOnCommit(input_api, output_api):
results = []
results.extend(_CommonChecks(input_api, output_api))
return results
def GetPreferredTrySlaves():
return [
'linux_rel:sync_integration_tests',
'mac_rel:sync_integration_tests',
'win_rel:sync_integration_tests',
]
Notes about the Chrome memory allocator.
Background
----------
We use this library as a generic way to fork into any of several allocators.
Currently we can, at runtime, switch between:
the default windows allocator
the windows low-fragmentation-heap
tcmalloc
jemalloc (the heap used most notably within Mozilla Firefox)
The mechanism for hooking LIBCMT in windows is rather tricky. The core
problem is that by default, the windows library does not declare malloc and
free as weak symbols. Because of this, they cannot be overriden. To work
around this, we start with the LIBCMT.LIB, and manually remove all allocator
related functions from it using the visual studio library tool. Once removed,
we can now link against the library and provide custom versions of the
allocator related functionality.
Source code
-----------
This directory contains just the allocator (i.e. shim) layer that switches
between the different underlying memory allocation implementations.
The tcmalloc and jemalloc libraries originate outside of Chromium
and exist in ../../third_party/tcmalloc and ../../third_party/jemalloc
(currently, the actual locations are defined in the allocator.gyp file).
The third party sources use a vendor-branch SCM pattern to track
Chromium-specific changes independently from upstream changes.
The general intent is to push local changes upstream so that over
time we no longer need any forked files.
Adding a new allocator
----------------------
Adding a new allocator requires definition of the following five functions:
extern "C" {
bool init();
void* malloc(size_t s);
void* realloc(void* p, size_t s);
void free(void* s);
size_t msize(void* p);
}
All other allocation related functions (new/delete/calloc/etc) have been
implemented generically to work across all allocators.
Usage
-----
You can use the different allocators by setting the environment variable
CHROME_ALLOCATOR to:
"tcmalloc" - TC Malloc (default)
"jemalloc" - JE Malloc
"winheap" - Windows default heap
"winlfh" - Windows Low-Fragmentation heap
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/allocator/allocator_extension.h"
#include "base/logging.h"
namespace base {
namespace allocator {
bool GetAllocatorWasteSize(size_t* size) {
thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function =
thunks::GetGetAllocatorWasteSizeFunction();
return get_allocator_waste_size_function != NULL &&
get_allocator_waste_size_function(size);
}
void GetStats(char* buffer, int buffer_length) {
DCHECK_GT(buffer_length, 0);
thunks::GetStatsFunction get_stats_function = thunks::GetGetStatsFunction();
if (get_stats_function)
get_stats_function(buffer, buffer_length);
else
buffer[0] = '\0';
}
void ReleaseFreeMemory() {
thunks::ReleaseFreeMemoryFunction release_free_memory_function =
thunks::GetReleaseFreeMemoryFunction();
if (release_free_memory_function)
release_free_memory_function();
}
void SetGetAllocatorWasteSizeFunction(
thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function) {
DCHECK_EQ(thunks::GetGetAllocatorWasteSizeFunction(),
reinterpret_cast<thunks::GetAllocatorWasteSizeFunction>(NULL));
thunks::SetGetAllocatorWasteSizeFunction(get_allocator_waste_size_function);
}
void SetGetStatsFunction(thunks::GetStatsFunction get_stats_function) {
DCHECK_EQ(thunks::GetGetStatsFunction(),
reinterpret_cast<thunks::GetStatsFunction>(NULL));
thunks::SetGetStatsFunction(get_stats_function);
}
void SetReleaseFreeMemoryFunction(
thunks::ReleaseFreeMemoryFunction release_free_memory_function) {
DCHECK_EQ(thunks::GetReleaseFreeMemoryFunction(),
reinterpret_cast<thunks::ReleaseFreeMemoryFunction>(NULL));
thunks::SetReleaseFreeMemoryFunction(release_free_memory_function);
}
} // namespace allocator
} // namespace base
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H
#define BASE_ALLOCATOR_ALLOCATOR_EXTENSION_H
#include <stddef.h> // for size_t
#include "base/allocator/allocator_extension_thunks.h"
#include "base/base_export.h"
#include "build/build_config.h"
namespace base {
namespace allocator {
// Request the allocator to report value of its waste memory size.
// Waste size corresponds to memory that has been allocated from the OS but
// not passed up to the application. It e.g. includes memory retained by free
// lists, internal data, chunks padding, etc.
//
// |size| pointer to the returned value, must be not NULL.
// Returns true if the value has been returned, false otherwise.
BASE_EXPORT bool GetAllocatorWasteSize(size_t* size);
// Request that the allocator print a human-readable description of the current
// state of the allocator into a null-terminated string in the memory segment
// buffer[0,buffer_length-1].
//
// |buffer| must point to a valid piece of memory
// |buffer_length| must be > 0.
BASE_EXPORT void GetStats(char* buffer, int buffer_length);
// Request that the allocator release any free memory it knows about to the
// system.
BASE_EXPORT void ReleaseFreeMemory();
// These settings allow specifying a callback used to implement the allocator
// extension functions. These are optional, but if set they must only be set
// once. These will typically called in an allocator-specific initialization
// routine.
//
// No threading promises are made. The caller is responsible for making sure
// these pointers are set before any other threads attempt to call the above
// functions.
BASE_EXPORT void SetGetAllocatorWasteSizeFunction(
thunks::GetAllocatorWasteSizeFunction get_allocator_waste_size_function);
BASE_EXPORT void SetGetStatsFunction(
thunks::GetStatsFunction get_stats_function);
BASE_EXPORT void SetReleaseFreeMemoryFunction(
thunks::ReleaseFreeMemoryFunction release_free_memory_function);
} // namespace allocator
} // namespace base
#endif
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "base/allocator/allocator_extension_thunks.h"
#include <cstddef> // for NULL
namespace base {
namespace allocator {
namespace thunks {
// This slightly odd translation unit exists because of the peculularity of how
// allocator_unittests work on windows. That target has to perform
// tcmalloc-specific initialization on windows, but it cannot depend on base
// otherwise. This target sits in the middle - base and allocator_unittests
// can depend on it. This file can't depend on anything else in base, including
// logging.
static GetAllocatorWasteSizeFunction g_get_allocator_waste_size_function = NULL;
static GetStatsFunction g_get_stats_function = NULL;
static ReleaseFreeMemoryFunction g_release_free_memory_function = NULL;
void SetGetAllocatorWasteSizeFunction(
GetAllocatorWasteSizeFunction get_allocator_waste_size_function) {
g_get_allocator_waste_size_function = get_allocator_waste_size_function;
}
GetAllocatorWasteSizeFunction GetGetAllocatorWasteSizeFunction() {
return g_get_allocator_waste_size_function;
}
void SetGetStatsFunction(GetStatsFunction get_stats_function) {
g_get_stats_function = get_stats_function;
}
GetStatsFunction GetGetStatsFunction() {
return g_get_stats_function;
}
void SetReleaseFreeMemoryFunction(
ReleaseFreeMemoryFunction release_free_memory_function) {
g_release_free_memory_function = release_free_memory_function;
}
ReleaseFreeMemoryFunction GetReleaseFreeMemoryFunction() {
return g_release_free_memory_function;
}
} // namespace thunks
} // namespace allocator
} // namespace base
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H
#define BASE_ALLOCATOR_ALLOCATOR_THUNKS_EXTENSION_H
#include <stddef.h> // for size_t
namespace base {
namespace allocator {
namespace thunks {
// WARNING: You probably don't want to use this file unless you are routing a
// new allocator extension from a specific allocator implementation to base.
// See allocator_extension.h to see the interface that base exports.
typedef bool (*GetAllocatorWasteSizeFunction)(size_t* size);
void SetGetAllocatorWasteSizeFunction(
GetAllocatorWasteSizeFunction get_allocator_waste_size_function);
GetAllocatorWasteSizeFunction GetGetAllocatorWasteSizeFunction();
typedef void (*GetStatsFunction)(char* buffer, int buffer_length);
void SetGetStatsFunction(GetStatsFunction get_stats_function);
GetStatsFunction GetGetStatsFunction();
typedef void (*ReleaseFreeMemoryFunction)();
void SetReleaseFreeMemoryFunction(
ReleaseFreeMemoryFunction release_free_memory_function);
ReleaseFreeMemoryFunction GetReleaseFreeMemoryFunction();
} // namespace thunks
} // namespace allocator
} // namespace base
#endif
This diff is collapsed.
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_ALLOCATOR_SHIM_H_
#define BASE_ALLOCATOR_ALLOCATOR_SHIM_H_
namespace base {
namespace allocator {
// Resets the environment variable CHROME_ALLOCATOR to specify the choice to
// be used by subprocesses. Priority is given to the current value of
// CHROME_ALLOCATOR_2 (if specified), then CHROME_ALLOCATOR (if specified), and
// then a default value (typically set to TCMALLOC).
void SetupSubprocessAllocator();
// Expose some of tcmalloc functions for test.
void* TCMallocDoMallocForTest(size_t size);
void TCMallocDoFreeForTest(void* ptr);
size_t ExcludeSpaceForMarkForTest(size_t size);
} // namespace allocator.
} // namespace base.
#endif // BASE_ALLOCATOR_ALLOCATOR_SHIM_H_
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="..">
<UniqueIdentifier>{739DB09A-CC57-A953-A6CF-F64FA08E4FA7}</UniqueIdentifier>
</Filter>
<Filter Include="..\profiler">
<UniqueIdentifier>{87097DB4-0A18-6E42-07AB-BF3B3651C11F}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="allocator_unittests.cc"/>
<None Include="allocator.gyp"/>
<ClInclude Include="..\profiler\alternate_timer.h">
<Filter>..\profiler</Filter>
</ClInclude>
<ClCompile Include="..\profiler\alternate_timer.cc">
<Filter>..\profiler</Filter>
</ClCompile>
</ItemGroup>
</Project>
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#if defined(TCMALLOC_FOR_DEBUGALLOCATION)
#include "third_party/tcmalloc/chromium/src/debugallocation.cc"
#else
#include "third_party/tcmalloc/chromium/src/tcmalloc.cc"
#endif
This diff is collapsed.
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="_excluded_files">
<UniqueIdentifier>{158E591E-B6EA-0C85-8F5A-18EAFA09B4CE}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="allocator.gyp"/>
<None Include="prep_libc.py">
<Filter>_excluded_files</Filter>
</None>
</ItemGroup>
</Project>
#!/usr/bin/env python
# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# This script takes libcmt.lib for VS2005/08/10 and removes the allocation
# related functions from it.
#
# Usage: prep_libc.py <VCLibDir> <OutputDir> <arch>
#
# VCLibDir is the path where VC is installed, something like:
# C:\Program Files\Microsoft Visual Studio 8\VC\lib
# OutputDir is the directory where the modified libcmt file should be stored.
# arch is either 'ia32' or 'x64'
import os
import shutil
import subprocess
import sys
def run(command, filter=None):
"""Run |command|, removing any lines that match |filter|. The filter is
to remove the echoing of input filename that 'lib' does."""
popen = subprocess.Popen(
command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, _ = popen.communicate()
for line in out.splitlines():
if filter and line.strip() != filter:
print line
return popen.returncode
def main():
bindir = 'SELF_X86'
objdir = 'INTEL'
vs_install_dir = sys.argv[1]
outdir = sys.argv[2]
if "x64" in sys.argv[3]:
bindir = 'SELF_64_amd64'
objdir = 'amd64'
vs_install_dir = os.path.join(vs_install_dir, 'amd64')
output_lib = os.path.join(outdir, 'libcmt.lib')
shutil.copyfile(os.path.join(vs_install_dir, 'libcmt.lib'), output_lib)
shutil.copyfile(os.path.join(vs_install_dir, 'libcmt.pdb'),
os.path.join(outdir, 'libcmt.pdb'))
vspaths = [
'build\\intel\\mt_obj\\',
'f:\\dd\\vctools\\crt_bld\\' + bindir + \
'\\crt\\src\\build\\' + objdir + '\\mt_obj\\',
'F:\\dd\\vctools\\crt_bld\\' + bindir + \
'\\crt\\src\\build\\' + objdir + '\\mt_obj\\nativec\\\\',
'F:\\dd\\vctools\\crt_bld\\' + bindir + \
'\\crt\\src\\build\\' + objdir + '\\mt_obj\\nativecpp\\\\' ]
objfiles = ['malloc', 'free', 'realloc', 'new', 'delete', 'new2', 'delete2',
'align', 'msize', 'heapinit', 'expand', 'heapchk', 'heapwalk',
'heapmin', 'sbheap', 'calloc', 'recalloc', 'calloc_impl',
'new_mode', 'newopnt']
for obj in objfiles:
for vspath in vspaths:
cmd = ('lib /nologo /ignore:4006,4014,4221 /remove:%s%s.obj %s' %
(vspath, obj, output_lib))
run(cmd, obj + '.obj')
if __name__ == "__main__":
sys.exit(main())
This diff is collapsed.
// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef BASE_ALLOCATOR_TYPE_PROFILER_H_
#define BASE_ALLOCATOR_TYPE_PROFILER_H_
#if defined(TYPE_PROFILING)
#include <stddef.h> // for size_t
#include <typeinfo> // for std::typeinfo
namespace base {
namespace type_profiler {
typedef void* InterceptFunction(void*, size_t, const std::type_info&);
class InterceptFunctions {
public:
// It must be called only once in a process while it is in single-thread.
// For now, ContentMainRunnerImpl::Initialize is the only supposed caller
// of this function except for single-threaded unit tests.
static void SetFunctions(InterceptFunction* new_intercept,
InterceptFunction* delete_intercept);
private:
friend class TypeProfilerTest;
// These functions are not thread safe.
// They must be used only from single-threaded unit tests.
static void ResetFunctions();
static bool IsAvailable();
};
} // namespace type_profiler
} // namespace base
#endif // defined(TYPE_PROFILING)
#endif // BASE_ALLOCATOR_TYPE_PROFILER_H_
This diff is collapsed.
This diff is collapsed.
bulach@chromium.org
joth@chromium.org
jcivelli@chromium.org
yfriedman@chromium.org
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment