// WriteIfDifferent //------------------------------------------------------------------------------ /*static*/ bool ProjectGeneratorBase::WriteIfDifferent( const char * generatorId, const AString & content, const AString & fileName ) { bool needToWrite = false; FileStream old; if ( FBuild::Get().GetOptions().m_ForceCleanBuild ) { needToWrite = true; } else if ( old.Open( fileName.Get(), FileStream::READ_ONLY ) == false ) { needToWrite = true; } else { // files differ in size? size_t oldFileSize = (size_t)old.GetFileSize(); if ( oldFileSize != content.GetLength() ) { needToWrite = true; } else { // check content AutoPtr< char > mem( ( char *)ALLOC( oldFileSize ) ); if ( old.Read( mem.Get(), oldFileSize ) != oldFileSize ) { FLOG_ERROR( "%s - Failed to read '%s'", generatorId, fileName.Get() ); return false; } // compare content if ( memcmp( mem.Get(), content.Get(), oldFileSize ) != 0 ) { needToWrite = true; } } // ensure we are closed, so we can open again for write if needed old.Close(); } // only save if missing or different if ( needToWrite == false ) { return true; // nothing to do. } FLOG_BUILD( "%s: %s\n", generatorId, fileName.Get() ); // ensure path exists (normally handled by framework, but Projects // are not necessarily a single file) if ( Node::EnsurePathExistsForFile( fileName ) == false ) { FLOG_ERROR( "%s - Invalid path for '%s' (error: %u)", generatorId, fileName.Get(), Env::GetLastErr() ); return false; } // actually write FileStream f; if ( !f.Open( fileName.Get(), FileStream::WRITE_ONLY ) ) { FLOG_ERROR( "%s - Failed to open '%s' for write (error: %u)", generatorId, fileName.Get(), Env::GetLastErr() ); return false; } if ( f.Write( content.Get(), content.GetLength() ) != content.GetLength() ) { FLOG_ERROR( "%s - Error writing to '%s' (error: %u)", generatorId, fileName.Get(), Env::GetLastErr() ); return false; } f.Close(); return true; }
// PrintVarRecurse //------------------------------------------------------------------------------ /*static*/ void FunctionPrint::PrintVarRecurse( const BFFVariable & var, uint32_t indent ) { AStackString<> indentStr; for ( uint32_t i=0; i<indent; ++i ) { indentStr += " "; } ++indent; FLOG_BUILD( indentStr.Get() ); switch ( var.GetType() ) { case BFFVariable::VAR_ANY: ASSERT( false ); break; // Something is terribly wrong case BFFVariable::VAR_STRING: { AStackString<> value( var.GetString() ); value.Replace( "'", "^'" ); // escape single quotes FLOG_BUILD( "%s = '%s'\n", var.GetName().Get(), value.Get() ); break; } case BFFVariable::VAR_BOOL: { FLOG_BUILD( "%s = %s\n", var.GetName().Get(), var.GetBool() ? "true" : "false" ); break; } case BFFVariable::VAR_ARRAY_OF_STRINGS: { const auto & strings = var.GetArrayOfStrings(); FLOG_BUILD( "%s = // ArrayOfStrings, size: %u\n%s{\n", var.GetName().Get(), (uint32_t)strings.GetSize(), indentStr.Get() ); for ( const AString & string : strings ) { AStackString<> value( string ); value.Replace( "'", "^'" ); // escape single quotes FLOG_BUILD( "%s '%s'\n", indentStr.Get(), value.Get() ); } FLOG_BUILD( "%s}\n", indentStr.Get() ); break; } case BFFVariable::VAR_INT: { FLOG_BUILD( "%s = %i\n", var.GetName().Get(), var.GetInt() ); break; } case BFFVariable::VAR_STRUCT: { FLOG_BUILD( "%s = // Struct\n%s[\n", var.GetName().Get(), indentStr.Get() ); for ( const BFFVariable * subVar : var.GetStructMembers() ) { PrintVarRecurse( *subVar, indent ); } FLOG_BUILD( "%s]\n", indentStr.Get() ); break; } case BFFVariable::VAR_ARRAY_OF_STRUCTS: { const auto & structs = var.GetArrayOfStructs(); FLOG_BUILD( "%s = // ArrayOfStructs, size: %u\n%s{\n", var.GetName().Get(), (uint32_t)structs.GetSize(), indentStr.Get() ); for ( const BFFVariable * subVar : structs ) { PrintVarRecurse( *subVar, indent ); } FLOG_BUILD( "%s}\n", indentStr.Get() ); break; } case BFFVariable::MAX_VAR_TYPES: ASSERT( false ); break; // Something is terribly wrong } }
// Save //------------------------------------------------------------------------------ bool SLNNode::Save( const AString & content, const AString & fileName ) const { bool needToWrite = false; FileStream old; if ( FBuild::Get().GetOptions().m_ForceCleanBuild ) { needToWrite = true; } else if ( old.Open( fileName.Get(), FileStream::READ_ONLY ) == false ) { needToWrite = true; } else { // files differ in size? size_t oldFileSize = (size_t)old.GetFileSize(); if ( oldFileSize != content.GetLength() ) { needToWrite = true; } else { // check content AutoPtr< char > mem( ( char *)ALLOC( oldFileSize ) ); if ( old.Read( mem.Get(), oldFileSize ) != oldFileSize ) { FLOG_ERROR( "SLN - Failed to read '%s'", fileName.Get() ); return false; } // compare content if ( memcmp( mem.Get(), content.Get(), oldFileSize ) != 0 ) { needToWrite = true; } } // ensure we are closed, so we can open again for write if needed old.Close(); } // only save if missing or ner if ( needToWrite == false ) { return true; // nothing to do. } FLOG_BUILD( "SLN: %s\n", fileName.Get() ); // actually write FileStream f; if ( !f.Open( fileName.Get(), FileStream::WRITE_ONLY ) ) { FLOG_ERROR( "SLN - Failed to open '%s' for write (error: %u)", fileName.Get(), Env::GetLastErr() ); return false; } if ( f.Write( content.Get(), content.GetLength() ) != content.GetLength() ) { FLOG_ERROR( "SLN - Error writing to '%s' (error: %u)", fileName.Get(), Env::GetLastErr() ); return false; } f.Close(); return true; }