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

/************************************************************************
**
**	Set up the various dprintf variables based on the configuration file.
**
************************************************************************/

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_string.h"
#include "condor_sys_types.h"

#if HAVE_BACKTRACE
#include "sig_install.h"
#endif

int		Termlog = 0;

extern int		DebugFlags;
#ifdef WIN32
extern FILE		*DebugFPs[D_NUMLEVELS+1];
#else
extern FILE		*DebugFP;
#endif
extern off_t		MaxLog[D_NUMLEVELS+1];
extern int 			MaxLogNum[D_NUMLEVELS+1];
extern char		*DebugFile[D_NUMLEVELS+1];
extern char		*DebugLock;
extern const char		*_condor_DebugFlagNames[];
extern int		_condor_dprintf_works;
extern time_t	DebugLastMod;
extern int		DebugUseTimestamps;
extern int      DebugContinueOnOpenFailure;
extern int		log_keep_open;

extern void		_condor_set_debug_flags( const char *strflags );
extern void		_condor_dprintf_saved_lines( void );

#if HAVE_EXT_GCB
void	_condor_gcb_dprintf_va( int flags, char* fmt, va_list args );
extern "C" void Generic_set_log_va(void(*app_log_va)(int level, char *fmt, va_list args));
#endif

#if HAVE_BACKTRACE
static void
sig_backtrace_handler(int signum)
{
	dprintf_dump_stack();

		// terminate for the same reason.
	struct sigaction sa;
	sa.sa_handler = SIG_DFL;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(signum, &sa, NULL);
	sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);

	raise(signum);
}

static void
install_backtrace_handler(void)
{
	sigset_t fullset;
	sigfillset( &fullset );
	install_sig_handler_with_mask(SIGSEGV, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGABRT, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGILL, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGFPE, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGBUS, &fullset, sig_backtrace_handler);
}
#endif

int
dprintf_config_ContinueOnFailure ( int fContinue )
{
    int fOld = DebugContinueOnOpenFailure;
	DebugContinueOnOpenFailure = fContinue;
	return fOld;
}

void
dprintf_config( const char *subsys )
{
	char pname[ BUFSIZ ];
	char *pval;
	static int first_time = 1;
	int want_truncate;
	int debug_level;
	FILE *debug_file_fp;

	/*
	**  We want to initialize this here so if we reconfig and the
	**	debug flags have changed, we actually use the new
	**  flags.  -Derek Wright 12/8/97
	*/
	DebugFlags = D_ALWAYS;

	/*
	** First, add the debug flags that are shared by everyone.
	*/
	pval = param("ALL_DEBUG");
	if( pval ) {
		_condor_set_debug_flags( pval );
		free( pval );
	}

	/*
	**  Then, pick up the subsys_DEBUG parameters.   Note: if we don't have
	**  anything set, we just leave it as D_ALWAYS.
	*/
	(void)sprintf(pname, "%s_DEBUG", subsys);
	pval = param(pname);
	if( pval ) {
		_condor_set_debug_flags( pval );
		free( pval );
	}

#ifdef WIN32
		/* Two reasons why we need to lock the log in Windows
		 * (when a lock is configured)
		 * 1) File rotation requires exclusive access in Windows.
		 * 2) O_APPEND doesn't guarantee atomic writes in Windows
		 */
	DebugShouldLockToAppend = 1;
#else
	DebugShouldLockToAppend = param_boolean_int("LOCK_DEBUG_LOG_TO_APPEND",0);
#endif

	/*
	**	If this is not going to the terminal, pick up the name
	**	of the log file, maximum log size, and the name of the
	**	lock file (if it is specified).
	*/
	if( !( Termlog) ) {
		for (debug_level = 0; debug_level <= D_NUMLEVELS; debug_level++) {
			want_truncate = 0;
			if (debug_level == 0) {
				/*
				** the level 0 file gets all debug messages; thus, the
				** offset into DebugFlagNames is off by one, since the
				** first level-specific file goes into the other arrays at
				** index 1
				*/
				(void)sprintf(pname, "%s_LOG", subsys);
			} else {
				(void)sprintf(pname, "%s_%s_LOG", subsys,
							  _condor_DebugFlagNames[debug_level-1]+2);
			}

			// Hold a temporary copy of the old file pointer until
			// *after* the param -- param can dprintf() in some cases
			{
				char	*tmp = DebugFile[debug_level];

				// NEGOTIATOR_MATCH_LOG is necessary by default, but debug_level
				// is not 0
				if(debug_level == 0)
				{
					char	*tmp2 = param(pname);

					// No default value found, so use $(LOG)/$(SUBSYSTEM)Log
					if(!tmp2) {
						// This char* will never be freed, but as long as
						// defaults are defined in condor_c++_util/param_info.in
						// we will never get here.
						char *str;
						char *log = param("LOG");
						char *lsubsys = param("SUBSYSTEM");
						if(!log || !lsubsys) {
							EXCEPT("Unable to find LOG or SUBSYSTEM.\n");
						}

						str = (char*)malloc(strlen(log) + strlen(lsubsys) + 5);
						sprintf(str, "%s%c%sLog", log, DIR_DELIM_CHAR, lsubsys);

						DebugFile[debug_level] = str;

						free(log);
						free(lsubsys);
					}
					else {
						DebugFile[debug_level] = tmp2;
					}
				}
				else {
					// This is looking up configuration options that I can't
					// find documentation for, so intead of coding in an
					// incorrect default value, I'm gonna use
					// param_without_default.
					// tristan 5/29/09
					DebugFile[debug_level] = param_without_default(pname);
				}
				if ( tmp ) {
					free( tmp );
				}
			}

			if( debug_level == 0 && DebugFile[0] == NULL ) {
				EXCEPT("No '%s' parameter specified.", pname);
			} else if ( DebugFile[debug_level] != NULL ) {

				if (debug_level == 0 && first_time) {
					struct stat stat_buf;
					if ( stat( DebugFile[debug_level], &stat_buf ) >= 0 ) {
						DebugLastMod = stat_buf.st_mtime > stat_buf.st_ctime ? stat_buf.st_mtime : stat_buf.st_ctime;
					} else {
						DebugLastMod = -errno;
					}
				}

				if (debug_level == 0) {
					(void)sprintf(pname, "TRUNC_%s_LOG_ON_OPEN", subsys);
				} else {
					(void)sprintf(pname, "TRUNC_%s_%s_LOG_ON_OPEN", subsys,
								  _condor_DebugFlagNames[debug_level-1]+2);
				}
				pval = param(pname);
				if( pval ) {
					if( *pval == 't' || *pval == 'T' ) {
						want_truncate = 1;
					}
					free(pval);
				}

				if (debug_level == 0) {
					(void)sprintf(pname, "%s_LOCK", subsys);
					if (DebugLock) {
						free(DebugLock);
					}
					DebugLock = param(pname);
				}

				if( first_time && want_truncate ) {
					debug_file_fp = debug_lock(debug_level, "w", 0);
				} else {
					debug_file_fp = debug_lock(debug_level, "a", 0);
				}

				if( debug_file_fp == NULL && debug_level == 0 ) {
                   #ifdef WIN32
					/*
					** If we could not open the log file, we might want to keep running anyway.
					** If we do, then set the log filename to NUL so we don't keep trying
					** (and failing) to open the file.
					*/
					if (DebugContinueOnOpenFailure) {

						// change the debug file to point to the NUL device.
						static const char strDevNull[] = "NUL";//"\\\\.\\Device\\Null";
						char * psz = (char*)malloc(sizeof(strDevNull));
						strcpy(psz, strDevNull);
						if (DebugFile[debug_level])
							free(DebugFile[debug_level]);
						DebugFile[debug_level] = psz;

					} else
                   #endif
					{
					    EXCEPT("Cannot open log file '%s'",
						       DebugFile[debug_level]);
					}
				}

				if (debug_file_fp) (void)debug_unlock( debug_level );
				debug_file_fp = NULL;

				if (debug_level == 0) {
					(void)sprintf(pname, "MAX_%s_LOG", subsys);
				} else {
					(void)sprintf(pname, "MAX_%s_%s_LOG", subsys,
								  _condor_DebugFlagNames[debug_level-1]+2);
				}
				pval = param(pname);
				if( pval != NULL ) {
					MaxLog[debug_level] = atoi( pval );
					free(pval);
				} else {
					MaxLog[debug_level] = 1024*1024;
				}

				if (debug_level == 0) {
					(void)sprintf(pname, "MAX_NUM_%s_LOG", subsys);
				} else {
					(void)sprintf(pname, "MAX_NUM_%s_%s_LOG", subsys,
								  _condor_DebugFlagNames[debug_level-1]+2);
				}
				pval = param(pname);
				if (pval != NULL) {
					MaxLogNum[debug_level] = atoi(pval);
					free(pval);
				} else {
					MaxLogNum[debug_level] = 1;
				}
			}
		}
	} else {

#if !defined(WIN32)
		setlinebuf( stderr );
#endif

		(void)fflush( stderr );	/* Don't know why we need this, but if not here
							   the first couple dprintf don't come out right */
	}

	if(!DebugLock) {
		sprintf(pname, "%s_LOG_KEEP_OPEN", subsys);
		log_keep_open = param_boolean_int(pname, FALSE);
	}

	first_time = 0;
	_condor_dprintf_works = 1;
#if HAVE_EXT_GCB
		/*
		  this method currently only lives in libGCB.a, so don't even
		  try to param() or call this function unless we're on a
		  platform where we're using the GCB external
		*/
    if ( param_boolean_int("NET_REMAP_ENABLE", 0) ) {
        Generic_set_log_va(_condor_gcb_dprintf_va);
    }
#endif

		/*
		  If LOGS_USE_TIMESTAMP is enabled, we will print out Unix timestamps
		  instead of the standard date format in all the log messages
		*/
	DebugUseTimestamps = param_boolean_int( "LOGS_USE_TIMESTAMP", FALSE );

#if HAVE_BACKTRACE
	install_backtrace_handler();
#endif

	_condor_dprintf_saved_lines();
}

#if HAVE_EXT_GCB
void
_condor_gcb_dprintf_va( int flags, char* fmt, va_list args )
{
	char* new_fmt;
	int len;

	len = strlen(fmt);
	new_fmt = (char*) malloc( (len + 6) * sizeof(char) );
	if( ! new_fmt ) {
		EXCEPT( "_condor_gcb_dprintf_va() out of memory!" );
	}
	snprintf( new_fmt, len + 6, "GCB: %s", fmt );
	_condor_dprintf_va( flags, new_fmt, args );
	free( new_fmt );
}
#endif /* HAVE_EXT_GCB */
<commit_msg>Turn on keeping file open by default on Windows for testing purposes.  Ticket #2064.<commit_after>/***************************************************************
 *
 * Copyright (C) 1990-2007, Condor Team, Computer Sciences Department,
 * University of Wisconsin-Madison, WI.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you
 * may not use this file except in compliance with the License.  You may
 * obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ***************************************************************/

/************************************************************************
**
**	Set up the various dprintf variables based on the configuration file.
**
************************************************************************/

#include "condor_common.h"
#include "condor_debug.h"
#include "condor_string.h"
#include "condor_sys_types.h"

#if HAVE_BACKTRACE
#include "sig_install.h"
#endif

int		Termlog = 0;

extern int		DebugFlags;
#ifdef WIN32
extern FILE		*DebugFPs[D_NUMLEVELS+1];
#else
extern FILE		*DebugFP;
#endif
extern off_t		MaxLog[D_NUMLEVELS+1];
extern int 			MaxLogNum[D_NUMLEVELS+1];
extern char		*DebugFile[D_NUMLEVELS+1];
extern char		*DebugLock;
extern const char		*_condor_DebugFlagNames[];
extern int		_condor_dprintf_works;
extern time_t	DebugLastMod;
extern int		DebugUseTimestamps;
extern int      DebugContinueOnOpenFailure;
extern int		log_keep_open;

extern void		_condor_set_debug_flags( const char *strflags );
extern void		_condor_dprintf_saved_lines( void );

#if HAVE_EXT_GCB
void	_condor_gcb_dprintf_va( int flags, char* fmt, va_list args );
extern "C" void Generic_set_log_va(void(*app_log_va)(int level, char *fmt, va_list args));
#endif

#if HAVE_BACKTRACE
static void
sig_backtrace_handler(int signum)
{
	dprintf_dump_stack();

		// terminate for the same reason.
	struct sigaction sa;
	sa.sa_handler = SIG_DFL;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = 0;
	sigaction(signum, &sa, NULL);
	sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL);

	raise(signum);
}

static void
install_backtrace_handler(void)
{
	sigset_t fullset;
	sigfillset( &fullset );
	install_sig_handler_with_mask(SIGSEGV, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGABRT, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGILL, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGFPE, &fullset, sig_backtrace_handler);
	install_sig_handler_with_mask(SIGBUS, &fullset, sig_backtrace_handler);
}
#endif

int
dprintf_config_ContinueOnFailure ( int fContinue )
{
    int fOld = DebugContinueOnOpenFailure;
	DebugContinueOnOpenFailure = fContinue;
	return fOld;
}

void
dprintf_config( const char *subsys )
{
	char pname[ BUFSIZ ];
	char *pval;
	static int first_time = 1;
	int want_truncate;
	int debug_level;
	FILE *debug_file_fp;

	/*
	**  We want to initialize this here so if we reconfig and the
	**	debug flags have changed, we actually use the new
	**  flags.  -Derek Wright 12/8/97
	*/
	DebugFlags = D_ALWAYS;

	/*
	** First, add the debug flags that are shared by everyone.
	*/
	pval = param("ALL_DEBUG");
	if( pval ) {
		_condor_set_debug_flags( pval );
		free( pval );
	}

	/*
	**  Then, pick up the subsys_DEBUG parameters.   Note: if we don't have
	**  anything set, we just leave it as D_ALWAYS.
	*/
	(void)sprintf(pname, "%s_DEBUG", subsys);
	pval = param(pname);
	if( pval ) {
		_condor_set_debug_flags( pval );
		free( pval );
	}

#ifdef WIN32
		/* Two reasons why we need to lock the log in Windows
		 * (when a lock is configured)
		 * 1) File rotation requires exclusive access in Windows.
		 * 2) O_APPEND doesn't guarantee atomic writes in Windows
		 */
	DebugShouldLockToAppend = 1;
#else
	DebugShouldLockToAppend = param_boolean_int("LOCK_DEBUG_LOG_TO_APPEND",0);
#endif

	/*
	**	If this is not going to the terminal, pick up the name
	**	of the log file, maximum log size, and the name of the
	**	lock file (if it is specified).
	*/
	if( !( Termlog) ) {
		for (debug_level = 0; debug_level <= D_NUMLEVELS; debug_level++) {
			want_truncate = 0;
			if (debug_level == 0) {
				/*
				** the level 0 file gets all debug messages; thus, the
				** offset into DebugFlagNames is off by one, since the
				** first level-specific file goes into the other arrays at
				** index 1
				*/
				(void)sprintf(pname, "%s_LOG", subsys);
			} else {
				(void)sprintf(pname, "%s_%s_LOG", subsys,
							  _condor_DebugFlagNames[debug_level-1]+2);
			}

			// Hold a temporary copy of the old file pointer until
			// *after* the param -- param can dprintf() in some cases
			{
				char	*tmp = DebugFile[debug_level];

				// NEGOTIATOR_MATCH_LOG is necessary by default, but debug_level
				// is not 0
				if(debug_level == 0)
				{
					char	*tmp2 = param(pname);

					// No default value found, so use $(LOG)/$(SUBSYSTEM)Log
					if(!tmp2) {
						// This char* will never be freed, but as long as
						// defaults are defined in condor_c++_util/param_info.in
						// we will never get here.
						char *str;
						char *log = param("LOG");
						char *lsubsys = param("SUBSYSTEM");
						if(!log || !lsubsys) {
							EXCEPT("Unable to find LOG or SUBSYSTEM.\n");
						}

						str = (char*)malloc(strlen(log) + strlen(lsubsys) + 5);
						sprintf(str, "%s%c%sLog", log, DIR_DELIM_CHAR, lsubsys);

						DebugFile[debug_level] = str;

						free(log);
						free(lsubsys);
					}
					else {
						DebugFile[debug_level] = tmp2;
					}
				}
				else {
					// This is looking up configuration options that I can't
					// find documentation for, so intead of coding in an
					// incorrect default value, I'm gonna use
					// param_without_default.
					// tristan 5/29/09
					DebugFile[debug_level] = param_without_default(pname);
				}
				if ( tmp ) {
					free( tmp );
				}
			}

			if( debug_level == 0 && DebugFile[0] == NULL ) {
				EXCEPT("No '%s' parameter specified.", pname);
			} else if ( DebugFile[debug_level] != NULL ) {

				if (debug_level == 0 && first_time) {
					struct stat stat_buf;
					if ( stat( DebugFile[debug_level], &stat_buf ) >= 0 ) {
						DebugLastMod = stat_buf.st_mtime > stat_buf.st_ctime ? stat_buf.st_mtime : stat_buf.st_ctime;
					} else {
						DebugLastMod = -errno;
					}
				}

				if (debug_level == 0) {
					(void)sprintf(pname, "TRUNC_%s_LOG_ON_OPEN", subsys);
				} else {
					(void)sprintf(pname, "TRUNC_%s_%s_LOG_ON_OPEN", subsys,
								  _condor_DebugFlagNames[debug_level-1]+2);
				}
				pval = param(pname);
				if( pval ) {
					if( *pval == 't' || *pval == 'T' ) {
						want_truncate = 1;
					}
					free(pval);
				}

				if (debug_level == 0) {
					(void)sprintf(pname, "%s_LOCK", subsys);
					if (DebugLock) {
						free(DebugLock);
					}
					DebugLock = param(pname);
				}

				if( first_time && want_truncate ) {
					debug_file_fp = debug_lock(debug_level, "w", 0);
				} else {
					debug_file_fp = debug_lock(debug_level, "a", 0);
				}

				if( debug_file_fp == NULL && debug_level == 0 ) {
                   #ifdef WIN32
					/*
					** If we could not open the log file, we might want to keep running anyway.
					** If we do, then set the log filename to NUL so we don't keep trying
					** (and failing) to open the file.
					*/
					if (DebugContinueOnOpenFailure) {

						// change the debug file to point to the NUL device.
						static const char strDevNull[] = "NUL";//"\\\\.\\Device\\Null";
						char * psz = (char*)malloc(sizeof(strDevNull));
						strcpy(psz, strDevNull);
						if (DebugFile[debug_level])
							free(DebugFile[debug_level]);
						DebugFile[debug_level] = psz;

					} else
                   #endif
					{
					    EXCEPT("Cannot open log file '%s'",
						       DebugFile[debug_level]);
					}
				}

				if (debug_file_fp) (void)debug_unlock( debug_level );
				debug_file_fp = NULL;

				if (debug_level == 0) {
					(void)sprintf(pname, "MAX_%s_LOG", subsys);
				} else {
					(void)sprintf(pname, "MAX_%s_%s_LOG", subsys,
								  _condor_DebugFlagNames[debug_level-1]+2);
				}
				pval = param(pname);
				if( pval != NULL ) {
					MaxLog[debug_level] = atoi( pval );
					free(pval);
				} else {
					MaxLog[debug_level] = 1024*1024;
				}

				if (debug_level == 0) {
					(void)sprintf(pname, "MAX_NUM_%s_LOG", subsys);
				} else {
					(void)sprintf(pname, "MAX_NUM_%s_%s_LOG", subsys,
								  _condor_DebugFlagNames[debug_level-1]+2);
				}
				pval = param(pname);
				if (pval != NULL) {
					MaxLogNum[debug_level] = atoi(pval);
					free(pval);
				} else {
					MaxLogNum[debug_level] = 1;
				}
			}
		}
	} else {

#if !defined(WIN32)
		setlinebuf( stderr );
#endif

		(void)fflush( stderr );	/* Don't know why we need this, but if not here
							   the first couple dprintf don't come out right */
	}
#ifdef WIN32
	if(!DebugLock) {
		sprintf(pname, "%s_LOG_KEEP_OPEN", subsys);
		log_keep_open = param_boolean_int(pname, TRUE);
	}
#endif
	first_time = 0;
	_condor_dprintf_works = 1;
#if HAVE_EXT_GCB
		/*
		  this method currently only lives in libGCB.a, so don't even
		  try to param() or call this function unless we're on a
		  platform where we're using the GCB external
		*/
    if ( param_boolean_int("NET_REMAP_ENABLE", 0) ) {
        Generic_set_log_va(_condor_gcb_dprintf_va);
    }
#endif

		/*
		  If LOGS_USE_TIMESTAMP is enabled, we will print out Unix timestamps
		  instead of the standard date format in all the log messages
		*/
	DebugUseTimestamps = param_boolean_int( "LOGS_USE_TIMESTAMP", FALSE );

#if HAVE_BACKTRACE
	install_backtrace_handler();
#endif

	_condor_dprintf_saved_lines();
}

#if HAVE_EXT_GCB
void
_condor_gcb_dprintf_va( int flags, char* fmt, va_list args )
{
	char* new_fmt;
	int len;

	len = strlen(fmt);
	new_fmt = (char*) malloc( (len + 6) * sizeof(char) );
	if( ! new_fmt ) {
		EXCEPT( "_condor_gcb_dprintf_va() out of memory!" );
	}
	snprintf( new_fmt, len + 6, "GCB: %s", fmt );
	_condor_dprintf_va( flags, new_fmt, args );
	free( new_fmt );
}
#endif /* HAVE_EXT_GCB */
<|endoftext|>


<commit_before>#include "MCAbstractPart.h"

#include <string.h>
#include <stdlib.h>
#include <libetpan/libetpan.h>
#include "MCData.h"

using namespace mailcore;

AbstractPart::AbstractPart()
{
    init();
}

AbstractPart::AbstractPart(AbstractPart * other)
{
    init();
    setUniqueID(other->mUniqueID);
    setFilename(other->mFilename);
    setMimeType(other->mMimeType);
    setCharset(other->mCharset);
    setContentID(other->mContentID);
    setContentLocation(other->mContentLocation);
    setInlineAttachment(other->mInlineAttachment);
    setPartType(other->mPartType);
}

void AbstractPart::init()
{
    mUniqueID = NULL;
    mFilename = NULL;
    mMimeType = NULL;
    mCharset = NULL;
    mContentID = NULL;
    mContentLocation = NULL;
    mInlineAttachment = false;
    mPartType = PartTypeSingle;
}

AbstractPart::~AbstractPart()
{
    MC_SAFE_RELEASE(mUniqueID);
    MC_SAFE_RELEASE(mFilename);
    MC_SAFE_RELEASE(mMimeType);
    MC_SAFE_RELEASE(mCharset);
    MC_SAFE_RELEASE(mContentID);
    MC_SAFE_RELEASE(mContentLocation);
}

String * AbstractPart::description()
{
    String * result = String::string();
    result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this);
    if (mFilename != NULL) {
        result->appendUTF8Format("filename: %s\n", mFilename->UTF8Characters());
    }
    if (mMimeType != NULL) {
        result->appendUTF8Format("mime type: %s\n", mMimeType->UTF8Characters());
    }
    if (mCharset != NULL) {
        result->appendUTF8Format("charset: %s\n", mCharset->UTF8Characters());
    }
    if (mContentID != NULL) {
        result->appendUTF8Format("content-ID: %s\n", mContentID->UTF8Characters());
    }
    if (mContentLocation != NULL) {
        result->appendUTF8Format("content-location: %s\n", mContentLocation->UTF8Characters());
    }
    result->appendUTF8Format("inline: %i\n", mInlineAttachment);
    result->appendUTF8Format(">");

    return result;
}

Object * AbstractPart::copy()
{
    return new AbstractPart(this);
}

PartType AbstractPart::partType()
{
    return mPartType;
}

void AbstractPart::setPartType(PartType type)
{
    mPartType = type;
}

String * AbstractPart::uniqueID()
{
    return mUniqueID;
}

void AbstractPart::setUniqueID(String * uniqueID)
{
    MC_SAFE_REPLACE_COPY(String, mUniqueID, uniqueID);
}

String * AbstractPart::filename()
{
    return mFilename;
}

void AbstractPart::setFilename(String * filename)
{
    MC_SAFE_REPLACE_COPY(String, mFilename, filename);
}

String * AbstractPart::mimeType()
{
    return mMimeType;
}

void AbstractPart::setMimeType(String * mimeType)
{
    MC_SAFE_REPLACE_COPY(String, mMimeType, mimeType);
}

String * AbstractPart::charset()
{
    return mCharset;
}

void AbstractPart::setCharset(String * charset)
{
    MC_SAFE_REPLACE_COPY(String, mCharset, charset);
}

String * AbstractPart::contentID()
{
    return mContentID;
}

void AbstractPart::setContentID(String * contentID)
{
    MC_SAFE_REPLACE_COPY(String, mContentID, contentID);
}

String * AbstractPart::contentLocation()
{
    return mContentLocation;
}

void AbstractPart::setContentLocation(String * contentLocation)
{
    MC_SAFE_REPLACE_COPY(String, mContentLocation, contentLocation);
}

bool AbstractPart::isInlineAttachment()
{
    return mInlineAttachment;
}

void AbstractPart::setInlineAttachment(bool inlineAttachment)
{
    mInlineAttachment = inlineAttachment;
}

AbstractMessage * AbstractPart::message()
{
    return mMessage;
}

void AbstractPart::setMessage(AbstractMessage * message)
{
    mMessage = message;
}

void AbstractPart::importIMAPFields(struct mailimap_body_fields * fields,
    struct mailimap_body_ext_1part * extension)
{
	if (fields->bd_parameter != NULL) {
		clistiter * cur;

		for(cur = clist_begin(fields->bd_parameter->pa_list) ; cur != NULL ;
			cur = clist_next(cur)) {
			struct mailimap_single_body_fld_param * imap_param;

			imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur);

			if (strcasecmp(imap_param->pa_name, "name") == 0) {
                setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value));
			}
			else if (strcasecmp(imap_param->pa_name, "charset") == 0) {
                setCharset(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value));
			}
		}
	}
    if (fields->bd_id != NULL) {
		char * contentid;
		size_t cur_token;
		int r;

		cur_token = 0;
		r = mailimf_msg_id_parse(fields->bd_id, strlen(fields->bd_id),
            &cur_token, &contentid);
		if (r == MAILIMF_NO_ERROR) {
			// msg id
            setContentID(String::stringWithUTF8Characters(contentid));
            free(contentid);
		}
    }

    if (extension != NULL) {
        if (extension->bd_disposition != NULL) {
            if (strcasecmp(extension->bd_disposition->dsp_type, "inline") == 0) {
                setInlineAttachment(true);
            }

            if (extension->bd_disposition->dsp_attributes != NULL) {
                clistiter * cur;

                for(cur = clist_begin(extension->bd_disposition->dsp_attributes->pa_list) ; cur != NULL ;
                    cur = clist_next(cur)) {
                    struct mailimap_single_body_fld_param * imap_param;

                    imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur);

                    if (strcasecmp(imap_param->pa_name, "filename") == 0) {
                        setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value));
                    }
                }
            }
        }

        if (extension->bd_loc != NULL) {
            setContentLocation(String::stringWithUTF8Characters(extension->bd_loc));
        }
    }
}

AbstractPart * AbstractPart::partForContentID(String * contentID)
{
    if (contentID->isEqual(mContentID)) {
        return this;
    }
    else {
        return NULL;
    }
}

AbstractPart * AbstractPart::partForUniqueID(String * uniqueID)
{
    if (uniqueID->isEqual(mUniqueID)) {
        return this;
    }
    else {
        return NULL;
    }
}

String * AbstractPart::decodedStringForData(Data * data)
{
	if (mMimeType && mMimeType->hasPrefix(MCSTR("text/"))) {
		return data->stringWithDetectedCharset(mCharset, false);
	}
	else {
		return NULL;
	}
}
<commit_msg>Added check for text/html<commit_after>#include "MCAbstractPart.h"

#include <string.h>
#include <stdlib.h>
#include <libetpan/libetpan.h>
#include "MCData.h"

using namespace mailcore;

AbstractPart::AbstractPart()
{
    init();
}

AbstractPart::AbstractPart(AbstractPart * other)
{
    init();
    setUniqueID(other->mUniqueID);
    setFilename(other->mFilename);
    setMimeType(other->mMimeType);
    setCharset(other->mCharset);
    setContentID(other->mContentID);
    setContentLocation(other->mContentLocation);
    setInlineAttachment(other->mInlineAttachment);
    setPartType(other->mPartType);
}

void AbstractPart::init()
{
    mUniqueID = NULL;
    mFilename = NULL;
    mMimeType = NULL;
    mCharset = NULL;
    mContentID = NULL;
    mContentLocation = NULL;
    mInlineAttachment = false;
    mPartType = PartTypeSingle;
}

AbstractPart::~AbstractPart()
{
    MC_SAFE_RELEASE(mUniqueID);
    MC_SAFE_RELEASE(mFilename);
    MC_SAFE_RELEASE(mMimeType);
    MC_SAFE_RELEASE(mCharset);
    MC_SAFE_RELEASE(mContentID);
    MC_SAFE_RELEASE(mContentLocation);
}

String * AbstractPart::description()
{
    String * result = String::string();
    result->appendUTF8Format("<%s:%p\n", className()->UTF8Characters(), this);
    if (mFilename != NULL) {
        result->appendUTF8Format("filename: %s\n", mFilename->UTF8Characters());
    }
    if (mMimeType != NULL) {
        result->appendUTF8Format("mime type: %s\n", mMimeType->UTF8Characters());
    }
    if (mCharset != NULL) {
        result->appendUTF8Format("charset: %s\n", mCharset->UTF8Characters());
    }
    if (mContentID != NULL) {
        result->appendUTF8Format("content-ID: %s\n", mContentID->UTF8Characters());
    }
    if (mContentLocation != NULL) {
        result->appendUTF8Format("content-location: %s\n", mContentLocation->UTF8Characters());
    }
    result->appendUTF8Format("inline: %i\n", mInlineAttachment);
    result->appendUTF8Format(">");

    return result;
}

Object * AbstractPart::copy()
{
    return new AbstractPart(this);
}

PartType AbstractPart::partType()
{
    return mPartType;
}

void AbstractPart::setPartType(PartType type)
{
    mPartType = type;
}

String * AbstractPart::uniqueID()
{
    return mUniqueID;
}

void AbstractPart::setUniqueID(String * uniqueID)
{
    MC_SAFE_REPLACE_COPY(String, mUniqueID, uniqueID);
}

String * AbstractPart::filename()
{
    return mFilename;
}

void AbstractPart::setFilename(String * filename)
{
    MC_SAFE_REPLACE_COPY(String, mFilename, filename);
}

String * AbstractPart::mimeType()
{
    return mMimeType;
}

void AbstractPart::setMimeType(String * mimeType)
{
    MC_SAFE_REPLACE_COPY(String, mMimeType, mimeType);
}

String * AbstractPart::charset()
{
    return mCharset;
}

void AbstractPart::setCharset(String * charset)
{
    MC_SAFE_REPLACE_COPY(String, mCharset, charset);
}

String * AbstractPart::contentID()
{
    return mContentID;
}

void AbstractPart::setContentID(String * contentID)
{
    MC_SAFE_REPLACE_COPY(String, mContentID, contentID);
}

String * AbstractPart::contentLocation()
{
    return mContentLocation;
}

void AbstractPart::setContentLocation(String * contentLocation)
{
    MC_SAFE_REPLACE_COPY(String, mContentLocation, contentLocation);
}

bool AbstractPart::isInlineAttachment()
{
    return mInlineAttachment;
}

void AbstractPart::setInlineAttachment(bool inlineAttachment)
{
    mInlineAttachment = inlineAttachment;
}

AbstractMessage * AbstractPart::message()
{
    return mMessage;
}

void AbstractPart::setMessage(AbstractMessage * message)
{
    mMessage = message;
}

void AbstractPart::importIMAPFields(struct mailimap_body_fields * fields,
    struct mailimap_body_ext_1part * extension)
{
	if (fields->bd_parameter != NULL) {
		clistiter * cur;

		for(cur = clist_begin(fields->bd_parameter->pa_list) ; cur != NULL ;
			cur = clist_next(cur)) {
			struct mailimap_single_body_fld_param * imap_param;

			imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur);

			if (strcasecmp(imap_param->pa_name, "name") == 0) {
                setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value));
			}
			else if (strcasecmp(imap_param->pa_name, "charset") == 0) {
                setCharset(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value));
			}
		}
	}
    if (fields->bd_id != NULL) {
		char * contentid;
		size_t cur_token;
		int r;

		cur_token = 0;
		r = mailimf_msg_id_parse(fields->bd_id, strlen(fields->bd_id),
            &cur_token, &contentid);
		if (r == MAILIMF_NO_ERROR) {
			// msg id
            setContentID(String::stringWithUTF8Characters(contentid));
            free(contentid);
		}
    }

    if (extension != NULL) {
        if (extension->bd_disposition != NULL) {
            if (strcasecmp(extension->bd_disposition->dsp_type, "inline") == 0) {
                setInlineAttachment(true);
            }

            if (extension->bd_disposition->dsp_attributes != NULL) {
                clistiter * cur;

                for(cur = clist_begin(extension->bd_disposition->dsp_attributes->pa_list) ; cur != NULL ;
                    cur = clist_next(cur)) {
                    struct mailimap_single_body_fld_param * imap_param;

                    imap_param = (struct mailimap_single_body_fld_param *) clist_content(cur);

                    if (strcasecmp(imap_param->pa_name, "filename") == 0) {
                        setFilename(String::stringByDecodingMIMEHeaderValue(imap_param->pa_value));
                    }
                }
            }
        }

        if (extension->bd_loc != NULL) {
            setContentLocation(String::stringWithUTF8Characters(extension->bd_loc));
        }
    }
}

AbstractPart * AbstractPart::partForContentID(String * contentID)
{
    if (contentID->isEqual(mContentID)) {
        return this;
    }
    else {
        return NULL;
    }
}

AbstractPart * AbstractPart::partForUniqueID(String * uniqueID)
{
    if (uniqueID->isEqual(mUniqueID)) {
        return this;
    }
    else {
        return NULL;
    }
}

String * AbstractPart::decodedStringForData(Data * data)
{
	String *lowerMimeType = mMimeType ? mMimeType->lowercaseString() : NULL;

	if (lowerMimeType && lowerMimeType->hasPrefix(MCSTR("text/"))) {
		bool isHTML = lowerMimeType->isEqual(MCSTR("text/html"));
		return data->stringWithDetectedCharset(mCharset, isHTML);
	}
	else {
		return NULL;
	}
}
<|endoftext|>


<commit_before>#include "ProcBody.h"
#include "../../Units/Units.h"
#include "../../Node/Node.h"
#include "../../ParseResult/ParseResult.h"
#include "../../Function/Function.h"
#include "../../CoreForms/CoreForms.h"
#include "../../Operation/Copy/Copy.h"
#include "../../Operation/Destruct/Destruct.h"
#include "../../Operation/CloseScope/CloseScope.h"
#include "../Linkage/Linkage.h"
#include "../Type/Type.h"
#include "../Proc/Inst/Inst.h"
#include "../../llvm_Function.h"

using namespace dale::ErrorInst;

namespace dale
{
bool
addVariables(Context *ctx, Node *node, Function *fn, llvm::BasicBlock *block)
{
    llvm::IRBuilder<> builder(block);

    bool past_first = false;
    for (std::vector<Variable *>::iterator b = fn->parameters.begin(),
                                           e = fn->parameters.end();
            b != e;
            ++b) {
        Variable *var = (*b);
        bool is_macro_varargs = false;
        if (var->type->base_type == BaseType::VarArgs) {
            if (!var->name.compare("rest")) {
                is_macro_varargs = true;
            } else {
                break;
            }
        }
        Variable *param_var = new Variable();
        var->copyTo(param_var);
        /* todo: It would be better if TypeRegister supported a
         * 'getReferencedType' function, to avoid the copying below.
         * */
        if (var->type->is_reference) {
            var->type->is_reference = false;
            param_var->type =
                ctx->tr->getPointerType(var->type->makeCopy());
            var->type->is_reference = true;
        } else if (var->type->is_rvalue_reference) {
            var->type->is_rvalue_reference = false;
            param_var->type =
                ctx->tr->getPointerType(var->type->makeCopy());
            var->type->is_rvalue_reference = true;
        } else {
            param_var->type = var->type;
        }
        param_var->linkage = Linkage::Auto;

        if (past_first && fn->is_macro) {
            /* Macro arguments, past the first, always have a type of
             * (p DNode), notwithstanding that the type in the
             * Function is unrestricted (to support overloading).
             * (Except for the 'rest' parameter.) */
            param_var->type = ctx->tr->type_pdnode;
            if (is_macro_varargs) {
                param_var->type =
                    ctx->tr->getPointerType(ctx->tr->type_pdnode);
            }
        }
        bool res = ctx->ns()->addVariable(param_var->name.c_str(), param_var);
        if (!res) {
            Error *e = new Error(RedefinitionOfVariable, node,
                                 param_var->name.c_str());
            ctx->er->addError(e);
            return false;
        }

        llvm::Type *llvm_type = ctx->toLLVMType(param_var->type, NULL, false);
        if (!llvm_type) {
            return false;
        }
        llvm::Value *param_var_ptr =
            llvm::cast<llvm::Value>(builder.CreateAlloca(llvm_type));
        llvm::Value *original_value = param_var->value;
        param_var->value = param_var_ptr;
        builder.CreateStore(original_value, param_var_ptr);
        past_first = true;
    }

    return true;
}

bool
addRetval(Context *ctx, Node *node, Function *fn,
          llvm::BasicBlock *block, llvm::Value *return_value)
{
    Variable *var = new Variable();

    var->type            = ctx->tr->getPointerType(fn->return_type);
    var->name            = "retval";
    var->symbol          = "retval";
    var->has_initialiser = false;
    var->once_tag        = "";
    var->index           = 0;
    var->linkage         = Linkage::Auto;

    bool res = ctx->ns()->addVariable(var->name.c_str(), var);
    if (!res) {
        Error *e = new Error(RedefinitionOfVariable, node,
                             var->name.c_str());
        ctx->er->addError(e);
        return false;
    }

    llvm::Type *llvm_type = ctx->toLLVMType(var->type, NULL,
                                            false);
    if (!llvm_type) {
        return false;
    }

    llvm::IRBuilder<> builder(block);
    llvm::Value *new_ptr =
        llvm::cast<llvm::Value>(builder.CreateAlloca(llvm_type));
    var->value = new_ptr;
    builder.CreateStore(return_value, new_ptr);

    return true;
}

bool
gotoCrossesDeclaration(DeferredGoto *dg, Label *label)
{
    /* If the label's namespace, or any namespace in which the label's
     * namespace is located, has a variable declaration with an index
     * smaller than that of the label, then the goto is going to cross
     * that variable declaration.  This is an error, because the
     * declaration may result in a destructor being called on scope
     * close, and the variable may not be initialised when the goto is
     * reached. */

    std::vector<Variable *> vars_before;
    Namespace *label_ns = label->ns;

    while (label_ns) {
        label_ns->getVarsBeforeIndex(label->index, &vars_before);
        if (vars_before.size() > 0) {
            for (std::vector<Variable*>::iterator b = vars_before.begin(),
                                                  e = vars_before.end();
                    b != e;
                    ++b) {
                if ((*b)->index >= dg->index) {
                    return true;
                }
            }
            vars_before.clear();
        }
        label_ns = label_ns->parent_namespace;
    }

    return false;
}

bool
resolveDeferredGotos(Context *ctx, Node *node, Function *fn,
                     llvm::BasicBlock *block)
{
    for (std::vector<DeferredGoto *>::iterator b = fn->deferred_gotos.begin(),
                                               e = fn->deferred_gotos.end();
            b != e;
            ++b) {
        DeferredGoto *dg = (*b);
        const char *label_name = dg->label_name.c_str();
        Label *label = fn->getLabel(label_name);
        if (!label) {
            Error *e = new Error(LabelNotInScope, node, label_name);
            ctx->er->addError(e);
            continue;
        }

        llvm::BasicBlock *block        = label->block;
        llvm::BasicBlock *block_marker = dg->block_marker;
        llvm::Instruction *marker      = dg->marker;

        llvm::IRBuilder<> builder(block_marker);

        if (!marker && (block_marker->size() != 0)) {
            marker = block_marker->getFirstNonPHI();
        }
        if (marker) {
            llvm::BasicBlock::iterator bi = marker;
            ++bi;
            if (bi != block_marker->end()) {
                builder.SetInsertPoint(bi);
            }
        }

        /* Create a vector of variables to destruct.  This will
         * comprise all variables in the goto's namespace and upwards,
         * until either null (top of function) or the label's
         * namespace is reached. */

        std::vector<Variable *> variables;

        Namespace *goto_ns = dg->ns;
        Namespace *current_ns = goto_ns;

        while (current_ns != label->ns) {
            current_ns->getVariables(&variables);
            current_ns = current_ns->parent_namespace;
            if (!current_ns) {
                break;
            }
        }

        if (current_ns != label->ns) {
            if (gotoCrossesDeclaration(dg, label)) {
                Error *e = new Error(GotoWillCrossDeclaration, dg->node);
                ctx->er->addError(e);
                return false;
            }
        }

        /* Add the destructors for the collected variables. */
        ParseResult var_pr;
        for (std::vector<Variable *>::iterator vb = variables.begin(),
                                               ve = variables.end();
                vb != ve;
                ++vb) {
            Variable *var = (*vb);
            ParseResult destruct_pr;
            var_pr.set(NULL, var->type, var->value);
            var_pr.do_not_destruct = false;
            bool res = Operation::Destruct(ctx, &var_pr, &destruct_pr,
                                           &builder);
            if (!res) {
                return false;
            }
        }

        builder.CreateBr(block);
    }

    STL::deleteElements(&(fn->deferred_gotos));
    fn->deferred_gotos.clear();
    fn->labels.clear();

    return true;
}

bool
terminateBlocks(Context *ctx, Function *fn, llvm::Function *llvm_fn,
                llvm::Value *last_value, Type *last_type,
                Node *last_position)
{
    /* Iterate over the blocks in the function. If the block ends in a
     * terminator, all is well.  If it doesn't: if the block is the
     * last block in the function, create a return instruction
     * containing the last value evaluated, otherwise create a branch
     * instruction that moves to the next block.
     */

    for (llvm::Function::iterator b = llvm_fn->begin(),
                                  e = llvm_fn->end();
            b != e;
            ++b) {
        if (b->size() && b->back().isTerminator()) {
            continue;
        }
        llvm::IRBuilder<> builder(b);
        ++b;
        if (b != e) {
            builder.CreateBr(b);
            --b;
            continue;
        }
        --b;

        Operation::CloseScope(ctx, fn, b, NULL, true);

        /* The underlying error here will have been reported earlier,
         * if there is no last_value. */
        if (fn->return_type->base_type == BaseType::Void) {
            builder.CreateRetVoid();
        } else if (!fn->hasRetval() && last_value) {
            Type *got_type = last_type;
            if (!fn->return_type->canBePassedFrom(got_type)) {
                std::string wanted;
                fn->return_type->toString(&wanted);
                std::string got;
                got_type->toString(&got);
                Error *e = new Error(IncorrectReturnType,
                                     last_position,
                                     wanted.c_str(), got.c_str());
                ctx->er->addError(e);
                return false;
            }
            builder.CreateRet(last_value);
        } else {
            builder.CreateRetVoid();
        }
    }

    return true;
}

void
removePostTerminators(llvm::Function *llvm_fn)
{
    /* Iterate over the blocks in the function. Delete all
     * instructions that occur after the first terminating
     * instruction. */

    for (llvm::iplist<llvm::BasicBlock>::reverse_iterator
            b = llvm_fn->getBasicBlockList().rbegin(),
            e = llvm_fn->getBasicBlockList().rend();
            b != e;
            ++b) {
        for (llvm::BasicBlock::iterator ib = b->begin(),
                                        ie = b->end();
                ib != ie;
                ++ib) {
            if (!(*ib).isTerminator()) {
                continue;
            }
            ++ib;
            if (ib == ie) {
                break;
            }
            /* Subtraction is not publicly available on the LLVM
             * iterator classes. */
            int count = 0;
            while (ib != ie) {
                ++count;
                ++ib;
            }
            while (count--) {
                b->getInstList().pop_back();
            }
            break;
        }
    }
}

bool
FormProcBodyParse(Units *units, Node *node, Function *fn,
                  llvm::Function *llvm_fn, int skip, bool is_anonymous,
                  llvm::Value *return_value)
{
    Context *ctx = units->top()->ctx;

    std::vector<Node *> *lst = node->list;

    llvm::BasicBlock *block =
        llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", llvm_fn);

    units->top()->pushGlobalBlock(block);

    llvm::BasicBlock *next = block;
    llvm::IRBuilder<> builder(block);

    addVariables(ctx, node, fn, block);

    if (fn->hasRetval()) {
        addRetval(ctx, node, fn, block, return_value);
    }

    llvm::Value *last_value = NULL;
    Type *last_type = NULL;
    Node *last_position = NULL;

    for (std::vector<Node *>::iterator b = (lst->begin() + skip),
                                       e = lst->end();
            b != e;
            ++b) {
        Type *wanted_type = NULL;
        bool is_last = ((b + 1) == e);
        if (is_last) {
            wanted_type = fn->return_type;
        }
        ParseResult res_pr;
        bool res = FormProcInstParse(units, fn, next, (*b), false, false,
                                     wanted_type, &res_pr);
        if (res) {
            next = res_pr.block;
            if (is_last) {
		bool res = Operation::Copy(units->top()->ctx, fn, (*b),
					   &res_pr, &res_pr);
                if (!res) {
                    return false;
                }
                last_value = res_pr.getValue(ctx);
                last_type = res_pr.type;
                last_position = (*b);
            } else {
                ParseResult destruct_pr;
                bool res = Operation::Destruct(ctx, &res_pr, &destruct_pr);
                if (!res) {
                    return false;
                }
                next = destruct_pr.block;
            }
        }
    }

    bool res = resolveDeferredGotos(ctx, node, fn, block);
    if (!res) {
        return false;
    }

    res = terminateBlocks(ctx, fn, llvm_fn, last_value, last_type,
                          last_position);
    if (!res) {
        return false;
    }

    removePostTerminators(llvm_fn);
    units->top()->popGlobalBlock();

    return true;
}
}
<commit_msg>[master] deferred goto problem (#180)<commit_after>#include "ProcBody.h"
#include "../../Units/Units.h"
#include "../../Node/Node.h"
#include "../../ParseResult/ParseResult.h"
#include "../../Function/Function.h"
#include "../../CoreForms/CoreForms.h"
#include "../../Operation/Copy/Copy.h"
#include "../../Operation/Destruct/Destruct.h"
#include "../../Operation/CloseScope/CloseScope.h"
#include "../Linkage/Linkage.h"
#include "../Type/Type.h"
#include "../Proc/Inst/Inst.h"
#include "../../llvm_Function.h"

using namespace dale::ErrorInst;

namespace dale
{
bool
addVariables(Context *ctx, Node *node, Function *fn, llvm::BasicBlock *block)
{
    llvm::IRBuilder<> builder(block);

    bool past_first = false;
    for (std::vector<Variable *>::iterator b = fn->parameters.begin(),
                                           e = fn->parameters.end();
            b != e;
            ++b) {
        Variable *var = (*b);
        bool is_macro_varargs = false;
        if (var->type->base_type == BaseType::VarArgs) {
            if (!var->name.compare("rest")) {
                is_macro_varargs = true;
            } else {
                break;
            }
        }
        Variable *param_var = new Variable();
        var->copyTo(param_var);
        /* todo: It would be better if TypeRegister supported a
         * 'getReferencedType' function, to avoid the copying below.
         * */
        if (var->type->is_reference) {
            var->type->is_reference = false;
            param_var->type =
                ctx->tr->getPointerType(var->type->makeCopy());
            var->type->is_reference = true;
        } else if (var->type->is_rvalue_reference) {
            var->type->is_rvalue_reference = false;
            param_var->type =
                ctx->tr->getPointerType(var->type->makeCopy());
            var->type->is_rvalue_reference = true;
        } else {
            param_var->type = var->type;
        }
        param_var->linkage = Linkage::Auto;

        if (past_first && fn->is_macro) {
            /* Macro arguments, past the first, always have a type of
             * (p DNode), notwithstanding that the type in the
             * Function is unrestricted (to support overloading).
             * (Except for the 'rest' parameter.) */
            param_var->type = ctx->tr->type_pdnode;
            if (is_macro_varargs) {
                param_var->type =
                    ctx->tr->getPointerType(ctx->tr->type_pdnode);
            }
        }
        bool res = ctx->ns()->addVariable(param_var->name.c_str(), param_var);
        if (!res) {
            Error *e = new Error(RedefinitionOfVariable, node,
                                 param_var->name.c_str());
            ctx->er->addError(e);
            return false;
        }

        llvm::Type *llvm_type = ctx->toLLVMType(param_var->type, NULL, false);
        if (!llvm_type) {
            return false;
        }
        llvm::Value *param_var_ptr =
            llvm::cast<llvm::Value>(builder.CreateAlloca(llvm_type));
        llvm::Value *original_value = param_var->value;
        param_var->value = param_var_ptr;
        builder.CreateStore(original_value, param_var_ptr);
        past_first = true;
    }

    return true;
}

bool
addRetval(Context *ctx, Node *node, Function *fn,
          llvm::BasicBlock *block, llvm::Value *return_value)
{
    Variable *var = new Variable();

    var->type            = ctx->tr->getPointerType(fn->return_type);
    var->name            = "retval";
    var->symbol          = "retval";
    var->has_initialiser = false;
    var->once_tag        = "";
    var->index           = 0;
    var->linkage         = Linkage::Auto;

    bool res = ctx->ns()->addVariable(var->name.c_str(), var);
    if (!res) {
        Error *e = new Error(RedefinitionOfVariable, node,
                             var->name.c_str());
        ctx->er->addError(e);
        return false;
    }

    llvm::Type *llvm_type = ctx->toLLVMType(var->type, NULL,
                                            false);
    if (!llvm_type) {
        return false;
    }

    llvm::IRBuilder<> builder(block);
    llvm::Value *new_ptr =
        llvm::cast<llvm::Value>(builder.CreateAlloca(llvm_type));
    var->value = new_ptr;
    builder.CreateStore(return_value, new_ptr);

    return true;
}

bool
gotoCrossesDeclaration(DeferredGoto *dg, Label *label)
{
    /* If the label's namespace, or any namespace in which the label's
     * namespace is located, has a variable declaration with an index
     * smaller than that of the label, then the goto is going to cross
     * that variable declaration.  This is an error, because the
     * declaration may result in a destructor being called on scope
     * close, and the variable may not be initialised when the goto is
     * reached. */

    std::vector<Variable *> vars_before;
    Namespace *label_ns = label->ns;

    while (label_ns) {
        label_ns->getVarsBeforeIndex(label->index, &vars_before);
        if (vars_before.size() > 0) {
            for (std::vector<Variable*>::iterator b = vars_before.begin(),
                                                  e = vars_before.end();
                    b != e;
                    ++b) {
                if ((*b)->index >= dg->index) {
                    return true;
                }
            }
            vars_before.clear();
        }
        label_ns = label_ns->parent_namespace;
    }

    return false;
}

bool
resolveDeferredGotos(Context *ctx, Node *node, Function *fn,
                     llvm::BasicBlock *block)
{
    for (std::vector<DeferredGoto *>::iterator b = fn->deferred_gotos.begin(),
                                               e = fn->deferred_gotos.end();
            b != e;
            ++b) {
        DeferredGoto *dg = (*b);
        const char *label_name = dg->label_name.c_str();
        Label *label = fn->getLabel(label_name);
        if (!label) {
            Error *e = new Error(LabelNotInScope, node, label_name);
            ctx->er->addError(e);
            continue;
        }

        llvm::BasicBlock *block        = label->block;
        llvm::BasicBlock *block_marker = dg->block_marker;
        llvm::Instruction *marker      = dg->marker;

        llvm::IRBuilder<> builder(block_marker);

        if (!marker && (block_marker->size() != 0)) {
            marker = block_marker->getFirstNonPHI();
        }
        if (marker) {
            llvm::BasicBlock::iterator bi = marker;
            ++bi;
            if (bi != block_marker->end()) {
                builder.SetInsertPoint(bi);
            }
        }

        /* Create a vector of variables to destruct.  This will
         * comprise all variables in the goto's namespace and upwards,
         * until either the namespace before the root or the label's
         * namespace is reached. */

        std::vector<Variable *> variables;

        Namespace *goto_ns = dg->ns;
        Namespace *current_ns = goto_ns;

        while (current_ns != label->ns) {
            Namespace *parent = current_ns->parent_namespace;
            if (parent && !parent->parent_namespace) {
                break;
            }
            current_ns->getVariables(&variables);
            current_ns = parent;
        }

        if (current_ns != label->ns) {
            if (gotoCrossesDeclaration(dg, label)) {
                Error *e = new Error(GotoWillCrossDeclaration, dg->node);
                ctx->er->addError(e);
                return false;
            }
        }

        /* Add the destructors for the collected variables. */
        ParseResult var_pr;
        for (std::vector<Variable *>::iterator vb = variables.begin(),
                                               ve = variables.end();
                vb != ve;
                ++vb) {
            Variable *var = (*vb);
            ParseResult destruct_pr;
            var_pr.set(NULL, var->type, var->value);
            var_pr.do_not_destruct = false;
            bool res = Operation::Destruct(ctx, &var_pr, &destruct_pr,
                                           &builder);
            if (!res) {
                return false;
            }
        }

        builder.CreateBr(block);
    }

    STL::deleteElements(&(fn->deferred_gotos));
    fn->deferred_gotos.clear();
    fn->labels.clear();

    return true;
}

bool
terminateBlocks(Context *ctx, Function *fn, llvm::Function *llvm_fn,
                llvm::Value *last_value, Type *last_type,
                Node *last_position)
{
    /* Iterate over the blocks in the function. If the block ends in a
     * terminator, all is well.  If it doesn't: if the block is the
     * last block in the function, create a return instruction
     * containing the last value evaluated, otherwise create a branch
     * instruction that moves to the next block.
     */

    for (llvm::Function::iterator b = llvm_fn->begin(),
                                  e = llvm_fn->end();
            b != e;
            ++b) {
        if (b->size() && b->back().isTerminator()) {
            continue;
        }
        llvm::IRBuilder<> builder(b);
        ++b;
        if (b != e) {
            builder.CreateBr(b);
            --b;
            continue;
        }
        --b;

        Operation::CloseScope(ctx, fn, b, NULL, true);

        /* The underlying error here will have been reported earlier,
         * if there is no last_value. */
        if (fn->return_type->base_type == BaseType::Void) {
            builder.CreateRetVoid();
        } else if (!fn->hasRetval() && last_value) {
            Type *got_type = last_type;
            if (!fn->return_type->canBePassedFrom(got_type)) {
                std::string wanted;
                fn->return_type->toString(&wanted);
                std::string got;
                got_type->toString(&got);
                Error *e = new Error(IncorrectReturnType,
                                     last_position,
                                     wanted.c_str(), got.c_str());
                ctx->er->addError(e);
                return false;
            }
            builder.CreateRet(last_value);
        } else {
            builder.CreateRetVoid();
        }
    }

    return true;
}

void
removePostTerminators(llvm::Function *llvm_fn)
{
    /* Iterate over the blocks in the function. Delete all
     * instructions that occur after the first terminating
     * instruction. */

    for (llvm::iplist<llvm::BasicBlock>::reverse_iterator
            b = llvm_fn->getBasicBlockList().rbegin(),
            e = llvm_fn->getBasicBlockList().rend();
            b != e;
            ++b) {
        for (llvm::BasicBlock::iterator ib = b->begin(),
                                        ie = b->end();
                ib != ie;
                ++ib) {
            if (!(*ib).isTerminator()) {
                continue;
            }
            ++ib;
            if (ib == ie) {
                break;
            }
            /* Subtraction is not publicly available on the LLVM
             * iterator classes. */
            int count = 0;
            while (ib != ie) {
                ++count;
                ++ib;
            }
            while (count--) {
                b->getInstList().pop_back();
            }
            break;
        }
    }
}

bool
FormProcBodyParse(Units *units, Node *node, Function *fn,
                  llvm::Function *llvm_fn, int skip, bool is_anonymous,
                  llvm::Value *return_value)
{
    Context *ctx = units->top()->ctx;

    std::vector<Node *> *lst = node->list;

    llvm::BasicBlock *block =
        llvm::BasicBlock::Create(llvm::getGlobalContext(), "entry", llvm_fn);

    units->top()->pushGlobalBlock(block);

    llvm::BasicBlock *next = block;
    llvm::IRBuilder<> builder(block);

    addVariables(ctx, node, fn, block);

    if (fn->hasRetval()) {
        addRetval(ctx, node, fn, block, return_value);
    }

    llvm::Value *last_value = NULL;
    Type *last_type = NULL;
    Node *last_position = NULL;

    for (std::vector<Node *>::iterator b = (lst->begin() + skip),
                                       e = lst->end();
            b != e;
            ++b) {
        Type *wanted_type = NULL;
        bool is_last = ((b + 1) == e);
        if (is_last) {
            wanted_type = fn->return_type;
        }
        ParseResult res_pr;
        bool res = FormProcInstParse(units, fn, next, (*b), false, false,
                                     wanted_type, &res_pr);
        if (res) {
            next = res_pr.block;
            if (is_last) {
		bool res = Operation::Copy(units->top()->ctx, fn, (*b),
					   &res_pr, &res_pr);
                if (!res) {
                    return false;
                }
                last_value = res_pr.getValue(ctx);
                last_type = res_pr.type;
                last_position = (*b);
            } else {
                ParseResult destruct_pr;
                bool res = Operation::Destruct(ctx, &res_pr, &destruct_pr);
                if (!res) {
                    return false;
                }
                next = destruct_pr.block;
            }
        }
    }

    bool res = resolveDeferredGotos(ctx, node, fn, block);
    if (!res) {
        return false;
    }

    res = terminateBlocks(ctx, fn, llvm_fn, last_value, last_type,
                          last_position);
    if (!res) {
        return false;
    }

    removePostTerminators(llvm_fn);
    units->top()->popGlobalBlock();

    return true;
}
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestLabelPlacerCoincidentPoints.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

// .NAME Test of vtkLabelPlacer
// .SECTION Description
// this program tests vtkLabelPlacer which uses a sophisticated algorithm to
// prune labels/icons preventing them from overlapping.

#include "vtkActor.h"
#include "vtkActor2D.h"
#include "vtkCellArray.h"
#include "vtkLabeledDataMapper.h"
#include "vtkLabelHierarchy.h"
#include "vtkLabelPlacer.h"
#include "vtkLabelSizeCalculator.h"
#include "vtkPointSetToLabelHierarchy.h"
#include "vtkPoints.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkPolyDataMapper2D.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkTextProperty.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkXMLPolyDataWriter.h"
#include "vtkPolyData.h"
#include "vtkImageData.h"
#include "vtkSmartPointer.h"
#include "vtkStructuredGrid.h"
#include "vtkUnstructuredGrid.h"
#include "vtkRectilinearGrid.h"

#include <vtkTestUtilities.h>
#include <vtkRegressionTestImage.h>

int TestLabelPlacerCoincidentPoints(int argc, char *argv[])
{
  int maxLevels = 5;
  int targetLabels = 32;
  double labelRatio = 0.05;
  //char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/uniform-001371-5x5x5.vtp");
  int iteratorType = vtkLabelHierarchy::FULL_SORT;
  bool showBounds = false;

  cout << "TestLabelPlacer" << endl;

  vtkSmartPointer<vtkLabelSizeCalculator> labelSizeCalculator =
    vtkSmartPointer<vtkLabelSizeCalculator>::New();
  vtkSmartPointer<vtkLabelHierarchy> labelHierarchy =
    vtkSmartPointer<vtkLabelHierarchy>::New();
  vtkSmartPointer<vtkLabelPlacer> labelPlacer =
    vtkSmartPointer<vtkLabelPlacer>::New();
  vtkSmartPointer<vtkPointSetToLabelHierarchy> pointSetToLabelHierarchy =
    vtkSmartPointer<vtkPointSetToLabelHierarchy>::New();
  vtkSmartPointer<vtkXMLPolyDataReader> xmlPolyDataReader =
    vtkSmartPointer<vtkXMLPolyDataReader>::New();

  vtkSmartPointer<vtkPolyDataMapper> polyDataMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  vtkSmartPointer<vtkActor> actor =
    vtkSmartPointer<vtkActor>::New();
  vtkSmartPointer<vtkRenderer> renderer =
    vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renWin =
    vtkSmartPointer<vtkRenderWindow>::New();
  vtkSmartPointer<vtkRenderWindowInteractor> iren =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();

  vtkSmartPointer<vtkLabeledDataMapper> labeledMapper =
    vtkSmartPointer<vtkLabeledDataMapper>::New();
  vtkSmartPointer<vtkActor2D> textActor = vtkSmartPointer<vtkActor2D>::New();

  cout << "Done Instantiating" << endl;

  //xmlPolyDataReader->SetFileName( fname );
  //delete [] fname;

  vtkSmartPointer<vtkPoints> points = vtkPoints::New();

  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);

  vtkSmartPointer<vtkCellArray> cells = vtkCellArray::New();

  cells->InsertNextCell(10);
  for(int i = 0; i < 10; i++)
    {
    cells->InsertCellPoint(i);
    }

  vtkSmartPointer<vtkPolyData> polyData = vtkPolyData::New();
  polyData->SetPoints(points);
  polyData->SetVerts(cells);

  labelSizeCalculator->SetInput(polyData);
  labelSizeCalculator->GetFontProperty()->SetFontSize( 12 );
  labelSizeCalculator->GetFontProperty()->SetFontFamily( vtkTextProperty::GetFontFamilyFromString( "Arial" ) );
  labelSizeCalculator->SetInputArrayToProcess( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "PlaceNames" );
  labelSizeCalculator->SetLabelSizeArrayName( "LabelSize" );

  pointSetToLabelHierarchy->AddInputConnection(labelSizeCalculator->GetOutputPort());
  pointSetToLabelHierarchy->SetInputArrayToProcess( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Priority" );
  pointSetToLabelHierarchy->SetInputArrayToProcess( 1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "LabelSize" );
  pointSetToLabelHierarchy->SetInputArrayToProcess( 2, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "PlaceNames" );
  pointSetToLabelHierarchy->SetMaximumDepth( maxLevels );
  pointSetToLabelHierarchy->SetTargetLabelCount( targetLabels );

  labelPlacer->SetInputConnection( pointSetToLabelHierarchy->GetOutputPort() );
  labelPlacer->SetIteratorType( iteratorType );
  labelPlacer->SetOutputTraversedBounds( showBounds );
  labelPlacer->SetRenderer( renderer );
  labelPlacer->SetMaximumLabelFraction( labelRatio );

  cout << "Done Setting up LabelPlacer" << endl;

  polyDataMapper->SetInputConnection(labelPlacer->GetOutputPort());

  actor->SetMapper(polyDataMapper);

  labelPlacer->Update();

  cout << "Done Updating Label Placer" << endl;

  labeledMapper->SetInputConnection(labelPlacer->GetOutputPort());
  labeledMapper->SetLabelTextProperty(labelSizeCalculator->GetFontProperty());
  labeledMapper->SetFieldDataName("LabelText");
  labeledMapper->SetLabelModeToLabelFieldData();
  labeledMapper->GetLabelTextProperty()->SetColor(0.0, 0.8, 0.2);
  textActor->SetMapper(labeledMapper);

  renderer->AddActor(actor);
  renderer->AddActor(textActor);

  renWin->SetSize(300, 300);
  renWin->AddRenderer(renderer);
  renderer->SetBackground(0.0, 0.0, 0.0);
    iren->SetRenderWindow(renWin);

  cout << "Calling Render" << endl;

  renWin->Render();
  renderer->ResetCamera();
  renderer->ResetCamera();
  renderer->ResetCamera();

  int retVal = vtkRegressionTestImage( renWin );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  return !retVal;
}
<commit_msg>ENH: Further implementation of coincident points test.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    TestLabelPlacerCoincidentPoints.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

// .NAME Test of vtkLabelPlacer
// .SECTION Description
// this program tests vtkLabelPlacer which uses a sophisticated algorithm to
// prune labels/icons preventing them from overlapping.

#include "vtkActor.h"
#include "vtkActor2D.h"
#include "vtkCellArray.h"
#include "vtkFloatArray.h"
#include "vtkLabeledDataMapper.h"
#include "vtkLabelHierarchy.h"
#include "vtkLabelPlacer.h"
#include "vtkLabelSizeCalculator.h"
#include "vtkMath.h"
#include "vtkPointSetToLabelHierarchy.h"
#include "vtkPointData.h"
#include "vtkPoints.h"
#include "vtkPointSet.h"
#include "vtkPolyData.h"
#include "vtkPolyDataMapper.h"
#include "vtkPolyDataMapper2D.h"
#include "vtkProperty.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkStringArray.h"
#include "vtkTextProperty.h"
#include "vtkXMLPolyDataReader.h"
#include "vtkXMLPolyDataWriter.h"
#include "vtkPolyData.h"
#include "vtkImageData.h"
#include "vtkSmartPointer.h"
#include "vtkStructuredGrid.h"
#include "vtkUnstructuredGrid.h"
#include "vtkRectilinearGrid.h"

#include <vtkTestUtilities.h>
#include <vtkRegressionTestImage.h>

int TestLabelPlacerCoincidentPoints(int argc, char *argv[])
{
  int maxLevels = 5;
  int targetLabels = 32;
  double labelRatio = 0.05;
  int i = 0;
  //char* fname = vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/uniform-001371-5x5x5.vtp");
  int iteratorType = vtkLabelHierarchy::FULL_SORT;
  bool showBounds = false;

  vtkSmartPointer<vtkLabelSizeCalculator> labelSizeCalculator =
    vtkSmartPointer<vtkLabelSizeCalculator>::New();
  vtkSmartPointer<vtkLabelHierarchy> labelHierarchy =
    vtkSmartPointer<vtkLabelHierarchy>::New();
  vtkSmartPointer<vtkLabelPlacer> labelPlacer =
    vtkSmartPointer<vtkLabelPlacer>::New();
  vtkSmartPointer<vtkPointSetToLabelHierarchy> pointSetToLabelHierarchy =
    vtkSmartPointer<vtkPointSetToLabelHierarchy>::New();
  vtkSmartPointer<vtkXMLPolyDataReader> xmlPolyDataReader =
    vtkSmartPointer<vtkXMLPolyDataReader>::New();

  vtkSmartPointer<vtkPolyDataMapper> polyDataMapper =
    vtkSmartPointer<vtkPolyDataMapper>::New();
  vtkSmartPointer<vtkActor> actor =
    vtkSmartPointer<vtkActor>::New();
  vtkSmartPointer<vtkRenderer> renderer =
    vtkSmartPointer<vtkRenderer>::New();
  vtkSmartPointer<vtkRenderWindow> renWin =
    vtkSmartPointer<vtkRenderWindow>::New();
  vtkSmartPointer<vtkRenderWindowInteractor> iren =
    vtkSmartPointer<vtkRenderWindowInteractor>::New();

  vtkSmartPointer<vtkLabeledDataMapper> labeledMapper =
    vtkSmartPointer<vtkLabeledDataMapper>::New();
  vtkSmartPointer<vtkActor2D> textActor = vtkSmartPointer<vtkActor2D>::New();

  vtkSmartPointer<vtkPoints> points = vtkPoints::New();

  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);
  points->InsertNextPoint(5.0, 5.0, 5.0);

  vtkSmartPointer<vtkCellArray> cells = vtkCellArray::New();

  cells->InsertNextCell(10);
  for(i = 0; i < 10; i++)
    {
    cells->InsertCellPoint(i);
    }

  vtkSmartPointer<vtkPolyData> polyData = vtkPolyData::New();
  polyData->SetPoints(points);
  polyData->SetVerts(cells);

  vtkSmartPointer<vtkStringArray> stringData = vtkStringArray::New();
  stringData->SetNumberOfComponents(1);
  stringData->SetNumberOfTuples(10);
  stringData->SetName("PlaceNames");
  stringData->InsertNextValue("Amsterdam");
  stringData->InsertNextValue("Berlin");
  stringData->InsertNextValue("Cairo");
  stringData->InsertNextValue("New Dehli");
  stringData->InsertNextValue("Hanoi");
  stringData->InsertNextValue("Jakarta");
  stringData->InsertNextValue("London");
  stringData->InsertNextValue("Ottawa");
  stringData->InsertNextValue("Tokyo");
  stringData->InsertNextValue("Washington");

  polyData->GetPointData()->AddArray(stringData);

  vtkMath::RandomSeed(1234);
  vtkSmartPointer<vtkFloatArray> priority = vtkFloatArray::New();
  priority->SetNumberOfComponents(1);
  priority->SetNumberOfTuples(10);
  priority->SetName("Priority");

  for(i = 0; i < 10; i++)
    {
    priority->InsertNextValue(vtkMath::Random(0.0, 10.0));
    }

  polyData->GetPointData()->AddArray(priority);

  vtkSmartPointer<vtkFloatArray> labelSize = vtkFloatArray::New();
  labelSize->SetNumberOfComponents(3);
  labelSize->SetNumberOfTuples(10);
  labelSize->SetName("LabelSize");

  for(i = 0; i < 10; i++)
    {
    labelSize->InsertNextTuple3( vtkMath::Random(8.0, 10.0),
                                 vtkMath::Random(12.0, 16.0),
                                 0.0 );
    }

  polyData->GetPointData()->AddArray(labelSize);

  labelSizeCalculator->SetInput(polyData);
  labelSizeCalculator->GetFontProperty()->SetFontSize( 12 );
  labelSizeCalculator->GetFontProperty()->SetFontFamily( vtkTextProperty::GetFontFamilyFromString( "Arial" ) );
  labelSizeCalculator->SetInputArrayToProcess( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "PlaceNames" );
  labelSizeCalculator->SetLabelSizeArrayName( "LabelSize" );

  pointSetToLabelHierarchy->AddInputConnection(labelSizeCalculator->GetOutputPort());
  pointSetToLabelHierarchy->SetInputArrayToProcess( 0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "Priority" );
  pointSetToLabelHierarchy->SetInputArrayToProcess( 1, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "LabelSize" );
  pointSetToLabelHierarchy->SetInputArrayToProcess( 2, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, "PlaceNames" );
  pointSetToLabelHierarchy->SetMaximumDepth( maxLevels );
  pointSetToLabelHierarchy->SetTargetLabelCount( targetLabels );

  labelPlacer->SetInputConnection( pointSetToLabelHierarchy->GetOutputPort() );
  labelPlacer->SetIteratorType( iteratorType );
  labelPlacer->SetOutputTraversedBounds( showBounds );
  labelPlacer->SetRenderer( renderer );
  labelPlacer->SetMaximumLabelFraction( labelRatio );

  polyDataMapper->SetInputConnection(labelPlacer->GetOutputPort());

  actor->SetMapper(polyDataMapper);

  labelPlacer->Update();

  labeledMapper->SetInputConnection(labelPlacer->GetOutputPort());
  labeledMapper->SetLabelTextProperty(labelSizeCalculator->GetFontProperty());
  labeledMapper->SetFieldDataName("LabelText");
  labeledMapper->SetLabelModeToLabelFieldData();
  labeledMapper->GetLabelTextProperty()->SetColor(0.0, 0.8, 0.2);
  textActor->SetMapper(labeledMapper);

  renderer->AddActor(actor);
  renderer->AddActor(textActor);

  renWin->SetSize(300, 300);
  renWin->AddRenderer(renderer);
  renderer->SetBackground(0.0, 0.0, 0.0);
    iren->SetRenderWindow(renWin);

  renWin->Render();
  renderer->ResetCamera();
  renderer->ResetCamera();
  renderer->ResetCamera();

  int retVal = vtkRegressionTestImage( renWin );
  if ( retVal == vtkRegressionTester::DO_INTERACTOR)
    {
    iren->Start();
    }

  return !retVal;
}
<|endoftext|>


<commit_before>#define DEBUG 1
/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 6/7/2020, 1:57:06 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- main() -----

int main()
{
  int N;
  cin >> N;
  vector<int> L(N);
  for (auto i{0}; i < N; ++i)
  {
    cin >> L[i];
  }
  sort(L.begin(), L.end());
  ll ans{0};
  for (auto i{0}; i < N; ++i)
  {
    int k{N - 2};
    for (auto j{N - 1}; j >= 0; --j)
    {
      while (L[j] < L[i] + L[k] && k > i)
      {
        --k;
      }
      ans += j - k - 1;
    }
  }
  cout << ans << endl;
}
<commit_msg>submit D2.cpp to 'D - Triangles' (abc143) [C++14 (GCC 5.4.1)]<commit_after>#define DEBUG 1
/**
 * File    : D2.cpp
 * Author  : Kazune Takahashi
 * Created : 6/7/2020, 1:57:06 AM
 * Powered by Visual Studio Code
 */
#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <chrono>
#include <cmath>
#include <complex>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <stack>
#include <string>
#include <tuple>
#include <unordered_map>
#include <unordered_set>
#include <vector>
// ----- boost -----
#include <boost/rational.hpp>
#include <boost/multiprecision/cpp_int.hpp>
// ----- using directives and manipulations -----
using namespace std;
using boost::rational;
using boost::multiprecision::cpp_int;
using ll = long long;
using ld = long double;
template <typename T>
using max_heap = priority_queue<T>;
template <typename T>
using min_heap = priority_queue<T, vector<T>, greater<T>>;
// ----- constexpr for Mint and Combination -----
constexpr ll MOD{1'000'000'007LL};
// constexpr ll MOD{998'244'353LL}; // be careful
constexpr ll MAX_SIZE{3'000'010LL};
// constexpr ll MAX_SIZE{30'000'010LL}; // if 10^7 is needed
// ----- ch_max and ch_min -----
template <typename T>
void ch_max(T &left, T right)
{
  if (left < right)
  {
    left = right;
  }
}
template <typename T>
void ch_min(T &left, T right)
{
  if (left > right)
  {
    left = right;
  }
}
// ----- Mint -----
template <ll MOD = MOD>
class Mint
{
public:
  ll x;
  Mint() : x{0LL} {}
  Mint(ll x) : x{(x % MOD + MOD) % MOD} {}
  Mint operator-() const { return x ? MOD - x : 0; }
  Mint &operator+=(Mint const &a)
  {
    if ((x += a.x) >= MOD)
    {
      x -= MOD;
    }
    return *this;
  }
  Mint &operator-=(Mint const &a) { return *this += -a; }
  Mint &operator++() { return *this += 1; }
  Mint operator++(int)
  {
    Mint tmp{*this};
    ++*this;
    return tmp;
  }
  Mint &operator--() { return *this -= 1; }
  Mint operator--(int)
  {
    Mint tmp{*this};
    --*this;
    return tmp;
  }
  Mint &operator*=(Mint const &a)
  {
    (x *= a.x) %= MOD;
    return *this;
  }
  Mint &operator/=(Mint const &a)
  {
    Mint b{a};
    return *this *= b.power(MOD - 2);
  }
  Mint operator+(Mint const &a) const { return Mint(*this) += a; }
  Mint operator-(Mint const &a) const { return Mint(*this) -= a; }
  Mint operator*(Mint const &a) const { return Mint(*this) *= a; }
  Mint operator/(Mint const &a) const { return Mint(*this) /= a; }
  bool operator<(Mint const &a) const { return x < a.x; }
  bool operator<=(Mint const &a) const { return x <= a.x; }
  bool operator>(Mint const &a) const { return x > a.x; }
  bool operator>=(Mint const &a) const { return x >= a.x; }
  bool operator==(Mint const &a) const { return x == a.x; }
  bool operator!=(Mint const &a) const { return !(*this == a); }
  Mint power(ll N) const
  {
    if (N == 0)
    {
      return 1;
    }
    else if (N % 2 == 1)
    {
      return *this * power(N - 1);
    }
    else
    {
      Mint half = power(N / 2);
      return half * half;
    }
  }
};
template <ll MOD>
Mint<MOD> operator+(ll lhs, Mint<MOD> const &rhs)
{
  return rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator-(ll lhs, Mint<MOD> const &rhs)
{
  return -rhs + lhs;
}
template <ll MOD>
Mint<MOD> operator*(ll lhs, Mint<MOD> const &rhs)
{
  return rhs * lhs;
}
template <ll MOD>
Mint<MOD> operator/(ll lhs, Mint<MOD> const &rhs)
{
  return Mint<MOD>{lhs} / rhs;
}
template <ll MOD>
istream &operator>>(istream &stream, Mint<MOD> &a)
{
  return stream >> a.x;
}
template <ll MOD>
ostream &operator<<(ostream &stream, Mint<MOD> const &a)
{
  return stream << a.x;
}
// ----- Combination -----
template <ll MOD = MOD, ll MAX_SIZE = MAX_SIZE>
class Combination
{
public:
  vector<Mint<MOD>> inv, fact, factinv;
  Combination() : inv(MAX_SIZE), fact(MAX_SIZE), factinv(MAX_SIZE)
  {
    inv[1] = 1;
    for (auto i{2LL}; i < MAX_SIZE; i++)
    {
      inv[i] = (-inv[MOD % i]) * (MOD / i);
    }
    fact[0] = factinv[0] = 1;
    for (auto i{1LL}; i < MAX_SIZE; i++)
    {
      fact[i] = Mint<MOD>(i) * fact[i - 1];
      factinv[i] = inv[i] * factinv[i - 1];
    }
  }
  Mint<MOD> operator()(int n, int k)
  {
    if (n >= 0 && k >= 0 && n - k >= 0)
    {
      return fact[n] * factinv[k] * factinv[n - k];
    }
    return 0;
  }
  Mint<MOD> catalan(int x, int y)
  {
    return (*this)(x + y, y) - (*this)(x + y, y - 1);
  }
};
// ----- for C++14 -----
using mint = Mint<MOD>;
using combination = Combination<MOD, MAX_SIZE>;
template <typename T>
T gcd(T x, T y) { return y ? gcd(y, x % y) : x; }
template <typename T>
T lcm(T x, T y) { return x / gcd(x, y) * y; }
// ----- for C++17 -----
template <typename T>
int popcount(T x) // C++20
{
  int ans{0};
  while (x != 0)
  {
    ans += x & 1;
    x >>= 1;
  }
  return ans;
}
// ----- frequently used constexpr -----
// constexpr double epsilon{1e-10};
// constexpr ll infty{1'000'000'000'000'010LL}; // or
// constexpr int infty{1'000'000'010};
// constexpr int dx[4] = {1, 0, -1, 0};
// constexpr int dy[4] = {0, 1, 0, -1};
// ----- Yes() and No() -----
void Yes()
{
  cout << "Yes" << endl;
  exit(0);
}
void No()
{
  cout << "No" << endl;
  exit(0);
}

// ----- main() -----

int main()
{
  int N;
  cin >> N;
  vector<int> L(N);
  for (auto i{0}; i < N; ++i)
  {
    cin >> L[i];
  }
  sort(L.begin(), L.end());
  ll ans{0};
  for (auto i{1}; i < N - 1; ++i)
  {
    int k{i + 1};
    for (auto j{0}; j < i; ++j)
    {
      while (k < N && L[k] < L[i] + L[j])
      {
        ++k;
      }
      ans += k - i - 1;
    }
  }
  cout << ans << endl;
}
<|endoftext|>


<commit_before>#include "FileReader.h"

#include <cstdio>
#include "unicode/ustdio.h"

#include "Log.h"
using namespace ascii;

namespace
{
    const int LINE_CHARACTER_LIMIT = 500;
}

ascii::FileReader::FileReader(string path)
{
    Initialize(path);
}

ascii::FileReader::FileReader(string path, string forbiddenCharactersPath)
{
    // Read the list of forbidden characters from the given forbidden
    // characters file, if there is one
    mForbiddenCharacters = ReadContents(forbiddenCharactersPath);
    mForbiddenCharacters.trim(); // Trim the trailing newline

    //Log::Print("Loading file ", false);
    //Log::Print(path, false);
    //Log::Print(" with forbidden characters: ", false);
    //Log::Print(mForbiddenCharacters);

    Initialize(path);
}

void FileReader::Initialize(string path)
{
    // Now read the UTF-8 file we're really concerned with
    UnicodeString contents = ReadContents(path);

    // If the file exists, parse each line from the file
    if (mExists)
    {
        ParseLines(contents, path);
    }
}

UnicodeString ascii::FileReader::ReadContents(string path)
{
    // Open the file
    //Log("Opening file: " + path);
    UFILE* ufile = u_fopen(path.c_str(), "r", NULL, "UTF-8");

    // Check if the file exists and was opened properly
    mExists = (ufile != NULL);

    // Output a warning if the file wasn't found
    if (!mExists)
    {
        Log::Print("Possible error: Tried to open nonexistent file: " + path);
        return UnicodeString("");
    }
    else
    {
        // Retrieve the size of the file
        long fileSize = 0;
        FILE* file = u_fgetfile(ufile);
        fseek(file, 0, SEEK_END);
        fileSize = ftell(file);
        u_frewind(ufile);

        // Prepare enough space to read the entire string plus termination
        UChar* contents = new UChar[fileSize + 1];

        // Read every character
        long index = 0;
        while (!u_feof(ufile))
        {
            UChar nextChar = u_fgetc(ufile);
            contents[index++] = nextChar;

            // Make sure none of the characters we read are forbidden
            if (mForbiddenCharacters.indexOf(nextChar) != -1)
            {
                Log::Error(UnicodeString("Forbidden character '") + UnicodeString(nextChar) + UnicodeString("' found in file: ") + UnicodeString::fromUTF8(path));
            }
        }

        // Add the string termination
        contents[index] = 0;

        // Create a UnicodeString object
        UnicodeString contentsUString(contents);
        // Clean up the memory used to read the UChars
        delete[] contents;
        // Close the file
        u_fclose(ufile);

        // Check if the UTF-8 Bit Order Mark is present
		UChar a, b, c;
		a = contentsUString[0];
		b = contentsUString[1];
		c = contentsUString[2];

        if(!(a!=(UChar)0xEF || b!=(UChar)0xBB || c!=(UChar)0xBF))
        {
            Log::Error("Warning. File contains UTF-8 bit order mark: " + path);

            // Strip the BOM
            contentsUString = contentsUString.tempSubString(3);
        }

        return contentsUString;
    }
}

void ascii::FileReader::ParseLines(UnicodeString contents, string path)
{
    int numChars = contents.length();
    if (numChars > 0)
    {
        // Split the file contents by line endings
        UnicodeString line = "";
        for (int i = 0; i < numChars; ++i)
        {
            UChar nextChar = contents[i];

            // Store the characters that are chained together as a line
            if (nextChar == '\n' || nextChar == 0)
            {
                line += nextChar;

                mLines.push_back(line);
                line = "";
            }
            else if (nextChar == '\r')
            {
                continue;
            }
            else
            {
                line += nextChar;
            }
        }
    }
}

bool ascii::FileReader::HasNextLine()
{
    return !mLines.empty();
}

string ascii::FileReader::NextLine(bool trimmed)
{
    UnicodeString nextLine = mLines.front();
    mLines.pop_front();

    string temp;
    string nextLineUTF8 = nextLine.toUTF8String(temp);

    if (trimmed)
    {
        if (nextLineUTF8.back() == '\n')
        {
            nextLineUTF8.pop_back();
        }
    }

    return nextLineUTF8;
}

UnicodeString ascii::FileReader::NextLineUnicode(bool trimmed)
{
    UnicodeString nextLine = mLines.front();
    mLines.pop_front();

    if (trimmed)
    {
        nextLine = nextLine.findAndReplace("\n", "");
    }

    return nextLine;
}

string ascii::FileReader::FullContents()
{
    // Collect the whole contents of the buffer in a new string stream
    stringstream buffer;

    while (HasNextLine())
    {
        buffer << NextLine(false);
    }

    // Return the contents as a string
    return buffer.str();
}
<commit_msg>FileReader gives position of forbidden characters when found<commit_after>#include "FileReader.h"

#include <cstdio>
#include "unicode/ustdio.h"

#include "Log.h"
using namespace ascii;

namespace
{
    const int LINE_CHARACTER_LIMIT = 500;
}

ascii::FileReader::FileReader(string path)
{
    Initialize(path);
}

ascii::FileReader::FileReader(string path, string forbiddenCharactersPath)
{
    // Read the list of forbidden characters from the given forbidden
    // characters file, if there is one
    mForbiddenCharacters = ReadContents(forbiddenCharactersPath);
    mForbiddenCharacters.trim(); // Trim the trailing newline

    //Log::Print("Loading file ", false);
    //Log::Print(path, false);
    //Log::Print(" with forbidden characters: ", false);
    //Log::Print(mForbiddenCharacters);

    Initialize(path);
}

void FileReader::Initialize(string path)
{
    // Now read the UTF-8 file we're really concerned with
    UnicodeString contents = ReadContents(path);

    // If the file exists, parse each line from the file
    if (mExists)
    {
        ParseLines(contents, path);
    }
}

UnicodeString ascii::FileReader::ReadContents(string path)
{
    // Open the file
    //Log("Opening file: " + path);
    UFILE* ufile = u_fopen(path.c_str(), "r", NULL, "UTF-8");

    // Check if the file exists and was opened properly
    mExists = (ufile != NULL);

    // Output a warning if the file wasn't found
    if (!mExists)
    {
        Log::Print("Possible error: Tried to open nonexistent file: " + path);
        return UnicodeString("");
    }
    else
    {
        // Retrieve the size of the file
        long fileSize = 0;
        FILE* file = u_fgetfile(ufile);
        fseek(file, 0, SEEK_END);
        fileSize = ftell(file);
        u_frewind(ufile);

        // Prepare enough space to read the entire string plus termination
        UChar* contents = new UChar[fileSize + 1];

        // Read every character
        long index = 0;

        // Keep a working count of which line and character we're reading
        int line = 1;
        int lineCharacter = 0;

        while (!u_feof(ufile))
        {
            UChar nextChar = u_fgetc(ufile);
            contents[index++] = nextChar;

            // Make sure none of the characters we read are forbidden
            if (mForbiddenCharacters.indexOf(nextChar) != -1)
            {
                Log::Error(UnicodeString("Forbidden character '") + UnicodeString(nextChar) + UnicodeString("' found in file: ") + UnicodeString::fromUTF8(path));
                Log::Print("Line: ", false);
                Log::Print(line);
                Log::Print("Character: ", false);
                Log::Print(lineCharacter);
            }

            // Update the current position in the file
            if (nextChar == '\n')
            {
                ++line;
                lineCharacter = 0;
            }
            ++lineCharacter;
        }

        // Add the string termination
        contents[index] = 0;

        // Create a UnicodeString object
        UnicodeString contentsUString(contents);
        // Clean up the memory used to read the UChars
        delete[] contents;
        // Close the file
        u_fclose(ufile);

        // Check if the UTF-8 Bit Order Mark is present
		UChar a, b, c;
		a = contentsUString[0];
		b = contentsUString[1];
		c = contentsUString[2];

        if(!(a!=(UChar)0xEF || b!=(UChar)0xBB || c!=(UChar)0xBF))
        {
            Log::Error("Warning. File contains UTF-8 bit order mark: " + path);

            // Strip the BOM
            contentsUString = contentsUString.tempSubString(3);
        }

        return contentsUString;
    }
}

void ascii::FileReader::ParseLines(UnicodeString contents, string path)
{
    int numChars = contents.length();
    if (numChars > 0)
    {
        // Split the file contents by line endings
        UnicodeString line = "";
        for (int i = 0; i < numChars; ++i)
        {
            UChar nextChar = contents[i];

            // Store the characters that are chained together as a line
            if (nextChar == '\n' || nextChar == 0)
            {
                line += nextChar;

                mLines.push_back(line);
                line = "";
            }
            else if (nextChar == '\r')
            {
                continue;
            }
            else
            {
                line += nextChar;
            }
        }
    }
}

bool ascii::FileReader::HasNextLine()
{
    return !mLines.empty();
}

string ascii::FileReader::NextLine(bool trimmed)
{
    UnicodeString nextLine = mLines.front();
    mLines.pop_front();

    string temp;
    string nextLineUTF8 = nextLine.toUTF8String(temp);

    if (trimmed)
    {
        if (nextLineUTF8.back() == '\n')
        {
            nextLineUTF8.pop_back();
        }
    }

    return nextLineUTF8;
}

UnicodeString ascii::FileReader::NextLineUnicode(bool trimmed)
{
    UnicodeString nextLine = mLines.front();
    mLines.pop_front();

    if (trimmed)
    {
        nextLine = nextLine.findAndReplace("\n", "");
    }

    return nextLine;
}

string ascii::FileReader::FullContents()
{
    // Collect the whole contents of the buffer in a new string stream
    stringstream buffer;

    while (HasNextLine())
    {
        buffer << NextLine(false);
    }

    // Return the contents as a string
    return buffer.str();
}
<|endoftext|>


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

/**
 * @file
 **/
#include "modules/planning/scenarios/valet_parking/stage_parking.h"

namespace apollo {
namespace planning {
namespace scenario {
namespace valet_parking {

Stage::StageStatus StageParking::Process(
    const common::TrajectoryPoint& planning_init_point, Frame* frame) {
  // Open space planning doesn't use planning_init_point from upstream because
  // of different stitching strategy
  bool plan_ok = ExecuteTaskOnOpenSpace(frame);
  if (!plan_ok) {
    AERROR << "StageParking planning error";
    return StageStatus::ERROR;
  }
  frame->mutable_open_space_info()->set_is_on_open_space_trajectory(true);
  return StageStatus::RUNNING;
}

Stage::StageStatus StageParking::FinishStage() { return Stage::FINISHED; }

}  // namespace valet_parking
}  // namespace scenario
}  // namespace planning
}  // namespace apollo
<commit_msg>Planning: skip reference line decision loading if open_space not successful<commit_after>/******************************************************************************
 * Copyright 2019 The Apollo Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
 * @file
 **/
#include "modules/planning/scenarios/valet_parking/stage_parking.h"

namespace apollo {
namespace planning {
namespace scenario {
namespace valet_parking {

Stage::StageStatus StageParking::Process(
    const common::TrajectoryPoint& planning_init_point, Frame* frame) {
  // Open space planning doesn't use planning_init_point from upstream because
  // of different stitching strategy
  frame->mutable_open_space_info()->set_is_on_open_space_trajectory(true);
  bool plan_ok = ExecuteTaskOnOpenSpace(frame);
  if (!plan_ok) {
    AERROR << "StageParking planning error";
    return StageStatus::ERROR;
  }
  return StageStatus::RUNNING;
}

Stage::StageStatus StageParking::FinishStage() { return Stage::FINISHED; }

}  // namespace valet_parking
}  // namespace scenario
}  // namespace planning
}  // namespace apollo
<|endoftext|>