[sm130futures -> default] The future is now.

This commit is contained in:
Jason Felds
2011-05-05 14:10:42 -04:00
316 changed files with 2879 additions and 34065 deletions
+51 -7
View File
@@ -99,6 +99,9 @@ class Actor : public MessageSubscriber
public:
/** @brief Set up the Actor with its initial settings. */
Actor();
/**
* @brief Copy a new Actor to the old one.
* @param cpy the new Actor to use in place of this one. */
Actor( const Actor &cpy );
virtual ~Actor();
virtual Actor *Copy() const;
@@ -218,11 +221,35 @@ public:
float aux;
};
void Draw(); // calls, EarlyAbortDraw, BeginDraw, DrawPrimitives, EndDraw
virtual bool EarlyAbortDraw() const { return false; } // return true to early abort drawing of this Actor
virtual void BeginDraw(); // pushes transform onto world matrix stack
virtual void SetGlobalRenderStates(); // Actor should call this at beginning of their DrawPrimitives()
virtual void SetTextureRenderStates(); // Actor should call this after setting a texture
/**
* @brief Calls multiple functions for drawing the Actors.
*
* It calls the following in order:
* -# EarlyAbortDraw
* -# BeginDraw
* -# DrawPrimitives
* -# EndDraw
*/
void Draw();
/**
* @brief Allow the Actor to be aborted early.
*
* Subclasses may wish to overwrite this to allow for
* aborted actors.
* @return false, as by default Actors shouldn't be aborted on drawing. */
virtual bool EarlyAbortDraw() const { return false; }
/** @brief Start the drawing and push the transform on the world matrix stack. */
virtual void BeginDraw();
/**
* @brief Set the global rendering states of this Actor.
*
* This should be called at the beginning of an Actor's DrawPrimitives() call. */
virtual void SetGlobalRenderStates();
/**
* @brief Set the texture rendering states of this Actor.
*
* This should be called after setting a texture for the Actor. */
virtual void SetTextureRenderStates();
/**
* @brief Draw the primitives of the Actor.
*
@@ -331,9 +358,26 @@ public:
* @brief Retrieve the zoom factor for the z coordinate of the Actor.
* @return the zoom factor for the z coordinate of the Actor. */
float GetZoomZ() const { return DestTweenState().scale.z; }
void SetZoom( float zoom ) { DestTweenState().scale.x = zoom; DestTweenState().scale.y = zoom; DestTweenState().scale.z = zoom; }
/**
* @brief Set the zoom factor for all dimensions of the Actor.
* @param zoom the zoom factor for all dimensions. */
void SetZoom( float zoom )
{
DestTweenState().scale.x = zoom;
DestTweenState().scale.y = zoom;
DestTweenState().scale.z = zoom;
}
/**
* @brief Set the zoom factor for the x dimension of the Actor.
* @param zoom the zoom factor for the x dimension. */
void SetZoomX( float zoom ) { DestTweenState().scale.x = zoom; }
/**
* @brief Set the zoom factor for the y dimension of the Actor.
* @param zoom the zoom factor for the y dimension. */
void SetZoomY( float zoom ) { DestTweenState().scale.y = zoom; }
/**
* @brief Set the zoom factor for the z dimension of the Actor.
* @param zoom the zoom factor for the z dimension. */
void SetZoomZ( float zoom ) { DestTweenState().scale.z = zoom; }
void ZoomTo( float fX, float fY ) { ZoomToWidth(fX); ZoomToHeight(fY); }
void ZoomToWidth( float zoom ) { SetZoomX( zoom / GetUnzoomedWidth() ); }
@@ -420,7 +464,7 @@ public:
enum StretchType
{
fit_inside, /**< Have the Actor fit inside its parent, using the smaller zoom. */
cover /**, Have the Actor cover its parent, using the larger zoom. */
cover /**< Have the Actor cover its parent, using the larger zoom. */
};
void ScaleToCover( const RectF &rect ) { ScaleTo( rect, cover ); }
+1 -1
View File
@@ -7,7 +7,7 @@
extern "C"
{
#include "lua-5.1/src/lua.h"
#include "../extern/lua-5.1/src/lua.h"
}
/** @brief A general foreach loop for enumerators, going up to a max value. */
+2 -2
View File
@@ -415,8 +415,8 @@ void GameCommand::LoadOne( const Command& cmd )
if( cmd.m_vsArgs.size() == 3 )
{
m_bFadeMusic = true;
m_fMusicFadeOutVolume = atof( cmd.m_vsArgs[1] );
m_fMusicFadeOutSeconds = atof( cmd.m_vsArgs[2] );
m_fMusicFadeOutVolume = static_cast<float>(atof( cmd.m_vsArgs[1] ));
m_fMusicFadeOutSeconds = static_cast<float>(atof( cmd.m_vsArgs[2] ));
}
}
+2 -2
View File
@@ -4,8 +4,8 @@
#include "RageUtil.h"
#include "RageLog.h"
#include "arch/Dialog/Dialog.h"
#include "jsoncpp/include/json/reader.h"
#include "jsoncpp/include/json/writer.h"
#include "../extern/jsoncpp/include/json/reader.h"
#include "../extern/jsoncpp/include/json/writer.h"
bool JsonUtil::LoadFromString(Json::Value &root, RString sData, RString &sErrorOut)
{
+1 -1
View File
@@ -2,7 +2,7 @@
#define JsonUtil_H
class RageFileBasic;
#include "jsoncpp/include/json/value.h"
#include "../extern/jsoncpp/include/json/value.h"
/** @brief Utilities for handling JSON data. */
namespace JsonUtil
{
+3 -3
View File
@@ -10,9 +10,9 @@ class LuaReference;
extern "C"
{
#include "lua-5.1/src/lua.h"
#include "lua-5.1/src/lualib.h"
#include "lua-5.1/src/lauxlib.h"
#include "../extern/lua-5.1/src/lua.h"
#include "../extern/lua-5.1/src/lualib.h"
#include "../extern/lua-5.1/src/lauxlib.h"
}
class LuaManager
+31
View File
@@ -426,6 +426,7 @@ static ThemeMetric<RageColor> WARP_COLOR ( "NoteField", "WarpColor" );
static ThemeMetric<RageColor> TIME_SIGNATURE_COLOR ( "NoteField", "TimeSignatureColor" );
static ThemeMetric<RageColor> TICKCOUNT_COLOR ( "NoteField", "TickcountColor" );
static ThemeMetric<RageColor> COMBO_COLOR ( "NoteField", "ComboColor" );
static ThemeMetric<RageColor> LABEL_COLOR ( "NoteField", "LabelColor" );
static ThemeMetric<bool> BPM_IS_LEFT_SIDE ( "NoteField", "BPMIsLeftSide" );
static ThemeMetric<bool> STOP_IS_LEFT_SIDE ( "NoteField", "StopIsLeftSide" );
static ThemeMetric<bool> DELAY_IS_LEFT_SIDE ( "NoteField", "DelayIsLeftSide" );
@@ -433,6 +434,7 @@ static ThemeMetric<bool> WARP_IS_LEFT_SIDE ( "NoteField", "WarpIsLeftSide" );
static ThemeMetric<bool> TIME_SIGNATURE_IS_LEFT_SIDE ( "NoteField", "TimeSignatureIsLeftSide" );
static ThemeMetric<bool> TICKCOUNT_IS_LEFT_SIDE ( "NoteField", "TickcountIsLeftSide" );
static ThemeMetric<bool> COMBO_IS_LEFT_SIDE ( "NoteField", "ComboIsLeftSide" );
static ThemeMetric<bool> LABEL_IS_LEFT_SIDE ( "NoteField", "LabelIsLeftSide" );
static ThemeMetric<float> BPM_OFFSETX ( "NoteField", "BPMOffsetX" );
static ThemeMetric<float> STOP_OFFSETX ( "NoteField", "StopOffsetX" );
static ThemeMetric<float> DELAY_OFFSETX ( "NoteField", "DelayOffsetX" );
@@ -440,6 +442,7 @@ static ThemeMetric<float> WARP_OFFSETX ( "NoteField", "WarpOffsetX" );
static ThemeMetric<float> TIME_SIGNATURE_OFFSETX ( "NoteField", "TimeSignatureOffsetX" );
static ThemeMetric<float> TICKCOUNT_OFFSETX ( "NoteField", "TickcountOffsetX" );
static ThemeMetric<float> COMBO_OFFSETX ( "NoteField", "ComboOffsetX" );
static ThemeMetric<float> LABEL_OFFSETX ( "NoteField", "LabelOffsetX" );
void NoteField::DrawBPMText( const float fBeat, const float fBPM )
{
@@ -552,6 +555,23 @@ void NoteField::DrawComboText( const float fBeat, int iCombo )
m_textMeasureNumber.Draw();
}
void NoteField::DrawLabelText( const float fBeat, RString sLabel )
{
const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat );
const float fYPos = ArrowEffects::GetYPos( m_pPlayerState, 0, fYOffset, m_fYReverseOffsetPixels );
const float fZoom = ArrowEffects::GetZoom( m_pPlayerState );
const float xBase = GetWidth()/2.f;
const float xOffset = LABEL_OFFSETX * fZoom;
m_textMeasureNumber.SetZoom( fZoom );
m_textMeasureNumber.SetHorizAlign( LABEL_IS_LEFT_SIDE ? align_right : align_left );
m_textMeasureNumber.SetDiffuse( LABEL_COLOR );
m_textMeasureNumber.SetGlow( RageColor(1,1,1,RageFastCos(RageTimer::GetTimeSinceStartFast()*2)/2+0.5f) );
m_textMeasureNumber.SetText( sLabel.c_str() );
m_textMeasureNumber.SetXY( (LABEL_IS_LEFT_SIDE ? -xBase - xOffset : xBase + xOffset), fYPos );
m_textMeasureNumber.Draw();
}
void NoteField::DrawAttackText( const float fBeat, const Attack &attack )
{
const float fYOffset = ArrowEffects::GetYOffset( m_pPlayerState, 0, fBeat );
@@ -830,6 +850,17 @@ void NoteField::DrawPrimitives()
DrawComboText( fBeat, seg->m_iCombo );
}
}
// Label text
FOREACH_CONST( LabelSegment, GAMESTATE->m_pCurSong->m_Timing.m_LabelSegments, seg )
{
if( seg->m_iStartRow >= iFirstRowToDraw && seg->m_iStartRow <= iLastRowToDraw )
{
float fBeat = NoteRowToBeat(seg->m_iStartRow);
if( IS_ON_SCREEN(fBeat) )
DrawLabelText( fBeat, seg->m_sLabel );
}
}
// Course mods text
const Course *pCourse = GAMESTATE->m_pCurCourse;
+1
View File
@@ -61,6 +61,7 @@ protected:
void DrawTimeSignatureText( const float fBeat, int iNumerator, int iDenominator );
void DrawTickcountText( const float fBeat, int iTicks );
void DrawComboText( const float fBeat, int iCombo );
void DrawLabelText( const float fBeat, RString sLabel );
void DrawAttackText( const float fBeat, const Attack &attack );
void DrawBGChangeText( const float fBeat, const RString sNewBGName );
float GetWidth() const;
+3 -2
View File
@@ -10,6 +10,7 @@
#include "Song.h"
#include "SongManager.h"
#include "Steps.h"
#include "Attack.h"
#include "PrefsManager.h"
/** @brief The maximum file size for edits. */
@@ -468,7 +469,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache
// handle the data
/* Don't use GetMainAndSubTitlesFromFullTitle; that's only for heuristically
* splitting other formats that *don't* natively support #SUBTITLE. */
* splitting other formats that *don't* natively support #SUBTITLE. */
if( sValueName=="TITLE" )
out.m_sMainTitle = sParams[1];
@@ -540,7 +541,7 @@ bool SMLoader::LoadFromSMFile( const RString &sPath, Song &out, bool bFromCache
; /* ignore */
/* We calculate these. Some SMs in circulation have bogus values for
* these, so make sure we always calculate it ourself. */
* these, so make sure we always calculate it ourself. */
else if( sValueName=="FIRSTBEAT" )
{
if( bFromCache )
+39 -161
View File
@@ -11,6 +11,7 @@
#include "Song.h"
#include "SongManager.h"
#include "Steps.h"
#include "Attack.h"
#include "PrefsManager.h"
/**
@@ -519,6 +520,35 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
}
}
}
else if( sValueName=="LABELS" )
{
vector<RString> arrayLabelExpressions;
split( sParams[1], ",", arrayLabelExpressions );
for( unsigned b=0; b<arrayLabelExpressions.size(); b++ )
{
vector<RString> arrayLabelValues;
split( arrayLabelExpressions[b], "=", arrayLabelValues );
if( arrayLabelValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayLabelExpressions[b].c_str() );
continue;
}
const float fBeat = StringToFloat( arrayLabelValues[0] );
RString sLabel = arrayLabelValues[1];
TrimRight(sLabel);
if( fBeat >= 0.0f )
out.m_Timing.AddLabelSegment( LabelSegment(fBeat, sLabel) );
else
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid Label at beat %f called %s.", fBeat, sLabel.c_str() );
}
}
}
else if( sValueName=="TIMESIGNATURES" )
{
@@ -768,180 +798,28 @@ bool SSCLoader::LoadFromSSCFile( const RString &sPath, Song &out, bool bFromCach
{
if( sValueName=="STOPS" )
{
/*
vector<RString> arrayFreezeExpressions;
split( sParams[1], ",", arrayFreezeExpressions );
for( unsigned f=0; f<arrayFreezeExpressions.size(); f++ )
{
vector<RString> arrayFreezeValues;
split( arrayFreezeExpressions[f], "=", arrayFreezeValues );
if( arrayFreezeValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayFreezeExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayFreezeValues[0] );
const float fFreezeSeconds = StringToFloat( arrayFreezeValues[1] );
StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds );
if(fFreezeSeconds > 0.0f)
{
// LOG->Trace( "Adding a freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
pNewNotes->m_Timing.AddStopSegment( new_seg );
}
else
{
// negative stops (hi JS!) -aj
if( PREFSMAN->m_bQuirksMode )
{
// LOG->Trace( "Adding a negative freeze segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
pNewNotes->m_Timing.AddStopSegment( new_seg );
}
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid stop at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
}
}
*/
// copy from above when it's time.
}
else if( sValueName=="DELAYS" )
{
/*
vector<RString> arrayDelayExpressions;
split( sParams[1], ",", arrayDelayExpressions );
for( unsigned f=0; f<arrayDelayExpressions.size(); f++ )
{
vector<RString> arrayDelayValues;
split( arrayDelayExpressions[f], "=", arrayDelayValues );
if( arrayDelayValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayDelayExpressions[f].c_str() );
continue;
}
const float fFreezeBeat = StringToFloat( arrayDelayValues[0] );
const float fFreezeSeconds = StringToFloat( arrayDelayValues[1] );
StopSegment new_seg( BeatToNoteRow(fFreezeBeat), fFreezeSeconds, true );
// LOG->Trace( "Adding a delay segment: beat: %f, seconds = %f", new_seg.m_fStartBeat, new_seg.m_fStopSeconds );
if(fFreezeSeconds > 0.0f)
pNewNotes->m_Timing.AddStopSegment( new_seg );
else
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid delay at beat %f, length %f.", fFreezeBeat, fFreezeSeconds );
}
*/
// copy from above when it's time.
}
else if( sValueName=="TIMESIGNATURES" )
{
/*
vector<RString> vs1;
split( sParams[1], ",", vs1 );
FOREACH_CONST( RString, vs1, s1 )
{
vector<RString> vs2;
split( *s1, "=", vs2 );
if( vs2.size() < 3 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with %i values.", (int)vs2.size() );
continue;
}
const float fBeat = StringToFloat( vs2[0] );
TimeSignatureSegment seg;
seg.m_iStartRow = BeatToNoteRow(fBeat);
seg.m_iNumerator = atoi( vs2[1] );
seg.m_iDenominator = atoi( vs2[2] );
if( fBeat < 0 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f.", fBeat );
continue;
}
if( seg.m_iNumerator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iNumerator %i.", fBeat, seg.m_iNumerator );
continue;
}
if( seg.m_iDenominator < 1 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid time signature change with beat %f, iDenominator %i.", fBeat, seg.m_iDenominator );
continue;
}
pNewNotes->m_Timing.AddTimeSignatureSegment( seg );
}
*/
// copy from above when it's time.
}
else if( sValueName=="TICKCOUNTS" )
{
/*
vector<RString> arrayTickcountExpressions;
split( sParams[1], ",", arrayTickcountExpressions );
for( unsigned f=0; f<arrayTickcountExpressions.size(); f++ )
{
vector<RString> arrayTickcountValues;
split( arrayTickcountExpressions[f], "=", arrayTickcountValues );
if( arrayTickcountValues.size() != 2 )
{
// XXX: Hard to tell which file caused this.
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayTickcountExpressions[f].c_str() );
continue;
}
const float fTickcountBeat = StringToFloat( arrayTickcountValues[0] );
const int iTicks = atoi( arrayTickcountValues[1] );
TickcountSegment new_seg( BeatToNoteRow(fTickcountBeat), iTicks );
if(iTicks >= 1 && iTicks <= ROWS_PER_BEAT ) // Constants
{
// LOG->Trace( "Adding a tickcount segment: beat: %f, ticks = %d", fTickcountBeat, iTicks );
pNewNotes->m_Timing.AddTickcountSegment( new_seg );
}
else
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid tickcount at beat %f, ticks %d.", fTickcountBeat, iTicks );
}
}
*/
// copy from above when it's time.
}
else if( sValueName=="COMBOS" )
{
/*
vector<RString> arrayComboExpressions;
split( sParams[1], ",", arrayComboExpressions );
for( unsigned f=0; f<arrayComboExpressions.size(); f++ )
{
vector<RString> arrayComboValues;
split( arrayComboExpressions[f], "=", arrayComboValues );
if( arrayComboValues.size() != 2 )
{
LOG->UserLog( "Song file", "(UNKNOWN)", "has an invalid #%s value \"%s\" (must have exactly one '='), ignored.",
sValueName.c_str(), arrayComboExpressions[f].c_str() );
continue;
}
const float fComboBeat = StringToFloat( arrayComboValues[0] );
const int iCombos = atoi( arrayComboValues[1] );
ComboSegment new_seg( BeatToNoteRow( fComboBeat ), iCombos );
pNewNotes->m_Timing.AddComboSegment( new_seg );
}
*/
// copy from above when it's time.
}
else if( sValueName=="WARPS" || sValueName=="LABELS" )
{
// copy from above when it's time.
}
else if( sValueName=="ATTACKS" )
{
+13
View File
@@ -134,6 +134,19 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
}
}
f.PutLine( ";" );
f.Write( "#ATTACKS:" );
for( unsigned j = 0; j < out.m_Attacks.size(); j++ )
{
const Attack &a = out.m_Attacks[j];
f.Write( ssprintf( "TIME=%.2f:LEN=%.2f:MODS=%s",
a.fStartSecond, a.fSecsRemaining, a.sModifiers.c_str() ) );
if( j+1 < out.m_Attacks.size() )
f.Write( ":" );
f.PutLine( "" );
}
f.PutLine( ";" );
f.Write( "#DELAYS:" );
for( unsigned i=0; i<out.m_Timing.m_StopSegments.size(); i++ )
+17 -83
View File
@@ -195,6 +195,17 @@ static void WriteGlobalTags( RageFile &f, const Song &out )
}
f.PutLine( ";" );
f.Write( "#LABELS:" );
for( unsigned i=0; i<out.m_Timing.m_LabelSegments.size(); i++ )
{
const LabelSegment &ls = out.m_Timing.m_LabelSegments[i];
f.PutLine( ssprintf( "%.6f=%s", NoteRowToBeat(ls.m_iStartRow), ls.m_sLabel.c_str() ) );
if( i != out.m_Timing.m_LabelSegments.size()-1 )
f.Write( "," );
}
f.PutLine( ";" );
FOREACH_BackgroundLayer( b )
{
if( b==0 )
@@ -292,106 +303,29 @@ static RString GetSSCNoteData( const Song &song, const Steps &in, bool bSavingCa
FOREACH_ENUM( RadarCategory, rc )
asRadarValues.push_back( ssprintf("%.3f", rv[rc]) );
}
lines.push_back( ssprintf( "#RADARVALUES:%s:", join(",",asRadarValues).c_str() ) );
lines.push_back( ssprintf( "#RADARVALUES:%s;", join(",",asRadarValues).c_str() ) );
lines.push_back( ssprintf( "#CREDIT:%s;", SmEscape(in.GetCredit()).c_str() ) );
// TODO: Remove this block, uncomment below block for Split Timing. -Wolfman2000
/*
* TODO: Remove this block, transplant above code
* below for Split Timing. -Wolfman2000 */
lines.push_back( "#BPMS:;" );
lines.push_back( "#STOPS:;" );
lines.push_back( "#DELAYS:;" );
lines.push_back( "#WARPS:;" );
lines.push_back( "#LABELS:;" );
lines.push_back( "#TIMESIGNATURES:;" );
lines.push_back( "#TICKCOUNTS:;" );
lines.push_back( "#ATTACKS:;" );
lines.push_back( "#COMBOS:;" );
/*
vector<RString> asBPMValues;
for( unsigned i=0; i<in.m_Timing.m_BPMSegments.size(); i++ )
{
const BPMSegment &bs = in.m_Timing.m_BPMSegments[i];
asBPMValues.push_back( ssprintf("%.6f=%.6f", NoteRowToBeat(bs.m_iStartRow), bs.GetBPM() ) );
}
lines.push_back( ssprintf( "#BPMS:%s;", join("\n,", asBPMValues).c_str() ) );
vector<RString> asStopValues;
for( unsigned i=0; i<in.m_Timing.m_StopSegments.size(); i++ )
{
const StopSegment &fs = in.m_Timing.m_StopSegments[i];
if(!fs.m_bDelay)
{
asStopValues.push_back( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) );
}
}
lines.push_back( ssprintf( "#STOPS:%s;", join("\n,", asStopValues).c_str() ) );
vector<RString> asDelayValues;
for( unsigned i=0; i<in.m_Timing.m_StopSegments.size(); i++ )
{
const StopSegment &fs = in.m_Timing.m_StopSegments[i];
if( fs.m_bDelay )
{
asDelayValues.push_back( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fStopSeconds ) );
}
}
lines.push_back( ssprintf( "#DELAYS:%s;", join("\n,", asDelayValues).c_str() ) );
vector<RString> asWarpValues;
for( unsigned i=0; i<in.m_Timing.m_WarpSegments.size(); i++ )
{
const WarpSegment &ws = in.m_Timing.m_WarpSegments[i];
if( ws.m_bDelay )
{
asWarpValues.push_back( ssprintf( "%.6f=%.6f", NoteRowToBeat(fs.m_iStartRow), fs.m_fWarpBeats ) );
}
}
lines.push_back( ssprintf( "#WARPS:%s;", join("\n,", asWarpValues).c_str() ) );
ASSERT( !in.m_Timing.m_vTimeSignatureSegments.empty() );
vector<RString> asTimeSigValues;
FOREACH_CONST( TimeSignatureSegment, in.m_Timing.m_vTimeSignatureSegments, iter )
{
asTimeSigValues.push_back( ssprintf( "%.6f=%d=%d", NoteRowToBeat(iter->m_iStartRow), iter->m_iNumerator, iter->m_iDenominator ) );
vector<TimeSignatureSegment>::const_iterator iter2 = iter;
iter2++;
}
lines.push_back( ssprintf( "#TIMESIGNATURES:%s;", join("\n,", asTimeSigValues).c_str() ) );
ASSERT( !in.m_Timing.m_TickcountSegments.empty() );
vector<RString> asTickValues;
for( unsigned i=0; i<in.m_Timing.m_TickcountSegments.size(); i++ )
{
const TickcountSegment &ts = in.m_Timing.m_TickcountSegments[i];
asTickValues.push_back( ssprintf( "%.6f=%d", NoteRowToBeat(ts.m_iStartRow), ts.m_iTicks ) );
}
lines.push_back( ssprintf( "#TICKCOUNTS:%s;", join("\n,", asTickValues).c_str() ) );
ASSERT( !in.m_Timing.m_ComboSegments.empty() );
vector<RString> asComboValues;
for( unsigned i=0; i<in.m_Timing.m_ComboSegments.size(); i++ )
{
const ComboSegment &cs = in.m_Timing.m_ComboSegments[i];
asComboValues.push_back( ssprintf( "%.6f=%d", NoteRowToBeat(cs.m_iStartRow), cs.m_iComboFactor ) );
}
lines.push_back( "#ATTACKS:;" );
lines.push_back( ssprintf( "#COMBOS:%s;", join("\n,", asComboValues).c_str() ) );
lines.push_back( ssprintf( "#OFFSET:%.6f;", in.m_Timing.m_fBeat0OffsetInSeconds ) );
*/
RString sNoteData;
in.GetSMNoteData( sNoteData );
lines.push_back( song.m_vsKeysoundFile.empty() ? "#NOTES:" : "#NOTES2:" );
TrimLeft(sNoteData);
split( sNoteData, "\n", lines, true );
lines.push_back( ";" );
+13 -3
View File
@@ -127,8 +127,13 @@ static Preference<bool> g_bEnableMineSoundPlayback ( "EnableMineHitSound", true
Preference<float> g_fTimingWindowHopo ( "TimingWindowHopo", 0.25 ); // max time between notes in a hopo chain
Preference<float> g_fTimingWindowStrum ( "TimingWindowStrum", 0.1f ); // max time between strum and when the frets must match
/** @brief How much life is in a hold note when you start on it? */
ThemeMetric<float> INITIAL_HOLD_LIFE ( "Player", "InitialHoldLife" );
ThemeMetric<float> MAX_HOLD_LIFE ( "Player", "MaxHoldLife" ); // sm-ssc addition
/**
* @brief How much hold life is possible to have when holding a hold note?
*
* This was an sm-ssc addition. */
ThemeMetric<float> MAX_HOLD_LIFE ( "Player", "MaxHoldLife" );
ThemeMetric<bool> PENALIZE_TAP_SCORE_NONE ( "Player", "PenalizeTapScoreNone" );
ThemeMetric<bool> JUDGE_HOLD_NOTES_ON_SAME_ROW_TOGETHER ( "Player", "JudgeHoldNotesOnSameRowTogether" );
/**
@@ -174,6 +179,11 @@ ThemeMetric<bool> REQUIRE_STEP_ON_MINES ( "Player", "RequireStepOnMines" );
*
* For those wishing to make a theme very accurate to In The Groove 2, set this to false. */
ThemeMetric<bool> ROLL_BODY_INCREMENTS_COMBO ( "Player", "RollBodyIncrementsCombo" );
/**
* @brief Are checkpoints and taps considered separate judgments?
*
* If set to true, they are considered separate.
* If set to false, they are considered the same. */
ThemeMetric<bool> CHECKPOINTS_TAPS_SEPARATE_JUDGMENT ( "Player", "CheckpointsTapsSeparateJudgment" );
/**
* @brief Do we score missed holds and rolls with HoldNoteScores?
@@ -1318,9 +1328,9 @@ void Player::UpdateHoldNotes( int iSongRow, float fDeltaTime, vector<TrackRowTap
{
//LOG->Trace("tap note scoring time.");
TapNote &tn = *vTN[0].pTN;
SetHoldJudgment( tn.result.tns, tn.HoldResult.hns, iFirstTrackWithMaxEndRow );
HandleHoldScore( tn );
//LOG->Trace("hold result = %s",StringConversion::ToString(tn.HoldResult.hns).c_str());
SetHoldJudgment( tn.result.tns, tn.HoldResult.hns, iFirstTrackWithMaxEndRow );
}
//LOG->Trace("[Player::UpdateHoldNotes] ends");
}
@@ -1803,8 +1813,8 @@ void Player::ScoreAllActiveHoldsLetGo()
tn.HoldResult.hns = HNS_LetGo;
tn.HoldResult.fLife = 0;
HandleHoldScore( tn );
SetHoldJudgment( tn.result.tns, tn.HoldResult.hns, iTrack );
HandleHoldScore( tn );
}
}
}
+25 -3
View File
@@ -234,7 +234,7 @@ float PlayerStageStats::MakePercentScore( int iActual, int iPossible )
int iPercentTotalDigits = 3 + CommonMetrics::PERCENT_SCORE_DECIMAL_PLACES; // "100" + "." + "00"
// TRICKY: printf will round, but we want to truncate. therwise, we may display
// TRICKY: printf will round, but we want to truncate. Otherwise, we may display
// a percent score that's too high and doesn't match up with the calculated grade.
float fTruncInterval = powf( 0.1f, (float)iPercentTotalDigits-1 );
@@ -250,7 +250,9 @@ RString PlayerStageStats::FormatPercentScore( float fPercentDancePoints )
{
int iPercentTotalDigits = 3 + CommonMetrics::PERCENT_SCORE_DECIMAL_PLACES; // "100" + "." + "00"
RString s = ssprintf( "%*.*f%%", iPercentTotalDigits, (int)CommonMetrics::PERCENT_SCORE_DECIMAL_PLACES, fPercentDancePoints*100 );
RString s = ssprintf( "%*.*f%%", iPercentTotalDigits,
(int)CommonMetrics::PERCENT_SCORE_DECIMAL_PLACES,
fPercentDancePoints*100 );
return s;
}
@@ -679,6 +681,7 @@ public:
DEFINE_METHOD( GetCurrentMissCombo, m_iCurMissCombo )
DEFINE_METHOD( GetCurrentScoreMultiplier, m_iCurScoreMultiplier )
DEFINE_METHOD( GetScore, m_iScore )
DEFINE_METHOD( GetCurMaxScore, m_iCurMaxScore )
DEFINE_METHOD( GetTapNoteScores, m_iTapNoteScores[Enum::Check<TapNoteScore>(L, 1)] )
DEFINE_METHOD( GetHoldNoteScores, m_iHoldNoteScores[Enum::Check<HoldNoteScore>(L, 1)] )
DEFINE_METHOD( FullCombo, FullCombo() )
@@ -724,7 +727,24 @@ public:
static int GetRadarPossible( T* p, lua_State *L ) { p->m_radarPossible.PushSelf(L); return 1; }
static int GetRadarActual( T* p, lua_State *L ) { p->m_radarActual.PushSelf(L); return 1; }
static int SetScore( T* p, lua_State *L ) { if( IArg(1) >= 0 ){ p->m_iScore = IArg(1); return 1; } return 0; }
static int SetScore( T* p, lua_State *L )
{
if( IArg(1) >= 0 )
{
p->m_iScore = IArg(1);
return 1;
}
return 0;
}
static int SetCurMaxScore( T* p, lua_State *L )
{
if( IArg(1) >= 0 )
{
p->m_iCurMaxScore = IArg(1);
return 1;
}
return 0;
}
LunaPlayerStageStats()
{
@@ -735,6 +755,7 @@ public:
ADD_METHOD( GetCurrentMissCombo );
ADD_METHOD( GetCurrentScoreMultiplier );
ADD_METHOD( GetScore );
ADD_METHOD( GetCurMaxScore );
ADD_METHOD( GetTapNoteScores );
ADD_METHOD( GetHoldNoteScores );
ADD_METHOD( FullCombo );
@@ -761,6 +782,7 @@ public:
ADD_METHOD( GetRadarPossible );
ADD_METHOD( GetBestFullComboTapNoteScore );
ADD_METHOD( SetScore );
ADD_METHOD( SetCurMaxScore );
}
};
+35 -8
View File
@@ -12,9 +12,13 @@ struct lua_State;
class PlayerStageStats
{
public:
/** @brief Set up the PlayerStageStats with default values. */
PlayerStageStats() { Init(); }
void Init();
/**
* @brief Add stats from one PlayerStageStats to another.
* @param other the other stats to add to this one. */
void AddStats( const PlayerStageStats& other ); // accumulate
Grade GetGrade() const;
@@ -51,14 +55,25 @@ public:
int m_iPossibleGradePoints;
int m_iTapNoteScores[NUM_TapNoteScore];
int m_iHoldNoteScores[NUM_HoldNoteScore];
/** @brief The Player's current combo. */
int m_iCurCombo;
/** @brief The Player's max combo. */
int m_iMaxCombo;
/** @brief The Player's current miss combo. */
int m_iCurMissCombo;
int m_iCurScoreMultiplier;
/** @brief The player's current score. */
int m_iScore;
/** @brief The theoretically highest score the Player could have at this point. */
int m_iCurMaxScore;
/** @brief The maximum score the Player can get this goaround. */
int m_iMaxScore;
RadarValues m_radarPossible; // filled in by ScreenGameplay on start of notes
/**
* @brief The possible RadarValues for a song.
*
* This is filled in by ScreenGameplay on the start of the notes. */
RadarValues m_radarPossible;
RadarValues m_radarActual;
/** @brief How many songs were passed by the Player? */
int m_iSongsPassed;
@@ -83,18 +98,30 @@ public:
struct Combo_t
{
/* Start and size of this combo, in the same scale as the combo list
* mapping and the life record. */
float m_fStartSecond, m_fSizeSeconds;
/**
* @brief The start time of the combo.
*
* This uses the same scale as the combo list mapping. */
float m_fStartSecond;
/**
* @brief The size time of the combo.
*
* This uses the same scale as the life record. */
float m_fSizeSeconds;
// Combo size, in steps.
/** @brief The size of the Combo, in steps. */
int m_cnt;
/* Size of the combo that didn't come from this stage (rollover from the
* last song). (This is a subset of cnt.) */
/**
* @brief The size of the combo that didn't come from this stage.
*
* This is generally rolled over from the last song.
* It is also a subset of m_cnt. */
int m_rollover;
// Get the size of the combo that came from this song.
/**
* @brief Retrieve the size of the combo that came from this song.
* @return this song's combo size. */
int GetStageCnt() const { return m_cnt - m_rollover; }
Combo_t(): m_fStartSecond(0), m_fSizeSeconds(0), m_cnt(0), m_rollover(0) { }
-10
View File
@@ -125,15 +125,6 @@ XToString( CourseSortOrders );
StringToX( CourseSortOrders );
LuaXType( CourseSortOrders );
static const char *ScoringTypeNames[] = {
"New",
"Old",
"Custom",
};
XToString( ScoringType );
StringToX( ScoringType );
LuaXType( ScoringType );
// XXX: Fix fail bug?
/* static const char *DefaultFailTypeNames[] = {
"Immediate",
@@ -263,7 +254,6 @@ PrefsManager::PrefsManager() :
m_CourseSortOrder ( "CourseSortOrder", COURSE_SORT_SONGS ),
m_bSubSortByNumSteps ( "SubSortByNumSteps", false ),
m_GetRankingName ( "GetRankingName", RANKING_ON ),
m_ScoringType ( "ScoringType", SCORING_NEW ),
m_sAdditionalSongFolders ( "AdditionalSongFolders", "" ),
m_sAdditionalCourseFolders ( "AdditionalCourseFolders", "" ),
m_sAdditionalFolders ( "AdditionalFolders", "" ),
-10
View File
@@ -108,14 +108,6 @@ enum CourseSortOrders
NUM_CourseSortOrders,
CourseSortOrders_Invalid
};
enum ScoringType
{
SCORING_NEW,
SCORING_OLD,
SCORING_CUSTOM,
NUM_ScoringType,
ScoringType_Invalid
};
enum DefaultFailType
{
@@ -266,8 +258,6 @@ public:
Preference<bool> m_bSubSortByNumSteps;
Preference<GetRankingName> m_GetRankingName;
Preference<ScoringType> m_ScoringType;
Preference<RString> m_sAdditionalSongFolders;
Preference<RString> m_sAdditionalCourseFolders;
Preference<RString> m_sAdditionalFolders;
+2 -2
View File
@@ -7,9 +7,9 @@
#include <memory>
#if defined(_WINDOWS)
#include "zlib/zlib.h"
#include "../extern/zlib/zlib.h"
#if defined(_MSC_VER)
#pragma comment(lib, "zlib/zdll.lib")
#pragma comment(lib, "../extern/zlib/zdll.lib")
#endif
#elif defined(MACOSX)
/* Since crypto++ was added to the repository, <zlib.h> includes the zlib.h
+2 -2
View File
@@ -10,9 +10,9 @@
#include <map>
#if defined(_WINDOWS) || defined(MACOSX)
#include "mad-0.15.1b/mad.h"
#include "../extern/mad-0.15.1b/mad.h"
#ifdef _MSC_VER
#pragma comment(lib, "mad-0.15.1b/msvc++/Release/libmad.lib")
#pragma comment(lib, "../extern/mad-0.15.1b/msvc++/Release/libmad.lib")
#endif //_MSC_VER
#else
#include <mad.h>
+1 -1
View File
@@ -7,7 +7,7 @@
#if defined(INTEGER_VORBIS)
#include <tremor/ivorbisfile.h>
#else
#include <vorbis/vorbisfile.h>
#include <../extern/vorbis/vorbis/vorbisfile.h>
#endif
#if defined(_MSC_VER)
+5 -5
View File
@@ -11,18 +11,18 @@
// work around namespace bugs in win32/libjpeg:
#define XMD_H
#undef FAR
#include "libjpeg/jpeglib.h"
#include "libjpeg/jerror.h"
#include "../extern/libjpeg/jpeglib.h"
#include "../extern/libjpeg/jerror.h"
#if defined(_MSC_VER)
#pragma comment(lib, "libjpeg/jpeg.lib")
#pragma comment(lib, "../extern/libjpeg/jpeg.lib")
#endif
#pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
#else
extern "C" {
#include <jpeglib.h>
#include <jerror.h>
#include <../extern/libjpeg/jpeglib.h>
#include <../extern/libjpeg/jerror.h>
}
#endif
+3 -3
View File
@@ -7,13 +7,13 @@
#if defined(_WINDOWS)
# include "libpng/include/png.h"
# include "../extern/libpng/include/png.h"
# if defined(_MSC_VER)
# pragma comment(lib, "libpng/lib/libpng.lib")
# pragma comment(lib, "../extern/libpng/lib/libpng.lib")
# pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
# endif // _MSC_VER
#else
# include <png.h>
# include <../extern/libpng/include/png.h>
#endif
namespace
+2 -2
View File
@@ -12,13 +12,13 @@ namespace jpeg
{
extern "C"
{
#include <jpeglib.h>
#include <../extern/libjpeg/jpeglib.h>
}
}
// Pull in JPEG library here.
#if defined _MSC_VER
#pragma comment(lib, "libjpeg/jpeg.lib")
#pragma comment(lib, "../extern/libjpeg/jpeg.lib")
#endif
#define OUTPUT_BUFFER_SIZE 4096
+3 -3
View File
@@ -7,13 +7,13 @@
#include "RageUtil.h"
#if defined(WINDOWS)
#include "libpng/include/png.h"
#include "../extern/libpng/include/png.h"
#if defined(_MSC_VER)
# pragma comment(lib, "libpng/lib/libpng.lib")
# pragma comment(lib, "../extern/libpng/lib/libpng.lib")
#pragma warning(disable: 4611) /* interaction between '_setjmp' and C++ object destruction is non-portable */
#endif
#else
#include <png.h>
#include <../extern/libpng/include/png.h>
#endif
static void SafePngError( png_struct *pPng, const RString &sStr )
+1 -1
View File
@@ -1280,7 +1280,7 @@ bool GetFileContents( const RString &sFile, vector<RString> &asOut )
return true;
}
#include "pcre/pcre.h"
#include "../extern/pcre/pcre.h"
void Regex::Compile()
{
const char *error;
+1
View File
@@ -1,6 +1,7 @@
#include "global.h"
#include "RollingNumbers.h"
#include "RageUtil.h"
#include "GameState.h"
#include "XmlFile.h"
#include "ActorUtil.h"
#include "LuaManager.h"
+10 -178
View File
@@ -94,30 +94,6 @@ void ScoreKeeperNormal::Load(
//m_vToastyTriggers.Load( "Gameplay", "ToastyTriggersAt" );
m_ToastyTrigger.Load( "Gameplay", "ToastyTriggersAt" );
// Custom Scoring
m_CustomComboMultiplier.Load( "CustomScoring", "ComboMultiplier" );
m_CustomTNS_W1.Load( "CustomScoring", "PointsW1" );
m_CustomTNS_W2.Load( "CustomScoring", "PointsW2" );
m_CustomTNS_W3.Load( "CustomScoring", "PointsW3" );
m_CustomTNS_W4.Load( "CustomScoring", "PointsW4" );
m_CustomTNS_W5.Load( "CustomScoring", "PointsW5" );
m_CustomTNS_Miss.Load( "CustomScoring", "PointsMiss" );
m_CustomTNS_HitMine.Load( "CustomScoring", "PointsHitMine" );
m_CustomTNS_CheckpointHit.Load( "CustomScoring", "PointsCheckpointHit" );
m_CustomTNS_CheckpointMiss.Load( "CustomScoring", "PointsCheckpointMiss" );
m_CustomTNS_None.Load( "CustomScoring", "PointsNone" );
m_CustomHNS_Held.Load( "CustomScoring", "PointsHoldHeld" );
m_CustomHNS_LetGo.Load( "CustomScoring", "PointsHoldLetGo" );
m_CustomComboBonus.Load( "CustomScoring", "ComboAboveThresholdAddsToScoreBonus" );
m_CustomComboBonusThreshold.Load( "CustomScoring", "ComboScoreBonusThreshold" );
m_CustomComboBonusValue.Load( "CustomScoring", "ComboScoreBonusValue" );
m_DoubleNoteMultiplier.Load( "CustomScoring", "DoubleNoteScoreMultiplier" );
m_TripleNoteMultiplier.Load( "CustomScoring", "TripleNoteScoreMultiplier" );
m_QuadPlusNoteMultiplier.Load( "CustomScoring", "QuadOrHigherNoteScoreMultiplier" );
// Fill in STATSMAN->m_CurStageStats, calculate multiplier
int iTotalPossibleDancePoints = 0;
int iTotalPossibleGradePoints = 0;
@@ -179,24 +155,7 @@ void ScoreKeeperNormal::Load(
MESSAGEMAN->Broadcast( msg );
memset( m_ComboBonusFactor, 0, sizeof(m_ComboBonusFactor) );
switch( PREFSMAN->m_ScoringType )
{
case SCORING_NEW:
case SCORING_CUSTOM:
m_iRoundTo = 1;
break;
case SCORING_OLD:
m_iRoundTo = 5;
if (!GAMESTATE->IsCourseMode())
{
m_ComboBonusFactor[TNS_W1] = 55;
m_ComboBonusFactor[TNS_W2] = 55;
m_ComboBonusFactor[TNS_W3] = 33;
}
break;
DEFAULT_FAIL( int(PREFSMAN->m_ScoringType) );
}
m_iRoundTo = 1;
}
void ScoreKeeperNormal::OnNextSong( int iSongInCourseIndex, const Steps* pSteps, const NoteData* pNoteData )
@@ -247,25 +206,12 @@ void ScoreKeeperNormal::OnNextSong( int iSongInCourseIndex, const Steps* pSteps,
}
else
{
const int iMeter = clamp( pSteps->GetMeter(), 1, 10 );
// long ver and marathon ver songs have higher max possible scores
int iLengthMultiplier = GameState::GetNumStagesMultiplierForSong( GAMESTATE->m_pCurSong );
switch( PREFSMAN->m_ScoringType )
{
case SCORING_NEW:
m_iMaxPossiblePoints = iMeter * 10000000 * iLengthMultiplier;
break;
case SCORING_OLD:
m_iMaxPossiblePoints = (iMeter * iLengthMultiplier + 1) * 5000000;
break;
case SCORING_CUSTOM:
/* This is just simple additive/subtractive scoring, but cap the
* score at the size of the score counter */
m_iMaxPossiblePoints = 10 * 10000000 * iLengthMultiplier;
break;
DEFAULT_FAIL( int(PREFSMAN->m_ScoringType) );
}
/* This is no longer just simple additive/subtractive scoring,
* but start with capping the score at the size of the score counter. */
m_iMaxPossiblePoints = 10 * 10000000 * iLengthMultiplier;
}
ASSERT( m_iMaxPossiblePoints >= 0 );
m_iMaxScoreSoFar += m_iMaxPossiblePoints;
@@ -317,24 +263,12 @@ void ScoreKeeperNormal::AddTapScore( TapNoteScore tns )
void ScoreKeeperNormal::AddHoldScore( HoldNoteScore hns )
{
if( PREFSMAN->m_ScoringType == SCORING_CUSTOM )
{
int &iScore = m_pPlayerStageStats->m_iScore;
int &iCurMaxScore = m_pPlayerStageStats->m_iCurMaxScore;
iCurMaxScore += m_CustomHNS_Held;
if( hns == HNS_Held )
iScore += m_CustomHNS_Held;
else if ( hns == HNS_LetGo )
iScore += m_CustomHNS_LetGo;
}
else
if( GAMESTATE->IsCourseMode() )
{
if( hns == HNS_Held )
AddScoreInternal( TNS_W1 );
else if ( hns == HNS_LetGo )
AddScoreInternal( TNS_W4 ); // required for subtractive score display to work properly
AddScoreInternal( TNS_W4 ); // required for subtractive score display to work properly.
}
}
@@ -352,14 +286,6 @@ void ScoreKeeperNormal::HandleTapScoreNone()
if( m_pPlayerState->m_PlayerNumber != PLAYER_INVALID )
MESSAGEMAN->Broadcast( enum_add2(Message_CurrentComboChangedP1,m_pPlayerState->m_PlayerNumber) );
if( PREFSMAN->m_ScoringType == SCORING_CUSTOM )
{
int &iScore = m_pPlayerStageStats->m_iScore;
iScore += m_CustomTNS_None;
}
else
AddScoreInternal( TNS_Miss );
}
// TODO: networking code
@@ -369,47 +295,9 @@ void ScoreKeeperNormal::AddScoreInternal( TapNoteScore score )
{
int &iScore = m_pPlayerStageStats->m_iScore;
int &iCurMaxScore = m_pPlayerStageStats->m_iCurMaxScore;
/*
Regular scoring:
Let p = score multiplier (W1 = W2 = 10, W3 = 5, other = 0)
Note on NONSTOP Mode scoring
Let p = score multiplier (W1 = 10, W2 = 9, W3 = 5, other = 0)
N = total number of steps and freeze steps
S = The sum of all integers from 1 to N (the total number of steps/freeze steps)
n = number of the current step or freeze step (varies from 1 to N)
Z = Base value of the song (1,000,000 X the number of feet difficulty) - All edit data is rated as 5 feet
So, the score for one step is:
one_step_score = p * (Z/S) * n
*IMPORTANT* : Double steps (U+L, D+R, etc.) count as two steps instead of one *for your combo count only*,
so if you get a double L+R on the 112th step of a song, you score is calculated for only one step, not two,
as the combo counter might otherwise imply.
Now, through simple algebraic manipulation:
S = 1+...+N = (1+N)*N/2 (1 through N added together)
Okay, time for an example. Suppose we wanted to calculate the step score of a W3 on the 57th step of
a 441 step, 8-foot difficulty song (I'm just making this one up):
S = (1 + 441)*441 / 2
= 194,222 / 2
= 97,461
StepScore = p * (Z/S) * n
= 5 * (8,000,000 / 97,461) * 57
= 5 * (82) * 57 (The 82 is rounded down from 82.08411...)
= 23,370
Remember this is just the score for the step, not the cumulative score up to the 57th step. Also, please note that
I am currently checking into rounding errors with the system and if there are any, how they are resolved in the system.
Note: if you got all W2s on this song, you would get (p=10)*Z, which is 80,000,000. In fact, the maximum possible
score for any song is the number of feet difficulty X 10,000,000.
*/
if( PREFSMAN->m_ScoringType != SCORING_CUSTOM || GAMESTATE->IsCourseMode() )
// See Aaron In Japan for more details about the scoring formulas.
if( GAMESTATE->IsCourseMode() )
{
int p = 0; // score multiplier
@@ -469,45 +357,7 @@ void ScoreKeeperNormal::AddScoreInternal( TapNoteScore score )
// Custom Scoring
else
{
int p = 0; // score value
switch( score )
{
case TNS_W1: p = m_CustomTNS_W1; break;
case TNS_W2: p = m_CustomTNS_W2; break;
case TNS_W3: p = m_CustomTNS_W3; break;
case TNS_W4: p = m_CustomTNS_W4; break;
case TNS_W5: p = m_CustomTNS_W5; break;
case TNS_Miss: p = m_CustomTNS_Miss; break;
default: p = 0; break;
}
if( m_CustomComboBonus )
{
if( m_pPlayerStageStats->m_iCurCombo > m_CustomComboBonusThreshold )
p += m_CustomComboBonusValue;
}
p += static_cast<int>(m_pPlayerStageStats->m_iCurCombo * m_CustomComboMultiplier);
if( m_iNumNotesHitThisRow == 2 )
p = (int)(p * m_DoubleNoteMultiplier);
else if( m_iNumNotesHitThisRow == 3 )
p = (int)(p * m_TripleNoteMultiplier);
else if( m_iNumNotesHitThisRow >= 4 )
p = (int)(p * m_QuadPlusNoteMultiplier);
if( !m_pPlayerStageStats->m_bFailed )
{
m_iTapNotesHit++;
iScore += p;
iCurMaxScore += m_CustomTNS_W1;
}
// Because the score can drop below 0 if you miss a bunch of notes, cap it off at zero
if( iScore <= 0 )
iScore = 0;
}
ASSERT( iScore >= 0 );
@@ -536,11 +386,6 @@ void ScoreKeeperNormal::HandleTapScore( const TapNote &tn )
if( m_MineHitIncrementsMissCombo )
HandleComboInternal( 0, 0, 1 );
if( PREFSMAN->m_ScoringType == SCORING_CUSTOM )
{
int &iScore = m_pPlayerStageStats->m_iScore;
iScore += m_CustomTNS_HitMine;
}
}
if( tns == TNS_AvoidMine && m_AvoidMineIncrementsCombo )
@@ -564,19 +409,6 @@ void ScoreKeeperNormal::HandleTapScore( const TapNote &tn )
void ScoreKeeperNormal::HandleHoldCheckpointScore( const NoteData &nd, int iRow, int iNumHoldsHeldThisRow, int iNumHoldsMissedThisRow )
{
if( PREFSMAN->m_ScoringType == SCORING_CUSTOM )
{
int &iScore = m_pPlayerStageStats->m_iScore;
int &iCurMaxScore = m_pPlayerStageStats->m_iCurMaxScore;
iCurMaxScore += m_CustomTNS_CheckpointHit;
if( iNumHoldsMissedThisRow == 0 )
iScore += m_CustomTNS_CheckpointHit;
else
iScore += m_CustomTNS_CheckpointMiss;
}
HandleTapNoteScoreInternal( iNumHoldsMissedThisRow == 0? TNS_CheckpointHit:TNS_CheckpointMiss, TNS_CheckpointHit );
HandleComboInternal( iNumHoldsHeldThisRow, 0, iNumHoldsMissedThisRow, iRow );
}
-24
View File
@@ -40,30 +40,6 @@ class ScoreKeeperNormal: public ScoreKeeper
ThemeMetric<bool> m_MineHitIncrementsMissCombo;
ThemeMetric<bool> m_AvoidMineIncrementsCombo;
// Custom Scoring Theme Metrics
ThemeMetric<int> m_CustomTNS_W1;
ThemeMetric<int> m_CustomTNS_W2;
ThemeMetric<int> m_CustomTNS_W3;
ThemeMetric<int> m_CustomTNS_W4;
ThemeMetric<int> m_CustomTNS_W5;
ThemeMetric<int> m_CustomTNS_Miss;
ThemeMetric<int> m_CustomTNS_HitMine;
ThemeMetric<int> m_CustomTNS_CheckpointHit;
ThemeMetric<int> m_CustomTNS_CheckpointMiss;
ThemeMetric<int> m_CustomTNS_None;
ThemeMetric<int> m_CustomHNS_Held;
ThemeMetric<int> m_CustomHNS_LetGo;
ThemeMetric<bool> m_CustomComboBonus;
ThemeMetric<int> m_CustomComboBonusThreshold;
ThemeMetric<int> m_CustomComboBonusValue;
ThemeMetric<float> m_DoubleNoteMultiplier;
ThemeMetric<float> m_TripleNoteMultiplier;
ThemeMetric<float> m_QuadPlusNoteMultiplier;
ThemeMetric<float> m_CustomComboMultiplier;
//ThemeMetric<LuaReference> m_vToastyTriggers;
ThemeMetric<int> m_ToastyTrigger;
+168 -89
View File
@@ -80,6 +80,8 @@ AutoScreenMessage( SM_BackFromTimeSignatureNumeratorChange );
AutoScreenMessage( SM_BackFromTimeSignatureDenominatorChange );
AutoScreenMessage( SM_BackFromTickcountChange );
AutoScreenMessage( SM_BackFromComboChange );
AutoScreenMessage( SM_BackFromLabelChange );
AutoScreenMessage( SM_BackFromWarpChange );
AutoScreenMessage( SM_DoSaveAndExit );
AutoScreenMessage( SM_DoExit );
AutoScreenMessage( SM_SaveSuccessful );
@@ -94,35 +96,6 @@ static const char *EditStateNames[] = {
XToString( EditState );
LuaXType( EditState );
#if defined(XBOX)
void ScreenEdit::InitEditMappings()
{
/* XXX: fill this in */
m_EditMappingsDeviceInput.Clear();
switch( EDIT_MODE.GetValue() )
{
case EditMode_Practice:
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_PREV_MEASURE][0] = DeviceInput(DEVICE_JOY1, JOY_HAT_UP);
m_EditMappingsMenuButton.button[EDIT_BUTTON_SCROLL_PREV_MEASURE][0] = GAME_BUTTON_UP;
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_NEXT_MEASURE][0] = DeviceInput(DEVICE_JOY1, JOY_HAT_DOWN);
m_EditMappingsMenuButton.button[EDIT_BUTTON_SCROLL_NEXT_MEASURE][0] = GAME_BUTTON_DOWN;
break;
default:
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_UP_LINE][0] = DeviceInput(DEVICE_JOY1, JOY_HAT_UP);
m_EditMappingsMenuButton.button[EDIT_BUTTON_SCROLL_UP_LINE][0] = GAME_BUTTON_UP;
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_DOWN_LINE][0] = DeviceInput(DEVICE_JOY1, JOY_HAT_DOWN);
m_EditMappingsMenuButton.button[EDIT_BUTTON_SCROLL_DOWN_LINE][0] = GAME_BUTTON_DOWN;
break;
}
// Map these to the triggers: L goes up, R goes down.
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_UP_PAGE][0] = DeviceInput(DEVICE_JOY1, JOY_BUTTON_7);
//m_EditMappingsMenuButton.button[EDIT_BUTTON_SCROLL_UP_PAGE][0] = GAME_BUTTON_UPLEFT;
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_DOWN_PAGE][0] = DeviceInput(DEVICE_JOY1, JOY_BUTTON_8);
//m_EditMappingsMenuButton.button[EDIT_BUTTON_SCROLL_DOWN_PAGE][0] = GAME_BUTTON_UPRIGHT;
}
#else
void ScreenEdit::InitEditMappings()
{
m_EditMappingsDeviceInput.Clear();
@@ -153,6 +126,14 @@ void ScreenEdit::InitEditMappings()
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_PERIOD);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_COMMA);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_PERIOD);
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_NEXT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_COMMA);
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LCTRL);
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_LABEL_PREV][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RCTRL);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SCROLL_SELECT][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT);
@@ -235,7 +216,7 @@ void ScreenEdit::InitEditMappings()
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SAMPLE_LENGTH_DOWN][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT);
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_SAMPLE_LENGTH_DOWN][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_PLAY_SAMPLE_MUSIC][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cm);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_PLAY_SAMPLE_MUSIC][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cl);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_BGCHANGE_LAYER1_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cb);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_BGCHANGE_LAYER2_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cb);
@@ -268,7 +249,7 @@ void ScreenEdit::InitEditMappings()
m_EditMappingsDeviceInput.button[EDIT_BUTTON_RIGHT_SIDE][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RALT);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_LAY_ROLL][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LSHIFT);
// m_EditMappingsDeviceInput.button[EDIT_BUTTON_LAY_TAP_ATTACK][0] = DeviceInput(DEVICE_KEYBOARD, KEY_RSHIFT);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_CYCLE_TAP_LEFT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cn);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_CYCLE_TAP_RIGHT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cm);
@@ -291,7 +272,7 @@ void ScreenEdit::InitEditMappings()
m_EditMappingsMenuButton.button[EDIT_BUTTON_OPEN_EDIT_MENU][1] = GAME_BUTTON_BACK;
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_AREA_MENU][0] = DeviceInput(DEVICE_KEYBOARD, KEY_ENTER);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_OPEN_INPUT_HELP][0] = DeviceInput(DEVICE_KEYBOARD, KEY_F1);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cb);
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP][0] = DeviceInput(DEVICE_KEYBOARD, KEY_LALT);
m_EditMappingsDeviceInput.hold[EDIT_BUTTON_BAKE_RANDOM_FROM_SONG_GROUP][1] = DeviceInput(DEVICE_KEYBOARD, KEY_RALT);
@@ -309,7 +290,7 @@ void ScreenEdit::InitEditMappings()
m_EditMappingsDeviceInput.button[EDIT_BUTTON_ADJUST_FINE][0] = DeviceInput(DEVICE_KEYBOARD, KEY_RALT);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_ADJUST_FINE][1] = DeviceInput(DEVICE_KEYBOARD, KEY_LALT);
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SAVE][1] = DeviceInput(DEVICE_KEYBOARD, KEY_Cs);
#if defined(MACOSX)
/* use cmd */
@@ -322,10 +303,10 @@ void ScreenEdit::InitEditMappings()
#endif
m_EditMappingsDeviceInput.button[EDIT_BUTTON_UNDO][1] = DeviceInput(DEVICE_KEYBOARD, KEY_Cu);
// Switch players, if it makes sense to do so.
m_EditMappingsDeviceInput.button[EDIT_BUTTON_SWITCH_PLAYERS][0] = DeviceInput(DEVICE_KEYBOARD, KEY_SLASH);
m_PlayMappingsDeviceInput.button[EDIT_BUTTON_RETURN_TO_EDIT][0] = DeviceInput(DEVICE_KEYBOARD, KEY_ESC);
m_PlayMappingsMenuButton.button[EDIT_BUTTON_RETURN_TO_EDIT][1] = GAME_BUTTON_BACK;
@@ -346,8 +327,6 @@ void ScreenEdit::InitEditMappings()
m_RecordPausedMappingsDeviceInput.button[EDIT_BUTTON_UNDO][0] = DeviceInput(DEVICE_KEYBOARD, KEY_Cu);
}
#endif
/* Given a DeviceInput that was just depressed, return an active edit function. */
EditButton ScreenEdit::DeviceToEdit( const DeviceInput &DeviceI ) const
{
@@ -540,8 +519,7 @@ static MenuDef g_AreaMenu(
static MenuDef g_StepsInformation(
"ScreenMiniMenuStepsInformation",
MenuRowDef( ScreenEdit::difficulty, "Difficulty", true, EditMode_Practice, true, true, 0, NULL ),
// xxx: this giant list of numbers SUUUUUUUUUUCKS -aj
MenuRowDef( ScreenEdit::meter, "Meter", true, EditMode_Practice, true, false, 0, "1","2","3","4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25" ),
MenuRowDef( ScreenEdit::meter, "Meter", true, EditMode_Practice, true, false, 0, MIN_METER, MAX_METER ),
MenuRowDef( ScreenEdit::description, "Description", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::chartstyle, "Chart Style", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::step_credit, "Step Author", true, EditMode_Practice, true, true, 0, NULL ),
@@ -569,7 +547,13 @@ static MenuDef g_SongInformation(
MenuRowDef( ScreenEdit::main_title_transliteration, "Main title transliteration", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::sub_title_transliteration, "Sub title transliteration", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::artist_transliteration, "Artist transliteration", true, EditMode_Practice, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::last_beat_hint, "Last beat hint", true, EditMode_Full, true, true, 0, NULL )
MenuRowDef( ScreenEdit::beat_0_offset, "Beat 0 Offset", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::last_beat_hint, "Last beat hint", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::preview_start, "Preview Start", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::preview_length, "Preview Length", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::display_bpm, "Display BPM", true, EditMode_Full, true, true, 0, "Actual", "Specified", "Random" ),
MenuRowDef( ScreenEdit::min_bpm, "Min BPM", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::max_bpm, "Max BPM", true, EditMode_Full, true, true, 0, NULL )
);
static MenuDef g_TimingDataInformation(
@@ -580,7 +564,9 @@ static MenuDef g_TimingDataInformation(
MenuRowDef( ScreenEdit::time_signature_numerator, "Edit time signature (top)", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::time_signature_denominator, "Edit time signature (bottom)", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::tickcount, "Edit tickcount", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL )
MenuRowDef( ScreenEdit::combo, "Edit combo", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::label, "Edit label", true, EditMode_Full, true, true, 0, NULL ),
MenuRowDef( ScreenEdit::warp, "Edit warp", true, EditMode_Full, true, true, 0, NULL )
);
enum { song_bganimation, song_movie, song_bitmap, global_bganimation, global_movie, global_movie_song_group, global_movie_song_group_and_genre, dynamic_random, baked_random, none };
@@ -765,8 +751,11 @@ void ScreenEdit::Init()
}
}
m_PlayerStateEdit.m_PlayerNumber = PLAYER_1;
// If we always go with the GAMESTATE NoteSkin, we will have fun effects like Vivid or Flat in the editor notefield.
// This is not conducive to productive editing.
// If we always go with the GAMESTATE NoteSkin, we will have fun effects
// like Vivid or Flat in the editor notefield. This is not conducive to
// productive editing.
// todo: We should allow certain noteskins (note-colored/rhythm) to be
// displayed. (Perhaps this should be a noteskin metric.) -aj
if( NOTESKIN->DoesNoteSkinExist( EDITOR_NOTE_SKINS[PLAYER_1].Get() ) )
{
PO_GROUP_ASSIGN( m_PlayerStateEdit.m_PlayerOptions, ModsLevel_Stage, m_sNoteSkin, EDITOR_NOTE_SKINS[PLAYER_1].Get() );
@@ -1243,6 +1232,8 @@ static int FindAttackAtTime( const AttackArray& attacks, float fStartTime )
static LocalizedString SWITCHED_TO ( "ScreenEdit", "Switched to" );
static LocalizedString NO_BACKGROUNDS_AVAILABLE ( "ScreenEdit", "No backgrounds available" );
static ThemeMetric<bool> INVERT_SCROLL_BUTTONS ( "ScreenEdit", "InvertScrollSpeedButtons" );
void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
{
if( input.type == IET_RELEASE )
@@ -1364,10 +1355,10 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
{
DEFAULT_FAIL(EditB);
case EDIT_BUTTON_SCROLL_SPEED_DOWN:
--iSpeed;
INVERT_SCROLL_BUTTONS ? ++iSpeed : --iSpeed;
break;
case EDIT_BUTTON_SCROLL_SPEED_UP:
++iSpeed;
INVERT_SCROLL_BUTTONS ? --iSpeed : ++iSpeed;
break;
}
iSpeed = clamp( iSpeed, 0, (int) ARRAYLEN(fSpeeds)-1 );
@@ -1449,6 +1440,18 @@ void ScreenEdit::InputEdit( const InputEventPlus &input, EditButton EditB )
ScrollTo( NoteRowToBeat(iRow) );
}
break;
case EDIT_BUTTON_LABEL_NEXT:
{
ScrollTo( GAMESTATE->m_pCurSong->m_Timing.
GetNextLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) );
}
break;
case EDIT_BUTTON_LABEL_PREV:
{
ScrollTo( GAMESTATE->m_pCurSong->m_Timing.
GetPreviousLabelSegmentBeatAtBeat( GAMESTATE->m_fSongBeat ) );
}
break;
case EDIT_BUTTON_SNAP_NEXT:
if( m_SnapDisplay.PrevSnapMode() )
OnSnapModeChange();
@@ -2668,6 +2671,23 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
}
SetDirty( true );
}
else if ( SM == SM_BackFromLabelChange )
{
RString sLabel = ScreenTextEntry::s_sLastAnswer;
if ( !m_pSong->m_Timing.DoesLabelExist(sLabel) )
{
sLabel.Replace("=", "_");
sLabel.Replace(",", "_");
m_pSong->m_Timing.SetLabelAtBeat( GAMESTATE->m_fSongBeat, sLabel );
SetDirty( true );
}
}
else if ( SM == SM_BackFromWarpChange )
{
float fWarp = StringToFloat( ScreenTextEntry::s_sLastAnswer );
m_pSong->m_Timing.SetWarpAtBeat( GAMESTATE->m_fSongBeat, fWarp );
SetDirty( true );
}
else if( SM == SM_BackFromBGChange )
{
HandleBGChangeChoice( (BGChangeChoice)ScreenMiniMenu::s_iLastRowCode, ScreenMiniMenu::s_viLastAnswers );
@@ -2867,8 +2887,8 @@ void ScreenEdit::HandleScreenMessage( const ScreenMessage SM )
if( (*s)->IsAutogen() )
continue;
// If the notedata has content, let it go.
// if( !(*s)->m_NoteData->IsEmpty() )
// continue;
if( !(*s)->GetNoteData().IsEmpty() )
continue;
// It's hard to say if these steps were saved to disk or not.
/*
if( !(*s)->GetSavedToDisk() )
@@ -2993,11 +3013,36 @@ static void ChangeArtistTranslit( const RString &sNew )
pSong->m_sArtistTranslit = sNew;
}
static void ChangeBeat0Offset( const RString &sNew )
{
GAMESTATE->m_pCurSong->m_Timing.m_fBeat0OffsetInSeconds = StringToFloat( sNew );
}
static void ChangeLastBeatHint( const RString &sNew )
{
GAMESTATE->m_pCurSong->m_fSpecifiedLastBeat = StringToFloat( sNew );
}
static void ChangePreviewStart( const RString &sNew )
{
GAMESTATE->m_pCurSong->m_fMusicSampleStartSeconds = StringToFloat( sNew );
}
static void ChangePreviewLength( const RString &sNew )
{
GAMESTATE->m_pCurSong->m_fMusicSampleLengthSeconds = StringToFloat( sNew );
}
static void ChangeMinBPM( const RString &sNew )
{
GAMESTATE->m_pCurSong->m_fSpecifiedBPMMin = StringToFloat( sNew );
}
static void ChangeMaxBPM( const RString &sNew )
{
GAMESTATE->m_pCurSong->m_fSpecifiedBPMMax = StringToFloat( sNew );
}
// End helper functions
static LocalizedString REVERT_LAST_SAVE ( "ScreenEdit", "Do you want to revert to your last save?" );
@@ -3188,7 +3233,13 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
g_SongInformation.rows[main_title_transliteration].SetOneUnthemedChoice( pSong->m_sMainTitleTranslit );
g_SongInformation.rows[sub_title_transliteration].SetOneUnthemedChoice( pSong->m_sSubTitleTranslit );
g_SongInformation.rows[artist_transliteration].SetOneUnthemedChoice( pSong->m_sArtistTranslit );
g_SongInformation.rows[beat_0_offset].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_Timing.m_fBeat0OffsetInSeconds) );
g_SongInformation.rows[last_beat_hint].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedLastBeat) );
g_SongInformation.rows[preview_start].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleStartSeconds) );
g_SongInformation.rows[preview_length].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fMusicSampleLengthSeconds) );
g_SongInformation.rows[display_bpm].iDefaultChoice = pSong->m_DisplayBPMType;
g_SongInformation.rows[min_bpm].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedBPMMin) );
g_SongInformation.rows[max_bpm].SetOneUnthemedChoice( ssprintf("%.5f", pSong->m_fSpecifiedBPMMax) );
EditMiniMenu( &g_SongInformation, SM_BackFromSongInformation );
}
@@ -3205,6 +3256,8 @@ void ScreenEdit::HandleMainMenuChoice( MainMenuChoice c, const vector<int> &iAns
g_TimingDataInformation.rows[time_signature_denominator].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTimeSignatureDenominatorAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[tickcount].SetOneUnthemedChoice( ssprintf("%d", pTime.GetTickcountAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[combo].SetOneUnthemedChoice( ssprintf("%d", pTime.GetComboAtBeat( fBeat ) ) );
g_TimingDataInformation.rows[label].SetOneUnthemedChoice( pTime.GetLabelAtBeat( fBeat ).c_str() );
g_TimingDataInformation.rows[warp].SetOneUnthemedChoice( ssprintf("%.5f", pTime.GetWarpAtBeat( fBeat ) ) );
EditMiniMenu( &g_TimingDataInformation, SM_BackFromTimingDataInformation );
}
@@ -3417,11 +3470,9 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
case tempo:
{
// This affects all steps.
const NoteData OldClipboard( m_Clipboard );
HandleAreaMenuChoice( cut );
AlterType at = (AlterType)iAnswers[c];
float fScale = -1;
switch( at )
{
DEFAULT_FAIL( at );
@@ -3432,31 +3483,18 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
case expand_3_2: fScale = 1.5f; break;
case expand_2x: fScale = 2; break;
}
int iStartIndex = m_NoteFieldEdit.m_iBeginMarker;
int iEndIndex = m_NoteFieldEdit.m_iEndMarker;
int iNewEndIndex = iEndIndex + lrintf( (iEndIndex - iStartIndex) * (fScale - 1) );
// scale currently editing notes
NoteDataUtil::ScaleRegion( m_NoteDataEdit, fScale, iStartIndex, iEndIndex );
// scale timing data
m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker, true );
switch( at )
{
DEFAULT_FAIL( at );
case compress_2x: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case compress_3_2: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case compress_4_3: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case expand_4_3: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case expand_3_2: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
case expand_2x: NoteDataUtil::Scale( m_Clipboard, fScale ); break;
}
int iOldClipboardRow = m_NoteFieldEdit.m_iEndMarker - m_NoteFieldEdit.m_iBeginMarker;
int iNewClipboardRow = lrintf( iOldClipboardRow * fScale );
int iDeltaRows = iNewClipboardRow - iOldClipboardRow;
int iNewClipboardEndRow = m_NoteFieldEdit.m_iBeginMarker + iNewClipboardRow;
if( iDeltaRows > 0 )
NoteDataUtil::InsertRows( m_NoteDataEdit, m_NoteFieldEdit.m_iBeginMarker, iDeltaRows );
else
NoteDataUtil::DeleteRows( m_NoteDataEdit, m_NoteFieldEdit.m_iBeginMarker, -iDeltaRows );
m_pSong->m_Timing.ScaleRegion( fScale, m_NoteFieldEdit.m_iBeginMarker, m_NoteFieldEdit.m_iEndMarker );
HandleAreaMenuChoice( paste_at_begin_marker );
// scale all other steps.
const vector<Steps*> sIter = m_pSong->GetAllSteps();
RString sTempStyle, sTempDiff;
for( unsigned i = 0; i < sIter.size(); i++ )
@@ -3476,12 +3514,8 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
sIter[i]->SetNoteData( ndTemp );
}
m_NoteFieldEdit.m_iEndMarker = iNewClipboardEndRow;
float fOldBPM = m_pSong->GetBPMAtBeat( NoteRowToBeat(m_NoteFieldEdit.m_iBeginMarker) );
float fNewBPM = fOldBPM * fScale;
m_pSong->m_Timing.SetBPMAtRow( m_NoteFieldEdit.m_iBeginMarker, fNewBPM );
m_pSong->m_Timing.SetBPMAtRow( iNewClipboardEndRow, fOldBPM );
m_NoteFieldEdit.m_iEndMarker = iNewEndIndex;
}
break;
case play:
@@ -3541,7 +3575,7 @@ void ScreenEdit::HandleAreaMenuChoice( AreaMenuChoice c, const vector<int> &iAns
// don't move the step from where it is, just move everything later
NoteDataUtil::InsertRows( m_NoteDataEdit, BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) );
m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopSeconds) );
m_pSong->m_Timing.InsertRows( BeatToNoteRow(GAMESTATE->m_fSongBeat) + 1, BeatToNoteRow(fStopBeats) );
}
break;
case undo:
@@ -3567,7 +3601,6 @@ void ScreenEdit::HandleStepsInformationChoice( StepsInformationChoice c, const v
switch( c )
{
case description:
// todo: Call a screen with class ScreenTextEntry instead. -aj
ScreenTextEntry::TextEntry(
SM_None,
ENTER_NEW_DESCRIPTION,
@@ -3611,16 +3644,19 @@ static LocalizedString ENTER_CREDIT ("ScreenEdit","Enter a new credit.");
static LocalizedString ENTER_MAIN_TITLE_TRANSLIT ("ScreenEdit","Enter a new main title transliteration.");
static LocalizedString ENTER_SUB_TITLE_TRANSLIT ("ScreenEdit","Enter a new sub title transliteration.");
static LocalizedString ENTER_ARTIST_TRANSLIT ("ScreenEdit","Enter a new artist transliteration.");
static LocalizedString ENTER_BEAT_0_OFFSET ("ScreenEdit","Enter the offset for the song.");
static LocalizedString ENTER_LAST_BEAT_HINT ("ScreenEdit","Enter a new last beat hint.");
static LocalizedString ENTER_PREVIEW_START ("ScreenEdit","Enter a new preview start.");
static LocalizedString ENTER_PREVIEW_LENGTH ("ScreenEdit","Enter a new preview length.");
static LocalizedString ENTER_MIN_BPM ("ScreenEdit","Enter a new min BPM.");
static LocalizedString ENTER_MAX_BPM ("ScreenEdit","Enter a new max BPM.");
void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vector<int> &iAnswers )
{
Song* pSong = GAMESTATE->m_pCurSong;
pSong->m_DisplayBPMType = static_cast<DisplayBPM>(iAnswers[display_bpm]);
// todo: Call a screen with class ScreenTextEntry instead.
// multiple times in this section, so I'm only saying it here. -aj
switch( c )
{
DEFAULT_FAIL(c);
case main_title:
ScreenTextEntry::TextEntry( SM_None, ENTER_MAIN_TITLE, pSong->m_sMainTitle, 100, NULL, ChangeMainTitle, NULL );
break;
@@ -3645,8 +3681,36 @@ void ScreenEdit::HandleSongInformationChoice( SongInformationChoice c, const vec
case artist_transliteration:
ScreenTextEntry::TextEntry( SM_None, ENTER_ARTIST_TRANSLIT, pSong->m_sArtistTranslit, 100, NULL, ChangeArtistTranslit, NULL );
break;
case beat_0_offset:
ScreenTextEntry::TextEntry( SM_None, ENTER_BEAT_0_OFFSET,
ssprintf("%.5f", pSong->m_Timing.m_fBeat0OffsetInSeconds), 20,
ScreenTextEntry::FloatValidate, ChangeBeat0Offset, NULL );
break;
case last_beat_hint:
ScreenTextEntry::TextEntry( SM_None, ENTER_LAST_BEAT_HINT, ssprintf("%.5f", pSong->m_fSpecifiedLastBeat), 20, ScreenTextEntry::FloatValidate, ChangeLastBeatHint, NULL );
ScreenTextEntry::TextEntry( SM_None, ENTER_LAST_BEAT_HINT,
ssprintf("%.5f", pSong->m_fSpecifiedLastBeat), 20,
ScreenTextEntry::FloatValidate, ChangeLastBeatHint, NULL );
break;
case preview_start:
ScreenTextEntry::TextEntry( SM_None, ENTER_PREVIEW_START,
ssprintf("%.5f", pSong->m_fMusicSampleStartSeconds), 20,
ScreenTextEntry::FloatValidate, ChangePreviewStart, NULL );
break;
case preview_length:
ScreenTextEntry::TextEntry( SM_None, ENTER_PREVIEW_LENGTH,
ssprintf("%.5f", pSong->m_fMusicSampleLengthSeconds), 20,
ScreenTextEntry::FloatValidate, ChangePreviewLength, NULL );
break;
case min_bpm:
ScreenTextEntry::TextEntry( SM_None, ENTER_MIN_BPM,
ssprintf("%.5f", pSong->m_fSpecifiedBPMMin), 20,
ScreenTextEntry::FloatValidate, ChangeMinBPM, NULL );
break;
case max_bpm:
ScreenTextEntry::TextEntry( SM_None, ENTER_MAX_BPM,
ssprintf("%.5f", pSong->m_fSpecifiedBPMMax), 20,
ScreenTextEntry::FloatValidate, ChangeMaxBPM, NULL );
break;
};
}
@@ -3657,13 +3721,14 @@ static LocalizedString ENTER_TIME_SIGNATURE_NUMERATOR_VALUE ( "ScreenEdit", "Ent
static LocalizedString ENTER_TIME_SIGNATURE_DENOMINATOR_VALUE ( "ScreenEdit", "Enter a new Time Signature denominator value." );
static LocalizedString ENTER_TICKCOUNT_VALUE ( "ScreenEdit", "Enter a new Tickcount value." );
static LocalizedString ENTER_COMBO_VALUE ( "ScreenEdit", "Enter a new Combo value." );
static LocalizedString ENTER_LABEL_VALUE ( "ScreenEdit", "Enter a new Label value." );
static LocalizedString ENTER_WARP_VALUE ( "ScreenEdit", "Enter a new Warp value." );
void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice c, const vector<int> &iAnswers )
{
switch( c )
{
DEFAULT_FAIL( c );
case bpm:
// todo: Call a screen with class ScreenTextEntry instead. -aj
ScreenTextEntry::TextEntry(
SM_BackFromBPMChange,
ENTER_BPM_VALUE,
@@ -3672,7 +3737,6 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
);
break;
case stop:
// todo: Call a screen with class ScreenTextEntry instead. -aj
ScreenTextEntry::TextEntry(
SM_BackFromStopChange,
ENTER_STOP_VALUE,
@@ -3681,7 +3745,6 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
);
break;
case delay:
// todo: Call a screen with class ScreenTextEntry instead. -aj
ScreenTextEntry::TextEntry(
SM_BackFromDelayChange,
ENTER_DELAY_VALUE,
@@ -3721,6 +3784,22 @@ void ScreenEdit::HandleTimingDataInformationChoice( TimingDataInformationChoice
4
);
break;
case label:
ScreenTextEntry::TextEntry(
SM_BackFromLabelChange,
ENTER_LABEL_VALUE,
ssprintf( "%s", m_pSong->m_Timing.GetLabelAtBeat( GAMESTATE->m_fSongBeat ).c_str() ),
64
);
break;
case warp:
ScreenTextEntry::TextEntry(
SM_BackFromWarpChange,
ENTER_WARP_VALUE,
ssprintf( "%.4f", m_pSong->m_Timing.GetWarpAtRow( BeatToNoteRow(GAMESTATE->m_fSongBeat) ) ),
10
);
break;
}
}
+24 -11
View File
@@ -24,12 +24,13 @@
const int NUM_EDIT_BUTTON_COLUMNS = 10;
struct MenuDef;
/** @brief What is going on with the Editor? */
enum EditState
{
STATE_EDITING,
STATE_RECORDING,
STATE_RECORDING_PAUSED,
STATE_PLAYING,
STATE_EDITING, /**< The person is making adjustments to the Steps. */
STATE_RECORDING, /**< The person is recording some Steps live. */
STATE_RECORDING_PAUSED, /**< The person has temporarily paused the recording of Steps. */
STATE_PLAYING, /**< The person is just trying out the Steps. */
NUM_EditState,
EditState_Invalid
};
@@ -56,8 +57,8 @@ enum EditButton
EDIT_BUTTON_REMOVE_NOTE,
// These are modifiers to change the present tap note.
EDIT_BUTTON_CYCLE_TAP_LEFT,
EDIT_BUTTON_CYCLE_TAP_RIGHT,
EDIT_BUTTON_CYCLE_TAP_LEFT, /**< Rotate the available tap notes once to the "left". */
EDIT_BUTTON_CYCLE_TAP_RIGHT, /**< Rotate the available tap notes once to the "right". */
EDIT_BUTTON_SCROLL_UP_LINE,
EDIT_BUTTON_SCROLL_UP_PAGE,
@@ -70,6 +71,9 @@ enum EditButton
EDIT_BUTTON_SCROLL_NEXT,
EDIT_BUTTON_SCROLL_PREV,
EDIT_BUTTON_LABEL_NEXT,
EDIT_BUTTON_LABEL_PREV,
// These are modifiers to EDIT_BUTTON_SCROLL_*.
EDIT_BUTTON_SCROLL_SELECT,
@@ -127,13 +131,13 @@ enum EditButton
// This modifies offset, BPM, and stop segment changes.
EDIT_BUTTON_ADJUST_FINE,
EDIT_BUTTON_SAVE,
EDIT_BUTTON_SAVE, /**< Save the present changes into the chart. */
EDIT_BUTTON_UNDO,
EDIT_BUTTON_UNDO, /**< Undo a recent change. */
EDIT_BUTTON_ADD_COURSE_MODS,
EDIT_BUTTON_SWITCH_PLAYERS,
EDIT_BUTTON_SWITCH_PLAYERS, /**< Allow entering notes for a different Player. */
NUM_EditButton, // leave this at the end
EditButton_Invalid
@@ -251,12 +255,17 @@ protected:
// The location we were at when shift was pressed, or -1 when shift isn't pressed:
int m_iShiftAnchor;
/** @brief The NoteData that has been cut or copied. */
NoteData m_Clipboard;
bool m_bHasUndo;
// TODO: convert this into a stack of NoteData objs for multi-state undo -aj
/**
* @brief The NoteData as it once just one action prior.
*
* TODO: Convert this into a stack or vector of NoteData to allow multiple undos. -aj
* TODO: Look into a redo option. -aj */
NoteData m_Undo;
// TODO: also maybe have a redo stack/option -aj
/** @brief Has the NoteData been changed such that a user should be prompted to save? */
bool m_bDirty;
RageSound m_soundAddNote;
@@ -441,7 +450,10 @@ public:
main_title_transliteration,
sub_title_transliteration,
artist_transliteration,
beat_0_offset,
last_beat_hint,
preview_start,
preview_length,
display_bpm,
min_bpm,
max_bpm,
@@ -459,6 +471,7 @@ public:
time_signature_denominator,
tickcount,
combo,
label,
warp,
NUM_TIMING_DATA_INFORMATION_CHOICES
};
+1 -1
View File
@@ -5,7 +5,7 @@
#include "Preference.h"
#include "RageLog.h"
#include "FileDownload.h"
#include "jsoncpp/include/json/value.h"
#include "../extern/jsoncpp/include/json/value.h"
#include "JsonUtil.h"
#include "SpecialFiles.h"
class Song;
+1 -2
View File
@@ -1,11 +1,10 @@
/* ScreenJukebox - Plays whole songs continuously. */
#ifndef ScreenJukebox_H
#define ScreenJukebox_H
#include "ScreenGameplayNormal.h"
class CourseEntry;
/** @brief Plays whole songs continuously. */
class ScreenJukebox : public ScreenGameplayNormal
{
public:
+16 -4
View File
@@ -26,7 +26,9 @@ InputMode StringToInputMode( const RString& str );
/** @brief A custom foreach loop for the player options for each player. */
#define FOREACH_OptionsPlayer( pn ) \
for( PlayerNumber pn=GetNextHumanPlayer((PlayerNumber)-1); pn!=PLAYER_INVALID && (m_InputMode==INPUTMODE_INDIVIDUAL || pn==0); pn=GetNextHumanPlayer(pn) )
for( PlayerNumber pn=GetNextHumanPlayer((PlayerNumber)-1); \
pn!=PLAYER_INVALID && (m_InputMode==INPUTMODE_INDIVIDUAL || pn==0); \
pn=GetNextHumanPlayer(pn) )
/** @brief A grid of options; the selected option is drawn with a highlight rectangle. */
class ScreenOptions : public ScreenWithMenuElements
@@ -53,7 +55,8 @@ protected:
virtual void ExportOptions( int iRow, const vector<PlayerNumber> &vpns ) = 0;
void RestartOptions();
void GetWidthXY( PlayerNumber pn, int iRow, int iChoiceOnRow, int &iWidthOut, int &iXOut, int &iYOut ) const;
void GetWidthXY( PlayerNumber pn, int iRow, int iChoiceOnRow,
int &iWidthOut, int &iXOut, int &iYOut ) const;
RString GetExplanationText( int iRow ) const;
void RefreshIcons( int iRow, PlayerNumber pn );
void PositionCursor( PlayerNumber pn );
@@ -67,10 +70,18 @@ protected:
void ChangeValueInRowRelative( int iRow, PlayerNumber pn, int iDelta, bool bRepeat );
void ChangeValueInRowAbsolute( int iRow, PlayerNumber pn, int iChoiceIndex, bool bRepeat );
virtual void AfterChangeValueInRow( int iRow, PlayerNumber pn ); // override this to detect when the value in a row has changed
/**
* @brief Perform an action after a row has changed its value.
*
* Override this to detect when the value in a row has changed. */
virtual void AfterChangeValueInRow( int iRow, PlayerNumber pn );
bool MoveRowRelative( PlayerNumber pn, int iDir, bool bRepeat );
bool MoveRowAbsolute( PlayerNumber pn, int iRow );
virtual void AfterChangeRow( PlayerNumber pn ); // override this to detect when the row has changed
/**
* @brief Perform an action after moving to a new row.
*
* Override this to detect when the row has changed. */
virtual void AfterChangeRow( PlayerNumber pn );
virtual void AfterChangeValueOrRow( PlayerNumber pn );
virtual void MenuBack( const InputEventPlus &input );
@@ -107,6 +118,7 @@ protected: // derived classes need access to these
bool m_bWasOnExit[NUM_PLAYERS];
/** @brief True if at least one player pressed Start after selecting the song.
*
* TRICKY: People hold Start to get to PlayerOptions, then the repeat events
* cause them to zip to the bottom. So, ignore Start repeat events until
* we've seen one first pressed event. */
+2 -3
View File
@@ -264,7 +264,7 @@ static void DisplayResolutionChoices( vector<RString> &out )
}
}
static void Theme( int &sel, bool ToSel, const ConfOption *pConfOption )
static void RequestedTheme( int &sel, bool ToSel, const ConfOption *pConfOption )
{
vector<RString> choices;
pConfOption->MakeOptionsList( choices );
@@ -653,7 +653,7 @@ static void InitializeConfOptions()
// Appearance options
ADD( ConfOption( "Language", Language, LanguageChoices ) );
ADD( ConfOption( "Theme", Theme, ThemeChoices ) );
ADD( ConfOption( "Theme", RequestedTheme, ThemeChoices ) );
g_ConfOptions.back().m_iEffects = OPT_APPLY_THEME;
ADD( ConfOption( "Announcer", Announcer, AnnouncerChoices ) );
@@ -718,7 +718,6 @@ static void InitializeConfOptions()
g_ConfOptions.back().m_sPrefName = "SongsPerPlay";
ADD( ConfOption( "EventMode", MovePref<bool>, "Off","On (recommended)" ) );
ADD( ConfOption( "ScoringType", MovePref<ScoringType>, "New","Old","Custom" ) );
ADD( ConfOption( "TimingWindowScale", TimingWindowScale, "|1","|2","|3","|4","|5","|6","|7","|8","Justice" ) );
ADD( ConfOption( "LifeDifficulty", LifeDifficulty, "|1.2","|1.0","|0.8","|0.6","|0.4","|0.33","|0.25" ) );
g_ConfOptions.back().m_sPrefName = "LifeDifficultyScale";
+5 -3
View File
@@ -1,5 +1,3 @@
/* ScreenTestFonts - Display and test fonts. */
#ifndef SCREEN_TEST_FONTS_H
#define SCREEN_TEST_FONTS_H
@@ -7,6 +5,7 @@
#include "BitmapText.h"
#include "Quad.h"
/** @brief Display and test fonts. */
class ScreenTestFonts: public Screen
{
public:
@@ -20,7 +19,10 @@ private:
void SetText( RString sText );
void SetFont( RString sFont );
RString m_sCurText, m_sFont;
/** @brief The current text to display. */
RString m_sCurText;
/** @brief The current font in use. */
RString m_sFont;
BitmapText txt, font;
Quad Vline, Hline;
};
+8 -1
View File
@@ -41,7 +41,7 @@
* @brief The internal version of the cache for StepMania.
*
* Increment this value to invalidate the current cache. */
const int FILE_CACHE_VERSION = 168;
const int FILE_CACHE_VERSION = 170;
/** @brief How long does a song sample last by default? */
const float DEFAULT_MUSIC_SAMPLE_LENGTH = 12.f;
@@ -802,6 +802,13 @@ void Song::TidyUpData()
ComboSegment seg(0, 1);
m_Timing.m_ComboSegments.push_back( seg );
}
// Have a default label segment just in case.
if( m_Timing.m_LabelSegments.empty() )
{
LabelSegment seg(0, "Song Start");
m_Timing.m_LabelSegments.push_back( seg );
}
}
void Song::TranslateTitles()
+1 -1
View File
@@ -17,7 +17,7 @@ struct lua_State;
struct BackgroundChange;
/** @brief The version of the .ssc file format. */
const static float STEPFILE_VERSION_NUMBER = 0.57f;
const static float STEPFILE_VERSION_NUMBER = 0.59f;
/** @brief How many edits for this song can each profile have? */
const int MAX_EDITS_PER_SONG_PER_PROFILE = 5;
+7 -1
View File
@@ -99,7 +99,13 @@ private:
EffectMode m_EffectMode;
bool m_bUsingCustomTexCoords;
bool m_bSkipNextUpdate;
float m_CustomTexCoords[8]; // (x,y) * 4: top left, bottom left, bottom right, top right
/**
* @brief Set up the coordinates for the texture.
*
* The first two parameters are the (x, y) coordinates for the top left.
* The remaining six are for the (x, y) coordinates for bottom left,
* bottom right, and top right respectively. */
float m_CustomTexCoords[8];
// Remembered clipped dimensions are applied on Load().
// -1 means no remembered dimensions;
+9 -6
View File
@@ -25,7 +25,7 @@
Name="VCCLCompilerTool"
AdditionalOptions="/EHa"
Optimization="0"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;ffmpeg\include&quot;;est;&quot;..\extern\glew-1.5.8\include&quot;"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;..\extern\lua-5.1\src&quot;;ffmpeg\modern_working\include;BaseClasses;&quot;..\extern\jsoncpp\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;;..\extern\pcre;&quot;..\extern\mad-0.15.1b&quot;;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis"
PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,WINDOWS,DEBUG,GLEW_STATIC"
ExceptionHandling="FALSE"
BasicRuntimeChecks="3"
@@ -40,7 +40,8 @@
BrowseInformation="0"
WarningLevel="4"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"/>
DebugInformationFormat="4"
DisableSpecificWarnings="4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
@@ -109,7 +110,7 @@ cl /Zl /nologo /c verstub.cpp /Fo&quot;$(IntDir)&quot;\
FavorSizeOrSpeed="2"
OptimizeForProcessor="2"
OptimizeForWindowsApplication="TRUE"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;ffmpeg\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;..\extern\lua-5.1\src&quot;;ffmpeg\modern_working\include;BaseClasses;&quot;..\extern\jsoncpp\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;;..\extern\pcre;&quot;..\extern\mad-0.15.1b&quot;;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis"
PreprocessorDefinitions="WIN32,NDEBUG,_WINDOWS,WINDOWS,RELEASE,GLEW_STATIC"
StringPooling="TRUE"
MinimalRebuild="FALSE"
@@ -127,7 +128,8 @@ cl /Zl /nologo /c verstub.cpp /Fo&quot;$(IntDir)&quot;\
BrowseInformation="0"
WarningLevel="4"
SuppressStartupBanner="TRUE"
DebugInformationFormat="3"/>
DebugInformationFormat="3"
DisableSpecificWarnings="4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
@@ -190,7 +192,7 @@ cl /Zl /nologo /c verstub.cpp /Fo&quot;$(IntDir)&quot;\
Name="VCCLCompilerTool"
AdditionalOptions="/EHa"
Optimization="0"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;ffmpeg\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;..\extern\lua-5.1\src&quot;;ffmpeg\modern_working\include;BaseClasses;&quot;..\extern\jsoncpp\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;;..\extern\pcre;&quot;..\extern\mad-0.15.1b&quot;;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis"
PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,WINDOWS,DEBUG,GLEW_STATIC"
ExceptionHandling="FALSE"
BasicRuntimeChecks="0"
@@ -205,7 +207,8 @@ cl /Zl /nologo /c verstub.cpp /Fo&quot;$(IntDir)&quot;\
BrowseInformation="0"
WarningLevel="4"
SuppressStartupBanner="TRUE"
DebugInformationFormat="4"/>
DebugInformationFormat="4"
DisableSpecificWarnings="4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996"/>
<Tool
Name="VCCustomBuildTool"/>
<Tool
+6 -3
View File
@@ -49,7 +49,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;lua-5.1\include&quot;;ffmpeg\include;BaseClasses;&quot;..\extern\glew-1.5.8\include&quot;"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;..\extern\lua-5.1\src&quot;;ffmpeg\modern_working\include;BaseClasses;&quot;..\extern\jsoncpp\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;;..\extern\pcre;&quot;..\extern\mad-0.15.1b&quot;;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis"
PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,WINDOWS,DEBUG,_CRT_SECURE_NO_DEPRECATE,GLEW_STATIC"
ExceptionHandling="0"
BasicRuntimeChecks="3"
@@ -64,6 +64,7 @@
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -156,7 +157,7 @@
InlineFunctionExpansion="2"
EnableIntrinsicFunctions="true"
FavorSizeOrSpeed="2"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;lua-5.1\include&quot;;ffmpeg\include;BaseClasses;&quot;..\extern\glew-1.5.8\include&quot;"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;..\extern\lua-5.1\src&quot;;ffmpeg\modern_working\include;BaseClasses;&quot;..\extern\jsoncpp\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;;..\extern\pcre;&quot;..\extern\mad-0.15.1b&quot;;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis"
PreprocessorDefinitions="WIN32,NDEBUG,_WINDOWS,WINDOWS,RELEASE,_CRT_SECURE_NO_DEPRECATE,GLEW_STATIC"
StringPooling="true"
MinimalRebuild="false"
@@ -174,6 +175,7 @@
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="3"
DisableSpecificWarnings="4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
@@ -261,7 +263,7 @@
<Tool
Name="VCCLCompilerTool"
Optimization="0"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;lua-5.1\include&quot;;ffmpeg\include;BaseClasses;&quot;..\extern\glew-1.5.8\include&quot;"
AdditionalIncludeDirectories=".;vorbis;libjpeg;&quot;..\extern\lua-5.1\src&quot;;ffmpeg\modern_working\include;BaseClasses;&quot;..\extern\jsoncpp\include&quot;;&quot;..\extern\glew-1.5.8\include&quot;;..\extern\pcre;&quot;..\extern\mad-0.15.1b&quot;;..\extern\libpng;..\extern\libjpeg;..\extern\zlib;..\extern\vorbis"
PreprocessorDefinitions="WIN32,_DEBUG,_WINDOWS,WINDOWS,DEBUG,_CRT_SECURE_NO_DEPRECATE,GLEW_STATIC"
ExceptionHandling="0"
BasicRuntimeChecks="0"
@@ -276,6 +278,7 @@
WarningLevel="4"
SuppressStartupBanner="true"
DebugInformationFormat="4"
DisableSpecificWarnings="4063;4100;4127;4201;4244;4275;4355;4505;4512;4702;4786;4996"
/>
<Tool
Name="VCManagedResourceCompilerTool"
+1510 -1506
View File
File diff suppressed because it is too large Load Diff
+139 -6
View File
@@ -57,6 +57,11 @@ void TimingData::AddComboSegment( const ComboSegment &seg )
m_ComboSegments.insert( upper_bound(m_ComboSegments.begin(), m_ComboSegments.end(), seg), seg );
}
void TimingData::AddLabelSegment( const LabelSegment &seg )
{
m_LabelSegments.insert( upper_bound(m_LabelSegments.begin(), m_LabelSegments.end(), seg), seg );
}
/* Change an existing BPM segment, merge identical segments together or insert a new one. */
void TimingData::SetBPMAtRow( int iNoteRow, float fBPM )
{
@@ -218,6 +223,27 @@ void TimingData::SetComboAtRow( int iRow, int iCombo )
}
}
void TimingData::SetLabelAtRow( int iRow, const RString sLabel )
{
unsigned i;
for( i=0; i<m_LabelSegments.size(); i++ )
if( m_LabelSegments[i].m_iStartRow >= iRow )
break;
if( i == m_LabelSegments.size() || m_LabelSegments[i].m_iStartRow != iRow )
{
if( i == 0 || m_LabelSegments[i-1].m_sLabel != sLabel )
AddLabelSegment( LabelSegment(iRow, sLabel ) );
}
else
{
if( i > 0 && ( m_LabelSegments[i-1].m_sLabel == sLabel || sLabel == "" ) )
m_LabelSegments.erase( m_LabelSegments.begin()+i, m_LabelSegments.begin()+i+1 );
else
m_LabelSegments[i].m_sLabel = sLabel;
}
}
float TimingData::GetStopAtRow( int iNoteRow, bool bDelay ) const
{
for( unsigned i=0; i<m_StopSegments.size(); i++ )
@@ -246,6 +272,11 @@ int TimingData::GetComboAtRow( int iNoteRow ) const
return m_ComboSegments[GetComboSegmentIndexAtRow( iNoteRow )].m_iCombo;
}
RString TimingData::GetLabelAtRow( int iRow ) const
{
return m_LabelSegments[GetLabelSegmentIndexAtRow( iRow )].m_sLabel;
}
float TimingData::GetWarpAtRow( int iWarpRow ) const
{
for( unsigned i=0; i<m_WarpSegments.size(); i++ )
@@ -383,6 +414,18 @@ int TimingData::GetComboSegmentIndexAtRow( int iRow ) const
return static_cast<int>(i);
}
int TimingData::GetLabelSegmentIndexAtRow( int iRow ) const
{
unsigned i;
for( i=0; i<m_LabelSegments.size()-1; i++ )
{
const LabelSegment& s = m_LabelSegments[i+1];
if( s.m_iStartRow > iRow )
break;
}
return static_cast<int>(i);
}
BPMSegment& TimingData::GetBPMSegmentAtRow( int iNoteRow )
{
static BPMSegment empty;
@@ -421,6 +464,15 @@ ComboSegment& TimingData::GetComboSegmentAtRow( int iRow )
return m_ComboSegments[i];
}
LabelSegment& TimingData::GetLabelSegmentAtRow( int iRow )
{
unsigned i;
for( i=0; i<m_LabelSegments.size()-1; i++ )
if( m_LabelSegments[i+1].m_iStartRow > iRow )
break;
return m_LabelSegments[i];
}
StopSegment& TimingData::GetStopSegmentAtRow( int iNoteRow, bool bDelay )
{
static StopSegment empty;
@@ -443,11 +495,11 @@ WarpSegment& TimingData::GetWarpSegmentAtRow( int iRow )
int TimingData::GetTickcountSegmentIndexAtRow( int iRow ) const
{
int i;
for (i=0; i < (int)(m_TickcountSegments.size()) - 1; i++ )
unsigned i;
for (i=0; i < m_TickcountSegments.size() - 1; i++ )
if( m_TickcountSegments[i+1].m_iStartRow > iRow )
break;
return i;
return static_cast<int>(i);
}
TickcountSegment& TimingData::GetTickcountSegmentAtRow( int iRow )
@@ -465,6 +517,43 @@ int TimingData::GetTickcountAtRow( int iRow ) const
return m_TickcountSegments[GetTickcountSegmentIndexAtRow( iRow )].m_iTicks;
}
float TimingData::GetPreviousLabelSegmentBeatAtRow( int iRow ) const
{
float backup = -1;
for (unsigned i = 0; i < m_LabelSegments.size(); i++ )
{
if( m_LabelSegments[i].m_iStartRow >= iRow )
{
break;
}
backup = NoteRowToBeat(m_LabelSegments[i].m_iStartRow);
}
return (backup > -1) ? backup : NoteRowToBeat(iRow);
}
float TimingData::GetNextLabelSegmentBeatAtRow( int iRow ) const
{
for (unsigned i = 0; i < m_LabelSegments.size(); i++ )
{
if( m_LabelSegments[i].m_iStartRow <= iRow )
{
continue;
}
return NoteRowToBeat(m_LabelSegments[i].m_iStartRow);
}
return NoteRowToBeat(iRow);
}
bool TimingData::DoesLabelExist( RString sLabel ) const
{
FOREACH_CONST( LabelSegment, m_LabelSegments, seg )
{
if( seg->m_sLabel == sLabel )
return true;
}
return false;
}
void TimingData::GetBeatAndBPSFromElapsedTime( float fElapsedTime, float &fBeatOut, float &fBPSOut, bool &bFreezeOut, bool &bDelayOut, int &iWarpBeginOut, float &fWarpLengthOut ) const
{
fElapsedTime += PREFSMAN->m_fGlobalOffsetSeconds;
@@ -581,9 +670,6 @@ void TimingData::GetBeatAndBPSFromElapsedTimeNoOffset( float fElapsedTime, float
}
float TimingData::GetElapsedTimeFromBeat( float fBeat ) const
{
return TimingData::GetElapsedTimeFromBeatNoOffset( fBeat ) - PREFSMAN->m_fGlobalOffsetSeconds;
@@ -742,6 +828,17 @@ void TimingData::ScaleRegion( float fScale, int iStartIndex, int iEndIndex, bool
m_ComboSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex;
}
for ( unsigned i = 0; i < m_LabelSegments.size(); i++ )
{
const int iSegStart = m_LabelSegments[i].m_iStartRow;
if( iSegStart < iStartIndex )
continue;
else if( iSegStart > iEndIndex )
m_LabelSegments[i].m_iStartRow += lrintf( (iEndIndex - iStartIndex) * (fScale - 1) );
else
m_LabelSegments[i].m_iStartRow = lrintf( (iSegStart - iStartIndex) * fScale ) + iStartIndex;
}
// adjust BPM changes to preserve timing
if( bAdjustBPM )
{
@@ -819,6 +916,13 @@ void TimingData::InsertRows( int iStartRow, int iRowsToAdd )
continue;
comb.m_iStartRow += iRowsToAdd;
}
for( unsigned i = 0; i < m_LabelSegments.size(); i++ )
{
LabelSegment &labl = m_LabelSegments[i];
if( labl.m_iStartRow < iStartRow )
continue;
labl.m_iStartRow += iRowsToAdd;
}
if( iStartRow == 0 )
{
@@ -960,6 +1064,22 @@ void TimingData::DeleteRows( int iStartRow, int iRowsToDelete )
// After deleted region:
comb.m_iStartRow -= iRowsToDelete;
}
for( unsigned i = 0; i < m_LabelSegments.size(); i++ )
{
LabelSegment &labl = m_LabelSegments[i];
if( labl.m_iStartRow < iStartRow )
continue;
if( labl.m_iStartRow < iStartRow+iRowsToDelete )
{
m_LabelSegments.erase( m_LabelSegments.begin()+i, m_LabelSegments.begin()+i+1 );
--i;
continue;
}
labl.m_iStartRow -= iRowsToDelete;
}
this->SetBPMAtRow( iStartRow, fNewBPM );
}
@@ -1065,6 +1185,18 @@ public:
LuaHelpers::CreateTableFromArray(vBPMs, L);
return 1;
}
static int GetLabels( T* p, lua_State *L )
{
vector<RString> vLabels;
FOREACH_CONST( LabelSegment, p->m_LabelSegments, seg )
{
const float fStartRow = NoteRowToBeat(seg->m_iStartRow);
const RString sLabel = seg->m_sLabel;
vLabels.push_back( ssprintf("%f=%s", fStartRow, sLabel.c_str()) );
}
LuaHelpers::CreateTableFromArray(vLabels, L);
return 1;
}
static int GetBPMsAndTimes( T* p, lua_State *L )
{
vector<RString> vBPMs;
@@ -1103,6 +1235,7 @@ public:
ADD_METHOD( GetStops );
ADD_METHOD( GetDelays );
ADD_METHOD( GetBPMs );
ADD_METHOD( GetLabels );
ADD_METHOD( GetBPMsAndTimes );
ADD_METHOD( GetActualBPM );
ADD_METHOD( HasNegativeBPMs );
+176
View File
@@ -564,6 +564,90 @@ struct ComboSegment
bool operator>=( const ComboSegment &other ) const { return !operator<(other); }
};
/**
* @brief Identifies when a chart is entering a different section.
*
* This is meant for helping to identify different sections of a chart
* versus relying on measures and beats alone.
*/
struct LabelSegment
{
/**
* @brief Creates a simple Label Segment with default values.
*
* It is best to override the values as soon as possible.
*/
LabelSegment() : m_iStartRow(-1), m_sLabel("") { }
/**
* @brief Creates a Label Segment with the specified starting row and label.
* @param s the starting row of this segment.
* @param l the label for this section.
*/
LabelSegment( int s, RString l ): m_iStartRow(max(0, s)),
m_sLabel(l) {}
/**
* @brief Creates a Label Segment with the specified starting beat and label.
* @param s the starting beat of this segment.
* @param l the label for this section.
*/
LabelSegment( float s, RString l ):
m_iStartRow(max(0, BeatToNoteRow(s))), m_sLabel(l) {}
/**
* @brief The row in which the ComboSegment activates.
*/
int m_iStartRow;
/**
* @brief The label/section name for this point.
*/
RString m_sLabel;
/**
* @brief Compares two LabelSegments to see if they are equal to each other.
* @param other the other LabelSegment to compare to.
* @return the equality of the two segments.
*/
bool operator==( const LabelSegment &other ) const
{
COMPARE( m_iStartRow );
COMPARE( m_sLabel );
return true;
}
/**
* @brief Compares two LabelSegments to see if they are not equal to each other.
* @param other the other LabelSegment to compare to.
* @return the inequality of the two segments.
*/
bool operator!=( const LabelSegment &other ) const { return !operator==(other); }
/**
* @brief Compares two LabelSegments to see if one is less than the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is less than the second.
*/
bool operator<( const LabelSegment &other ) const { return m_iStartRow < other.m_iStartRow; }
/**
* @brief Compares two LabelSegments to see if one is less than or equal to the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is less or equal to than the second.
*/
bool operator<=( const LabelSegment &other ) const
{
return ( operator<(other) || operator==(other) );
}
/**
* @brief Compares two LabelSegments to see if one is greater than the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is greater than the second.
*/
bool operator>( const LabelSegment &other ) const { return !operator<=(other); }
/**
* @brief Compares two LabelSegments to see if one is greater than or equal to the other.
* @param other the other LabelSegment to compare to.
* @return the truth/falsehood of if the first is greater than or equal to the second.
*/
bool operator>=( const LabelSegment &other ) const { return !operator<(other); }
};
/**
* @brief Holds data for translating beats<->seconds.
*/
@@ -1064,6 +1148,92 @@ public:
*/
void AddComboSegment( const ComboSegment &seg );
/**
* @brief Retrieve the Label at the given row.
* @param iNoteRow the row in question.
* @return the Label.
*/
RString GetLabelAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the Label at the given beat.
* @param fBeat the beat in question.
* @return the Label.
*/
RString GetLabelAtBeat( float fBeat ) const { return GetLabelAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Set the row to have the new Label.
* @param iNoteRow the row to have the new Label.
* @param sLabel the Label.
*/
void SetLabelAtRow( int iNoteRow, const RString sLabel );
/**
* @brief Set the beat to have the new Label.
* @param fBeat the beat to have the new Label.
* @param sLabel the Label.
*/
void SetLabelAtBeat( float fBeat, const RString sLabel ) { SetLabelAtRow( BeatToNoteRow( fBeat ), sLabel ); }
/**
* @brief Retrieve the LabelSegment at the specified row.
* @param iNoteRow the row that has a LabelSegment.
* @return the LabelSegment in question.
*/
LabelSegment& GetLabelSegmentAtRow( int iNoteRow );
/**
* @brief Retrieve the LabelSegment at the specified beat.
* @param fBeat the beat that has a LabelSegment.
* @return the LabelSegment in question.
*/
LabelSegment& GetLabelSegmentAtBeat( float fBeat ) { return GetLabelSegmentAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Retrieve the index of the LabelSegments at the specified row.
* @param iNoteRow the row that has a LabelSegment.
* @return the LabelSegment's index in question.
*/
int GetLabelSegmentIndexAtRow( int iNoteRow ) const;
/**
* @brief Retrieve the index of the LabelSegments at the specified beat.
* @param fBeat the beat that has a LabelSegment.
* @return the LabelSegment's index in question.
*/
int GetLabelSegmentIndexAtBeat( float fBeat ) const { return GetLabelSegmentIndexAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Add the LabelSegment to the TimingData.
* @param seg the new LabelSegment.
*/
void AddLabelSegment( const LabelSegment &seg );
/**
* @brief Retrieve the previous beat that contains a LabelSegment.
* @param iRow the present row.
* @return the previous beat with a LabelSegment, or fBeat if there is none prior.
*/
float GetPreviousLabelSegmentBeatAtRow( int iRow ) const;
/**
* @brief Retrieve the previous beat that contains a LabelSegment.
* @param fBeat the present beat.
* @return the previous beat with a LabelSegment, or fBeat if there is none prior.
*/
float GetPreviousLabelSegmentBeatAtBeat( float fBeat ) const { return GetPreviousLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); }
/**
* @brief Determine if the requisite label already exists.
* @param sLabel the label to check.
* @return true if it exists, false otherwise. */
bool DoesLabelExist( RString sLabel ) const;
/**
* @brief Retrieve the next beat that contains a LabelSegment.
* @param iRow the present row.
* @return the next beat with a LabelSegment, or fBeat if there is none ahead.
*/
float GetNextLabelSegmentBeatAtRow( int iRow ) const;
/**
* @brief Retrieve the previous beat that contains a LabelSegment.
* @param fBeat the present beat.
* @return the next beat with a LabelSegment, or fBeat if there is none ahead.
*/
float GetNextLabelSegmentBeatAtBeat( float fBeat ) const { return GetNextLabelSegmentBeatAtRow( BeatToNoteRow(fBeat) ); }
void MultiplyBPMInBeatRange( int iStartIndex, int iEndIndex, float fFactor );
void NoteRowToMeasureAndBeat( int iNoteRow, int &iMeasureIndexOut, int &iBeatIndexOut, int &iRowsRemainder ) const;
@@ -1131,6 +1301,8 @@ public:
COMPARE( m_ComboSegments.size() );
for( unsigned i=0; i<m_ComboSegments.size(); i++ )
COMPARE( m_ComboSegments[i] );
for( unsigned i=0; i<m_LabelSegments.size(); i++ )
COMPARE( m_LabelSegments[i] );
COMPARE( m_fBeat0OffsetInSeconds );
return true;
}
@@ -1178,6 +1350,10 @@ public:
* @brief The collection of ComboSegments.
*/
vector<ComboSegment> m_ComboSegments;
/**
* @brief The collection of LabelSegments.
*/
vector<LabelSegment> m_LabelSegments;
/**
* @brief The initial offset of a song.
*/
@@ -23,7 +23,7 @@ namespace avcodec
// #define HAVE_THEORAEXP
#if !defined(HAVE_THEORAEXP)
#include <theora/theora.h>
#include <../extern/vorbis/theora/theora.h>
#if defined(_MSC_VER)
#pragma comment(lib, OGG_LIB_DIR "ogg_static.lib")
+25 -19
View File
@@ -21,25 +21,31 @@
#define snprintf _snprintf // Unsure if this goes with __MINGW32__ right now.
#pragma warning (disable : 4275) // non dll-interface class 'stdext::exception' used as base for dll-interface class 'std::bad_cast', bug in VC <exception> when exceptions disabled
#pragma warning (disable : 4201) // nonstandard extension used : nameless struct/union (Windows headers do this)
#pragma warning (disable : 4786) // turn off broken debugger warning
#pragma warning (disable : 4512) // assignment operator could not be generated (so?)
/* "unreachable code". This warning crops up in incorrect places (end of do ... while(0)
* blocks, try/catch blocks), and I've never found it to be useful. */
#pragma warning (disable : 4702) // assignment operator could not be generated (so?)
// "unreferenced formal parameter"; we *want* that in many cases
#pragma warning (disable : 4100)
/* "case 'aaa' is not a valid value for switch of enum 'bbb'
* Actually, this is a valid warning, but we do it all over the
* place, eg. with ScreenMessages. Those should be fixed, but later. XXX */
#pragma warning (disable : 4063)
#pragma warning (disable : 4127)
#pragma warning (disable : 4786) /* VC6: identifier was truncated to '255' characters in the debug information */
#pragma warning (disable : 4505) // removed unferenced local function from integer.cpp & algebra.h
#pragma warning (disable : 4244) // converting of data = possible data loss. (This pragma should eventually go away)
#pragma warning (disable : 4355) // 'this' : used in base member initializer list
/*
The following warnings are disabled in all builds.
Enable them in the project file at your peril (or if you feel like
learning of many pedantic style warnings and want to fix them).
C2475: non dll-interface class 'stdext::exception' used as base for dll-interface class 'std::bad_cast', bug in VC <exception> when exceptions disabled
C4201: nonstandard extension used : nameless struct/union (Windows headers do this)
C4786: turn off broken debugger warning
C4512: assignment operator could not be generated (so?)
"unreachable code". This warning crops up in incorrect places (end of do ... while(0)
blocks, try/catch blocks), and I've never found it to be useful.
C4702: assignment operator could not be generated (so?)
// "unreferenced formal parameter"; we *want* that in many cases
C4100:
"case 'aaa' is not a valid value for switch of enum 'bbb'
Actually, this is a valid warning, but we do it all over the
place, eg. with ScreenMessages. Those should be fixed, but later. XXX
C4063:
C4127:
C4786: VC6: identifier was truncated to '255' characters in the debug information
C4505: removed unferenced local function from integer.cpp & algebra.h
C4244: converting of data = possible data loss. (This pragma should eventually go away)
C4355: 'this' : used in base member initializer list
*/
// Fix VC breakage.
#define PATH_MAX _MAX_PATH
@@ -145,7 +151,7 @@ inline long int lrintf( float f )
#define ENDIAN_LITTLE
#define OGG_LIB_DIR "vorbis/win32/"
#define OGG_LIB_DIR "../extern/vorbis/win32/"
#if defined(__GNUC__) // It might be MinGW or Cygwin(?)
#include "archutils/Common/gcc_byte_swaps.h"
File diff suppressed because it is too large Load Diff
-93
View File
@@ -1,93 +0,0 @@
#ifndef SSHBN_H
#define SSHBN_H
#if defined __GNUC__ && defined __i386__
typedef unsigned long BignumInt;
typedef unsigned long long BignumDblInt;
#define BIGNUM_INT_MASK 0xFFFFFFFFUL
#define BIGNUM_TOP_BIT 0x80000000UL
#define BIGNUM_INT_BITS 32
#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
#define DIVMOD_WORD(q, r, hi, lo, w) \
__asm__("div %2" : \
"=d" (r), "=a" (q) : \
"r" (w), "d" (hi), "a" (lo))
#else
typedef unsigned short BignumInt;
typedef unsigned long BignumDblInt;
#define BIGNUM_INT_MASK 0xFFFFU
#define BIGNUM_TOP_BIT 0x8000U
#define BIGNUM_INT_BITS 16
#define MUL_WORD(w1, w2) ((BignumDblInt)w1 * w2)
#define DIVMOD_WORD(q, r, hi, lo, w) do { \
BignumDblInt n = (((BignumDblInt)hi) << BIGNUM_INT_BITS) | lo; \
q = n / w; \
r = n % w; \
} while (0)
#endif
#define BIGNUM_INT_BYTES (BIGNUM_INT_BITS / 8)
typedef BignumInt *Bignum;
Bignum copybn(Bignum b);
Bignum bn_power_2(int n);
void bn_restore_invariant(Bignum b);
Bignum bignum_from_long(unsigned long n);
void freebn(Bignum b);
Bignum modpow(Bignum base, Bignum exp, Bignum mod);
Bignum modmul(Bignum a, Bignum b, Bignum mod);
void decbn(Bignum n);
extern Bignum Zero, One;
unsigned char *bignum_to_buffer( const Bignum bn, int *nbytes );
Bignum bignum_from_buffer(const unsigned char *data, int nbytes);
Bignum bignum_from_bytes(const unsigned char *data, int nbytes);
unsigned char *bignum_to_bytes( const Bignum bn, int *nbytes );
int ssh1_read_bignum(const unsigned char *data, Bignum * result);
int bignum_bitcount(Bignum bn);
int ssh1_bignum_length(Bignum bn);
int ssh2_bignum_length(Bignum bn);
unsigned char bignum_byte( const Bignum bn, int i );
int bignum_bit( const Bignum bn, int i );
void bignum_set_bit(Bignum bn, int i, int value);
int ssh1_write_bignum(void *data, Bignum bn);
Bignum biggcd(Bignum a, Bignum b);
unsigned short bignum_mod_short(Bignum number, unsigned short modulus);
Bignum bignum_add_long(Bignum number, unsigned long addend);
Bignum bigmul(Bignum a, Bignum b);
Bignum bigmuladd(Bignum a, Bignum b, Bignum addend);
Bignum bigdiv(Bignum a, Bignum b);
Bignum bigmod(Bignum a, Bignum b);
Bignum modinv(Bignum number, Bignum modulus);
Bignum bignum_bitmask(Bignum number);
Bignum bignum_rshift(Bignum number, int shift);
int bignum_cmp(Bignum a, Bignum b);
char *bignum_decimal(Bignum x);
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-232
View File
@@ -1,232 +0,0 @@
#include "global.h"
#include "CryptMD5.h"
/*
* MD5 implementation for PuTTY. Written directly from the spec by
* Simon Tatham.
*/
/* ----------------------------------------------------------------------
* Core MD5 algorithm: processes 16-word blocks into a message digest.
*/
#define F(x,y,z) ( ((x) & (y)) | ((~(x)) & (z)) )
#define G(x,y,z) ( ((x) & (z)) | ((~(z)) & (y)) )
#define H(x,y,z) ( (x) ^ (y) ^ (z) )
#define I(x,y,z) ( (y) ^ ( (x) | ~(z) ) )
#define rol(x,y) ( ((x) << (y)) | (((uint32_t)x) >> (32-y)) )
#define subround(f,w,x,y,z,k,s,ti) \
w = x + rol(w + f(x,y,z) + block[k] + ti, s)
static void MD5_Core_Init(MD5_Core_State * s)
{
s->h[0] = 0x67452301;
s->h[1] = 0xefcdab89;
s->h[2] = 0x98badcfe;
s->h[3] = 0x10325476;
}
static void MD5_Block(MD5_Core_State * s, uint32_t * block)
{
uint32_t a, b, c, d;
a = s->h[0];
b = s->h[1];
c = s->h[2];
d = s->h[3];
subround(F, a, b, c, d, 0, 7, 0xd76aa478);
subround(F, d, a, b, c, 1, 12, 0xe8c7b756);
subround(F, c, d, a, b, 2, 17, 0x242070db);
subround(F, b, c, d, a, 3, 22, 0xc1bdceee);
subround(F, a, b, c, d, 4, 7, 0xf57c0faf);
subround(F, d, a, b, c, 5, 12, 0x4787c62a);
subround(F, c, d, a, b, 6, 17, 0xa8304613);
subround(F, b, c, d, a, 7, 22, 0xfd469501);
subround(F, a, b, c, d, 8, 7, 0x698098d8);
subround(F, d, a, b, c, 9, 12, 0x8b44f7af);
subround(F, c, d, a, b, 10, 17, 0xffff5bb1);
subround(F, b, c, d, a, 11, 22, 0x895cd7be);
subround(F, a, b, c, d, 12, 7, 0x6b901122);
subround(F, d, a, b, c, 13, 12, 0xfd987193);
subround(F, c, d, a, b, 14, 17, 0xa679438e);
subround(F, b, c, d, a, 15, 22, 0x49b40821);
subround(G, a, b, c, d, 1, 5, 0xf61e2562);
subround(G, d, a, b, c, 6, 9, 0xc040b340);
subround(G, c, d, a, b, 11, 14, 0x265e5a51);
subround(G, b, c, d, a, 0, 20, 0xe9b6c7aa);
subround(G, a, b, c, d, 5, 5, 0xd62f105d);
subround(G, d, a, b, c, 10, 9, 0x02441453);
subround(G, c, d, a, b, 15, 14, 0xd8a1e681);
subround(G, b, c, d, a, 4, 20, 0xe7d3fbc8);
subround(G, a, b, c, d, 9, 5, 0x21e1cde6);
subround(G, d, a, b, c, 14, 9, 0xc33707d6);
subround(G, c, d, a, b, 3, 14, 0xf4d50d87);
subround(G, b, c, d, a, 8, 20, 0x455a14ed);
subround(G, a, b, c, d, 13, 5, 0xa9e3e905);
subround(G, d, a, b, c, 2, 9, 0xfcefa3f8);
subround(G, c, d, a, b, 7, 14, 0x676f02d9);
subround(G, b, c, d, a, 12, 20, 0x8d2a4c8a);
subround(H, a, b, c, d, 5, 4, 0xfffa3942);
subround(H, d, a, b, c, 8, 11, 0x8771f681);
subround(H, c, d, a, b, 11, 16, 0x6d9d6122);
subround(H, b, c, d, a, 14, 23, 0xfde5380c);
subround(H, a, b, c, d, 1, 4, 0xa4beea44);
subround(H, d, a, b, c, 4, 11, 0x4bdecfa9);
subround(H, c, d, a, b, 7, 16, 0xf6bb4b60);
subround(H, b, c, d, a, 10, 23, 0xbebfbc70);
subround(H, a, b, c, d, 13, 4, 0x289b7ec6);
subround(H, d, a, b, c, 0, 11, 0xeaa127fa);
subround(H, c, d, a, b, 3, 16, 0xd4ef3085);
subround(H, b, c, d, a, 6, 23, 0x04881d05);
subround(H, a, b, c, d, 9, 4, 0xd9d4d039);
subround(H, d, a, b, c, 12, 11, 0xe6db99e5);
subround(H, c, d, a, b, 15, 16, 0x1fa27cf8);
subround(H, b, c, d, a, 2, 23, 0xc4ac5665);
subround(I, a, b, c, d, 0, 6, 0xf4292244);
subround(I, d, a, b, c, 7, 10, 0x432aff97);
subround(I, c, d, a, b, 14, 15, 0xab9423a7);
subround(I, b, c, d, a, 5, 21, 0xfc93a039);
subround(I, a, b, c, d, 12, 6, 0x655b59c3);
subround(I, d, a, b, c, 3, 10, 0x8f0ccc92);
subround(I, c, d, a, b, 10, 15, 0xffeff47d);
subround(I, b, c, d, a, 1, 21, 0x85845dd1);
subround(I, a, b, c, d, 8, 6, 0x6fa87e4f);
subround(I, d, a, b, c, 15, 10, 0xfe2ce6e0);
subround(I, c, d, a, b, 6, 15, 0xa3014314);
subround(I, b, c, d, a, 13, 21, 0x4e0811a1);
subround(I, a, b, c, d, 4, 6, 0xf7537e82);
subround(I, d, a, b, c, 11, 10, 0xbd3af235);
subround(I, c, d, a, b, 2, 15, 0x2ad7d2bb);
subround(I, b, c, d, a, 9, 21, 0xeb86d391);
s->h[0] += a;
s->h[1] += b;
s->h[2] += c;
s->h[3] += d;
}
/* ----------------------------------------------------------------------
* Outer MD5 algorithm: take an arbitrary length byte string,
* convert it into 16-word blocks with the prescribed padding at
* the end, and pass those blocks to the core MD5 algorithm.
*/
#define BLKSIZE 64
void MD5Init(struct MD5Context *s)
{
MD5_Core_Init(&s->core);
s->blkused = 0;
s->lenhi = s->lenlo = 0;
}
void MD5Update(struct MD5Context *s, unsigned char const *p, unsigned len)
{
unsigned char *q = (unsigned char *) p;
uint32_t wordblock[16];
uint32_t lenw = len;
int i;
/*
* Update the length field.
*/
s->lenlo += lenw;
s->lenhi += (s->lenlo < lenw);
if (s->blkused + len < BLKSIZE) {
/*
* Trivial case: just add to the block.
*/
memcpy(s->block + s->blkused, q, len);
s->blkused += len;
} else {
/*
* We must complete and process at least one block.
*/
while (s->blkused + len >= BLKSIZE) {
memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
q += BLKSIZE - s->blkused;
len -= BLKSIZE - s->blkused;
/* Now process the block. Gather bytes little-endian into words */
for (i = 0; i < 16; i++) {
wordblock[i] =
(((uint32_t) s->block[i * 4 + 3]) << 24) |
(((uint32_t) s->block[i * 4 + 2]) << 16) |
(((uint32_t) s->block[i * 4 + 1]) << 8) |
(((uint32_t) s->block[i * 4 + 0]) << 0);
}
MD5_Block(&s->core, wordblock);
s->blkused = 0;
}
memcpy(s->block, q, len);
s->blkused = len;
}
}
void MD5Final(unsigned char output[16], struct MD5Context *s)
{
int i;
unsigned pad;
unsigned char c[64];
uint32_t lenhi, lenlo;
if (s->blkused >= 56)
pad = 56 + 64 - s->blkused;
else
pad = 56 - s->blkused;
lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
lenlo = (s->lenlo << 3);
memset(c, 0, pad);
c[0] = 0x80;
MD5Update(s, c, pad);
c[7] = char((lenhi >> 24) & 0xFF);
c[6] = char((lenhi >> 16) & 0xFF);
c[5] = char((lenhi >> 8) & 0xFF);
c[4] = char((lenhi >> 0) & 0xFF);
c[3] = char((lenlo >> 24) & 0xFF);
c[2] = char((lenlo >> 16) & 0xFF);
c[1] = char((lenlo >> 8) & 0xFF);
c[0] = char((lenlo >> 0) & 0xFF);
MD5Update(s, c, 8);
for (i = 0; i < 4; i++) {
output[4 * i + 3] = char((s->core.h[i] >> 24) & 0xFF);
output[4 * i + 2] = char((s->core.h[i] >> 16) & 0xFF);
output[4 * i + 1] = char((s->core.h[i] >> 8) & 0xFF);
output[4 * i + 0] = char((s->core.h[i] >> 0) & 0xFF);
}
}
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-46
View File
@@ -1,46 +0,0 @@
#ifndef SSHMD5_H
#define SSHMD5_H
typedef struct {
uint32_t h[4];
} MD5_Core_State;
struct MD5Context {
MD5_Core_State core;
unsigned char block[64];
int blkused;
uint32_t lenhi, lenlo;
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context);
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-154
View File
@@ -1,154 +0,0 @@
/*
* Noise generation for PuTTY's cryptographic random number
* generator.
*/
#include "global.h"
#if defined(_WINDOWS)
#define _WIN32_WINNT 0x0400 // VC6 header needs this defined.
#include <windows.h>
#include <wincrypt.h>
/*
* This function is called once, at PuTTY startup, and will do some
* seriously silly things like listing directories and getting disk
* free space and a process snapshot.
*/
void noise_get_heavy(void (*func) (void *, int))
{
static HCRYPTPROV hProv = NULL;
if( hProv == NULL )
{
if( !CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) )
{
char buf[1024] = "";
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
0, GetLastError(), 0, buf, sizeof(buf), NULL);
RageException::Throw( "CryptAcquireContext: %s", buf );
}
}
char buf[2048];
if ( !CryptGenRandom(hProv, sizeof(buf), (BYTE*) buf) )
RageException::Throw( "CryptGenRandom" );
func( buf, sizeof(buf) );
}
/*
* This function is called every time the random pool needs
* stirring, and will acquire the system time in all available
* forms and the battery status.
*/
void noise_get_light(void (*func) (void *, int))
{
SYSTEMTIME systime;
DWORD adjust[2];
BOOL rubbish;
GetSystemTime(&systime);
func(&systime, sizeof(systime));
GetSystemTimeAdjustment(&adjust[0], &adjust[1], &rubbish);
func(&adjust, sizeof(adjust));
}
#else
#include <fcntl.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/resource.h>
static int read_dev_urandom(char *buf, int len)
{
int fd;
int ngot, ret;
fd = open("/dev/urandom", O_RDONLY);
if (fd < 0)
return 0;
ngot = 0;
while (ngot < len)
{
ret = read(fd, buf+ngot, len-ngot);
if (ret < 0) {
close(fd);
return 0;
}
ngot += ret;
}
return 1;
}
/*
* This function is called once, at PuTTY startup. It will do some
* slightly silly things such as fetching an entire process listing
* and scanning /tmp, load the saved random seed from disk, and
* also read 32 bytes out of /dev/urandom.
*/
void noise_get_heavy(void (*func) (void *, int))
{
char buf[512];
if (read_dev_urandom(buf, 32))
func(buf, 32);
#if defined(UNIX)
FILE *fp;
int ret;
fp = popen("ps -axu 2>/dev/null", "r");
while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
func(buf, ret);
pclose(fp);
fp = popen("ls -al /tmp 2>/dev/null", "r");
while ( (ret = fread(buf, 1, sizeof(buf), fp)) > 0)
func(buf, ret);
pclose(fp);
#endif
}
/*
* This function is called every time the random pool needs
* stirring, and will acquire the system time.
*/
void noise_get_light(void (*func) (void *, int))
{
struct timeval tv;
gettimeofday(&tv, NULL);
func(&tv, sizeof(tv));
}
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
File diff suppressed because it is too large Load Diff
-34
View File
@@ -1,34 +0,0 @@
#ifndef SSH_PRIME_H
#define SSH_PRIME_H
#include "CryptBn.h"
Bignum primegen(int bits, int modulus, int residue, Bignum factor, int phase);
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-799
View File
@@ -1,799 +0,0 @@
/*
* RSA implementation for PuTTY.
*/
#include "global.h"
#include "RageUtil.h"
#include "CryptRSA.h"
#include "CryptSHA.h"
#include "CryptSH512.h"
#include "CryptMD5.h"
#include "CryptRand.h"
#include "CryptPrime.h"
#define GET_32BIT(cp) \
(((unsigned long)(unsigned char)(cp)[0] << 24) | \
((unsigned long)(unsigned char)(cp)[1] << 16) | \
((unsigned long)(unsigned char)(cp)[2] << 8) | \
((unsigned long)(unsigned char)(cp)[3]))
#define PUT_32BIT(cp, value) { \
(cp)[0] = (unsigned char)((value) >> 24); \
(cp)[1] = (unsigned char)((value) >> 16); \
(cp)[2] = (unsigned char)((value) >> 8); \
(cp)[3] = (unsigned char)(value); }
RSAKey::RSAKey()
{
bits = bytes = 0;
modulus = exponent = private_exponent = p = q = iqmp = NULL;
}
RSAKey::~RSAKey()
{
if(p)
freebn(p);
if(q)
freebn(q);
if(modulus)
freebn(modulus);
if(exponent)
freebn(exponent);
if(private_exponent)
freebn(private_exponent);
if(iqmp)
freebn(iqmp);
}
int makekey(unsigned char *data, struct RSAKey *result,
unsigned char **keystr, int order)
{
unsigned char *p = data;
int i;
if (result) {
result->bits = 0;
for (i = 0; i < 4; i++)
result->bits = (result->bits << 8) + *p++;
} else
p += 4;
/*
* order=0 means exponent then modulus (the keys sent by the
* server). order=1 means modulus then exponent (the keys
* stored in a keyfile).
*/
if (order == 0)
p += ssh1_read_bignum(p, result ? &result->exponent : NULL);
if (result)
result->bytes = (((p[0] << 8) + p[1]) + 7) / 8;
if (keystr)
*keystr = p + 2;
p += ssh1_read_bignum(p, result ? &result->modulus : NULL);
if (order == 1)
p += ssh1_read_bignum(p, result ? &result->exponent : NULL);
return p - data;
}
int makeprivate( const unsigned char *data, struct RSAKey *result )
{
return ssh1_read_bignum(data, &result->private_exponent);
}
unsigned char *GetBytes( Bignum bn, int *buflen )
{
int len = bn[0]*BIGNUM_INT_BYTES;
unsigned char *ret = new unsigned char[len];
unsigned char *p = ret;
for( int i = len-1; i >= 0; --i )
*p++ = bignum_byte( bn, i );
return ret;
}
static void sha512_mpint(SHA512_State * s, Bignum b)
{
unsigned char lenbuf[4];
int len;
len = (bignum_bitcount(b) + 8) / 8;
PUT_32BIT(lenbuf, len);
SHA512_Bytes(s, lenbuf, 4);
while (len-- > 0) {
lenbuf[0] = bignum_byte(b, len);
SHA512_Bytes(s, lenbuf, 1);
}
memset(lenbuf, 0, sizeof(lenbuf));
}
/*
* This function is a wrapper on modpow(). It has the same effect
* as modpow(), but employs RSA blinding to protect against timing
* attacks.
*/
static Bignum rsa_privkey_op(Bignum input, const RSAKey *key)
{
Bignum random, random_encrypted, random_inverse;
Bignum input_blinded, ret_blinded;
Bignum ret;
SHA512_State ss;
unsigned char digest512[64];
unsigned digestused = ARRAYLEN(digest512);
int hashseq = 0;
/*
* Start by inventing a random number chosen uniformly from the
* range 2..modulus-1. (We do this by preparing a random number
* of the right length and retrying if it's greater than the
* modulus, to prevent any potential Bleichenbacher-like
* attacks making use of the uneven distribution within the
* range that would arise from just reducing our number mod n.
* There are timing implications to the potential retries, of
* course, but all they tell you is the modulus, which you
* already knew.)
*
* To preserve determinism and avoid Pageant needing to share
* the random number pool, we actually generate this `random'
* number by hashing stuff with the private key.
*/
while (1) {
int bits, byte, bitsleft, v;
random = copybn(key->modulus);
/*
* Find the topmost set bit. (This function will return its
* index plus one.) Then we'll set all bits from that one
* downwards randomly.
*/
bits = bignum_bitcount(random);
byte = 0;
bitsleft = 0;
while (bits--) {
if (bitsleft <= 0) {
bitsleft = 8;
/*
* Conceptually the following few lines are equivalent to
* byte = random_byte();
*/
if (digestused >= ARRAYLEN(digest512)) {
unsigned char seqbuf[4];
PUT_32BIT(seqbuf, hashseq);
SHA512_Init(&ss);
SHA512_Bytes(&ss, "RSA deterministic blinding", 26);
SHA512_Bytes(&ss, seqbuf, sizeof(seqbuf));
sha512_mpint(&ss, key->private_exponent);
SHA512_Final(&ss, digest512);
hashseq++;
/*
* Now hash that digest plus the signature
* input.
*/
SHA512_Init(&ss);
SHA512_Bytes(&ss, digest512, sizeof(digest512));
sha512_mpint(&ss, input);
SHA512_Final(&ss, digest512);
digestused = 0;
}
byte = digest512[digestused++];
}
v = byte & 1;
byte >>= 1;
bitsleft--;
bignum_set_bit(random, bits, v);
}
/*
* Now check that this number is strictly greater than
* zero, and strictly less than modulus.
*/
if (bignum_cmp(random, Zero) <= 0 ||
bignum_cmp(random, key->modulus) >= 0) {
freebn(random);
continue;
} else {
break;
}
}
/*
* RSA blinding relies on the fact that (xy)^d mod n is equal
* to (x^d mod n) * (y^d mod n) mod n. We invent a random pair
* y and y^d; then we multiply x by y, raise to the power d mod
* n as usual, and divide by y^d to recover x^d. Thus an
* attacker can't correlate the timing of the modpow with the
* input, because they don't know anything about the number
* that was input to the actual modpow.
*
* The clever bit is that we don't have to do a huge modpow to
* get y and y^d; we will use the number we just invented as
* _y^d_, and use the _public_ exponent to compute (y^d)^e = y
* from it, which is much faster to do.
*/
random_encrypted = modpow(random, key->exponent, key->modulus);
random_inverse = modinv(random, key->modulus);
input_blinded = modmul(input, random_encrypted, key->modulus);
ret_blinded = modpow(input_blinded, key->private_exponent, key->modulus);
ret = modmul(ret_blinded, random_inverse, key->modulus);
freebn(ret_blinded);
freebn(input_blinded);
freebn(random_inverse);
freebn(random_encrypted);
freebn(random);
return ret;
}
bool RSAKey::Encrypt( RString &buf ) const
{
Bignum bn = bignum_from_bytes( (unsigned char *) buf.data(), buf.size() );
Bignum encrypted_bn = Encrypt( bn );
delete [] bn;
int len;
unsigned char *bytes = bignum_to_buffer( encrypted_bn, &len );
buf = RString( (const char *) bytes, len );
delete [] encrypted_bn;
return true;
}
bool RSAKey::Decrypt( RString &buf ) const
{
Bignum bn = bignum_from_buffer( (unsigned char *) buf.data(), buf.size() );
if( bn == NULL )
return false;
Bignum decrypted_bn = Decrypt( bn );
delete [] bn;
int len;
unsigned char *bytes = bignum_to_bytes( decrypted_bn, &len );
buf = RString( (const char *) bytes, len );
delete [] decrypted_bn;
return true;
}
Bignum RSAKey::Encrypt(const Bignum input) const
{
return modpow( input, this->exponent, this->modulus );
}
Bignum RSAKey::Decrypt(const Bignum input) const
{
return rsa_privkey_op(input, this);
}
int RSAKey::StrLen() const
{
Bignum md, ex;
int mdlen, exlen;
md = this->modulus;
ex = this->exponent;
mdlen = (bignum_bitcount(md) + 15) / 16;
exlen = (bignum_bitcount(ex) + 15) / 16;
return 4 * (mdlen + exlen) + 20;
}
void RSAKey::StrFmt( char *str ) const
{
int len = 0, i, nibbles;
static const char hex[] = "0123456789abcdef";
len += sprintf(str + len, "0x");
nibbles = (3 + bignum_bitcount(this->exponent)) / 4;
if (nibbles < 1)
nibbles = 1;
for (i = nibbles; i--;)
str[len++] = hex[(bignum_byte(this->exponent, i / 2) >> (4 * (i % 2))) & 0xF];
len += sprintf(str + len, ",0x");
nibbles = (3 + bignum_bitcount(this->modulus)) / 4;
if (nibbles < 1)
nibbles = 1;
for (i = nibbles; i--;)
str[len++] = hex[(bignum_byte(this->modulus, i / 2) >> (4 * (i % 2))) & 0xF];
str[len] = '\0';
}
/*
* Generate a fingerprint string for the key. Compatible with the
* OpenSSH fingerprint code.
*/
void RSAKey::Fingerprint( char *str, int len ) const
{
struct MD5Context md5c;
unsigned char digest[16];
char buffer[16 * 3 + 40];
int numlen, slen, i;
MD5Init(&md5c);
numlen = ssh1_bignum_length(this->modulus) - 2;
for (i = numlen; i--;) {
unsigned char c = bignum_byte(this->modulus, i);
MD5Update(&md5c, &c, 1);
}
numlen = ssh1_bignum_length(this->exponent) - 2;
for (i = numlen; i--;) {
unsigned char c = bignum_byte(this->exponent, i);
MD5Update(&md5c, &c, 1);
}
MD5Final(digest, &md5c);
sprintf(buffer, "%d ", bignum_bitcount(this->modulus));
for (i = 0; i < 16; i++)
sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
digest[i]);
strncpy(str, buffer, len);
str[len - 1] = '\0';
slen = strlen(str);
if (!this->comment.empty() && slen < len - 1)
{
str[slen] = ' ';
strncpy(str + slen + 1, this->comment, len - slen - 1);
str[len - 1] = '\0';
}
}
/*
* Verify that the public data in an RSA key matches the private
* data. We also check the private data itself: we ensure that p >
* q and that iqmp really is the inverse of q mod p.
*/
bool RSAKey::Check() const
{
Bignum n, ed, pm1, qm1;
int cmp;
/* n must equal pq. */
n = bigmul(this->p, this->q);
cmp = bignum_cmp(n, this->modulus);
freebn(n);
if (cmp != 0)
return 0;
/* e * d must be congruent to 1, modulo (p-1) and modulo (q-1). */
pm1 = copybn(this->p);
decbn(pm1);
ed = modmul(this->exponent, this->private_exponent, pm1);
cmp = bignum_cmp(ed, One);
delete [] ed;
if (cmp != 0)
return 0;
qm1 = copybn(this->q);
decbn(qm1);
ed = modmul(this->exponent, this->private_exponent, qm1);
cmp = bignum_cmp(ed, One);
delete [] ed;
if (cmp != 0)
return 0;
/*
* Ensure p > q.
*/
if (bignum_cmp(this->p, this->q) <= 0)
return 0;
/*
* Ensure iqmp * q is congruent to 1, modulo p.
*/
n = modmul(this->iqmp, this->q, this->p);
cmp = bignum_cmp(n, One);
delete [] n;
if (cmp != 0)
return 0;
return 1;
}
/* ----------------------------------------------------------------------
* Implementation of the ssh-rsa signing key type.
*/
static void getstring(const char **data, int *datalen, const char **p, int *length)
{
*p = NULL;
if (*datalen < 4)
return;
*length = GET_32BIT(*data);
*datalen -= 4;
*data += 4;
if (*datalen < *length)
return;
*p = *data;
*data += *length;
*datalen -= *length;
}
static Bignum getmp(const char **data, int *datalen)
{
const char *p;
int length;
Bignum b;
getstring(data, datalen, &p, &length);
if (!p)
return NULL;
b = bignum_from_bytes((unsigned char *)p, length);
return b;
}
bool RSAKey::LoadFromPublicBlob( const RString &str )
{
int len = str.size();
const char *data = str.data();
const char *p;
int slen;
getstring(&data, &len, &p, &slen);
if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
return false;
}
struct RSAKey *rsa = new RSAKey;
rsa->exponent = getmp(&data, &len);
rsa->modulus = getmp(&data, &len);
rsa->private_exponent = NULL;
return true;
}
char *RSAKey::FmtKey() const
{
int len = this->StrLen();
char *p = new char[len];
StrFmt( p );
return p;
}
void RSAKey::PublicBlob( RString &out ) const
{
int elen, mlen, bloblen;
int i;
unsigned char *blob, *p;
elen = (bignum_bitcount(this->exponent) + 8) / 8;
mlen = (bignum_bitcount(this->modulus) + 8) / 8;
/*
* string "ssh-rsa", mpint exp, mpint mod. Total 19+elen+mlen.
* (three length fields, 12+7=19).
*/
bloblen = 19 + elen + mlen;
blob = new unsigned char[bloblen];
p = blob;
PUT_32BIT(p, 7);
p += 4;
memcpy(p, "ssh-rsa", 7);
p += 7;
PUT_32BIT(p, elen);
p += 4;
for (i = elen; i--;)
*p++ = bignum_byte(this->exponent, i);
PUT_32BIT(p, mlen);
p += 4;
for (i = mlen; i--;)
*p++ = bignum_byte(this->modulus, i);
ASSERT(p == blob + bloblen);
out = RString( (const char *) blob, bloblen );
}
void RSAKey::PrivateBlob( RString &out ) const
{
int i;
unsigned char *blob, *p;
int elen = (bignum_bitcount(this->exponent) + 8) / 8;
int mlen = (bignum_bitcount(this->modulus) + 8) / 8;
int dlen = (bignum_bitcount(this->private_exponent) + 8) / 8;
int plen = (bignum_bitcount(this->p) + 8) / 8;
int qlen = (bignum_bitcount(this->q) + 8) / 8;
int ulen = (bignum_bitcount(this->iqmp) + 8) / 8;
/*
* mpint exp, mpint mod, mpint private_exp, mpint p, mpint q, mpint iqmp. Total 24 +
* sum of lengths.
*/
int bloblen = 24 + elen + mlen + dlen + plen + qlen + ulen;
blob = new unsigned char[bloblen];
p = blob;
PUT_32BIT(p, elen);
p += 4;
for (i = elen; i--;)
*p++ = bignum_byte(this->exponent, i);
PUT_32BIT(p, mlen);
p += 4;
for (i = mlen; i--;)
*p++ = bignum_byte(this->modulus, i);
PUT_32BIT(p, dlen);
p += 4;
for (i = dlen; i--;)
*p++ = bignum_byte(this->private_exponent, i);
PUT_32BIT(p, plen);
p += 4;
for (i = plen; i--;)
*p++ = bignum_byte(this->p, i);
PUT_32BIT(p, qlen);
p += 4;
for (i = qlen; i--;)
*p++ = bignum_byte(this->q, i);
PUT_32BIT(p, ulen);
p += 4;
for (i = ulen; i--;)
*p++ = bignum_byte(this->iqmp, i);
ASSERT(p == blob + bloblen);
out = RString( (const char *) blob, bloblen );
}
bool RSAKey::LoadFromPrivateBlob( const RString &str )
{
int len = str.size();
const char *data = str.data();
this->exponent = getmp(&data, &len);
this->modulus = getmp(&data, &len);
this->private_exponent = getmp(&data, &len);
this->p = getmp(&data, &len);
this->q = getmp(&data, &len);
this->iqmp = getmp(&data, &len);
if (!this->Check())
return false;
return true;
}
/* static struct RSAKey *rsa2_openssh_createkey(unsigned char **blob, int *len)
{
const char **b = (const char **) blob;
struct RSAKey *rsa = new RSAKey;
rsa->comment = NULL;
rsa->modulus = getmp(b, len);
rsa->exponent = getmp(b, len);
rsa->private_exponent = getmp(b, len);
rsa->iqmp = getmp(b, len);
rsa->p = getmp(b, len);
rsa->q = getmp(b, len);
if (!rsa->modulus || !rsa->exponent || !rsa->private_exponent ||
!rsa->iqmp || !rsa->p || !rsa->q)
{
delete rsa;
return NULL;
}
return rsa;
}
static int rsa2_openssh_fmtkey( struct RSAKey *rsa, unsigned char *blob, int len )
{
int bloblen =
ssh2_bignum_length(rsa->modulus) +
ssh2_bignum_length(rsa->exponent) +
ssh2_bignum_length(rsa->private_exponent) +
ssh2_bignum_length(rsa->iqmp) +
ssh2_bignum_length(rsa->p) + ssh2_bignum_length(rsa->q);
if (bloblen > len)
return bloblen;
bloblen = 0;
#define ENC(x) \
PUT_32BIT(blob+bloblen, ssh2_bignum_length((x))-4); bloblen += 4; \
for (i = ssh2_bignum_length((x))-4; i-- ;) blob[bloblen++]=bignum_byte((x),i);
int i;
ENC(rsa->modulus);
ENC(rsa->exponent);
ENC(rsa->private_exponent);
ENC(rsa->iqmp);
ENC(rsa->p);
ENC(rsa->q);
return bloblen;
}
*/
int rsa2_pubkey_bits( const RString &blob )
{
RSAKey rsa;
if( !rsa.LoadFromPublicBlob( blob ) )
return 0;
return bignum_bitcount(rsa.modulus);
}
char *rsa2_fingerprint( struct RSAKey *rsa )
{
struct MD5Context md5c;
unsigned char digest[16], lenbuf[4];
char buffer[16 * 3 + 40];
char *ret;
int numlen, i;
MD5Init(&md5c);
MD5Update(&md5c, (unsigned char *)"\0\0\0\7ssh-rsa", 11);
#define ADD_BIGNUM(bignum) \
numlen = (bignum_bitcount(bignum)+8)/8; \
PUT_32BIT(lenbuf, numlen); MD5Update(&md5c, lenbuf, 4); \
for (i = numlen; i-- ;) { \
unsigned char c = bignum_byte(bignum, i); \
MD5Update(&md5c, &c, 1); \
}
ADD_BIGNUM(rsa->exponent);
ADD_BIGNUM(rsa->modulus);
#undef ADD_BIGNUM
MD5Final(digest, &md5c);
sprintf(buffer, "ssh-rsa %d ", bignum_bitcount(rsa->modulus));
for (i = 0; i < 16; i++)
sprintf(buffer + strlen(buffer), "%s%02x", i ? ":" : "",
digest[i]);
ret = new char[strlen(buffer) + 1];
if (ret)
strcpy(ret, buffer);
return ret;
}
bool RSAKey::Verify( const RString &data, const RString &sig ) const
{
Bignum in, out;
int bytes, i, j;
unsigned char hash[20];
in = bignum_from_bytes( (const unsigned char *) sig.data(), sig.size() );
/* Base (in) must be smaller than the modulus. */
if( bignum_cmp(in, this->modulus) >= 0 )
{
freebn(in);
return false;
}
out = modpow(in, this->exponent, this->modulus);
freebn(in);
bool ret = true;
bytes = (bignum_bitcount(this->modulus)+7) / 8;
/* Top (partial) byte should be zero. */
if (bignum_byte(out, bytes - 1) != 0)
ret = 0;
/* First whole byte should be 1. */
if (bignum_byte(out, bytes - 2) != 1)
ret = 0;
/* Most of the rest should be FF. */
for (i = bytes - 3; i >= 20; i--) {
if (bignum_byte(out, i) != 0xFF)
ret = 0;
}
/* Finally, we expect to see the SHA-1 hash of the signed data. */
SHA_Simple( data.data(), data.size(), hash );
for (i = 19, j = 0; i >= 0; i--, j++) {
if (bignum_byte(out, i) != hash[j])
ret = false;
}
freebn(out);
return ret;
}
void RSAKey::Sign( const RString &data, RString &out ) const
{
Bignum in;
{
unsigned char hash[20];
SHA_Simple(data.data(), data.size(), hash);
int nbytes = (bignum_bitcount(this->modulus) - 1) / 8;
unsigned char *bytes = new unsigned char[nbytes];
memset( bytes, 0xFF, nbytes );
bytes[0] = 1;
memcpy( bytes + nbytes - 20, hash, 20 );
in = bignum_from_bytes(bytes, nbytes);
delete [] bytes;
}
Bignum outnum = rsa_privkey_op(in, this);
delete [] in;
int siglen;
unsigned char *bytes = bignum_to_bytes( outnum, &siglen );
delete [] outnum;
out = RString( (const char *) bytes, siglen );
delete [] bytes;
}
#define RSA_EXPONENT 37 /* we like this prime */
int RSAKey::Generate( int bits )
{
Bignum pm1, qm1, phi_n;
/*
* We don't generate e; we just use a standard one always.
*/
this->exponent = bignum_from_long(RSA_EXPONENT);
/*
* Generate p and q: primes with combined length `bits', not
* congruent to 1 modulo e. (Strictly speaking, we wanted (p-1)
* and e to be coprime, and (q-1) and e to be coprime, but in
* general that's slightly more fiddly to arrange. By choosing
* a prime e, we can simplify the criterion.)
*/
this->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL, 1);
this->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL, 2);
/*
* Ensure p > q, by swapping them if not.
*/
if (bignum_cmp(this->p, this->q) < 0)
swap( p, q );
/*
* Now we have p, q and e. All we need to do now is work out
* the other helpful quantities: n=pq, d=e^-1 mod (p-1)(q-1),
* and (q^-1 mod p).
*/
this->modulus = bigmul(this->p, this->q);
pm1 = copybn(this->p);
decbn(pm1);
qm1 = copybn(this->q);
decbn(qm1);
phi_n = bigmul(pm1, qm1);
freebn(pm1);
freebn(qm1);
this->private_exponent = modinv(this->exponent, phi_n);
this->iqmp = modinv(this->q, this->p);
/*
* Clean up temporary numbers.
*/
freebn(phi_n);
return 1;
}
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-68
View File
@@ -1,68 +0,0 @@
#ifndef RSAKEY_H
#define RSAKEY_H
#include "CryptBn.h"
struct RSAKey
{
RSAKey();
~RSAKey();
int bits;
int bytes;
Bignum modulus;
Bignum exponent;
Bignum private_exponent;
Bignum p;
Bignum q;
Bignum iqmp;
RString comment;
int Generate( int bits );
void Fingerprint( char *str, int len ) const;
void Sign( const RString &data, RString &out ) const;
bool Verify( const RString &data, const RString &sig ) const;
bool Encrypt( RString &buf ) const;
bool Decrypt( RString &buf ) const;
Bignum Encrypt( const Bignum input ) const;
Bignum Decrypt( const Bignum input ) const;
bool Check() const;
int StrLen() const;
void StrFmt( char *str ) const;
char *FmtKey() const;
void PublicBlob( RString &out ) const;
void PrivateBlob( RString &out ) const;
bool LoadFromPublicBlob( const RString &PublicBlob );
bool LoadFromPrivateBlob( const RString &PrivateBlob );
};
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-241
View File
@@ -1,241 +0,0 @@
/*
* cryptographic random number generator for PuTTY's ssh client
*/
#include "global.h"
#include "CryptSHA.h"
#include "CryptRand.h"
void noise_get_heavy(void (*func) (void *, int));
void noise_get_light(void (*func) (void *, int));
/*
* `pool' itself is a pool of random data which we actually use: we
* return bytes from `pool', at position `poolpos', until `poolpos'
* reaches the end of the pool. At this point we generate more
* random data, by adding noise, stirring well, and resetting
* `poolpos' to point to just past the beginning of the pool (not
* _the_ beginning, since otherwise we'd give away the whole
* contents of our pool, and attackers would just have to guess the
* next lot of noise).
*
* `incomingb' buffers acquired noise data, until it gets full, at
* which point the acquired noise is SHA'ed into `incoming' and
* `incomingb' is cleared. The noise in `incoming' is used as part
* of the noise for each stirring of the pool, in addition to local
* time, process listings, and other such stuff.
*/
#define HASHINPUT 64 /* 64 bytes SHA input */
#define HASHSIZE 20 /* 160 bits SHA output */
#define POOLSIZE 1200 /* size of random pool */
struct RandPool
{
unsigned char pool[POOLSIZE];
int poolpos;
unsigned char incoming[HASHSIZE];
unsigned char incomingb[HASHINPUT];
int incomingpos;
};
static struct RandPool pool;
bool random_active = false;
static void random_stir(void)
{
unsigned block[HASHINPUT / sizeof(unsigned)];
unsigned digest[HASHSIZE / sizeof(unsigned)];
int i, j;
SHATransform((unsigned *) pool.incoming, (unsigned *) pool.incomingb);
pool.incomingpos = 0;
/*
* Chunks of this code are blatantly endianness-dependent, but
* as it's all random bits anyway, WHO CARES?
*/
memcpy(digest, pool.incoming, sizeof(digest));
/*
* Make two passes over the pool.
*/
for (i = 0; i < 2; i++) {
/*
* We operate SHA in CFB mode, repeatedly adding the same
* block of data to the digest. But we're also fiddling
* with the digest-so-far, so this shouldn't be Bad or
* anything.
*/
memcpy(block, pool.pool, sizeof(block));
/*
* Each pass processes the pool backwards in blocks of
* HASHSIZE, just so that in general we get the output of
* SHA before the corresponding input, in the hope that
* things will be that much less predictable that way
* round, when we subsequently return bytes ...
*/
for (j = POOLSIZE; (j -= HASHSIZE) >= 0;) {
/*
* XOR the bit of the pool we're processing into the
* digest.
*/
unsigned k;
for (k = 0; k < sizeof(digest) / sizeof(*digest); k++)
digest[k] ^= ((unsigned *) (pool.pool + j))[k];
/*
* Munge our unrevealed first block of the pool into
* it.
*/
SHATransform(digest, block);
/*
* Stick the result back into the pool.
*/
for( k = 0; k < sizeof(digest) / sizeof(*digest); k++ )
((unsigned *) (pool.pool + j))[k] = digest[k];
}
}
/*
* Might as well save this value back into `incoming', just so
* there'll be some extra bizarreness there.
*/
SHATransform(digest, block);
memcpy(pool.incoming, digest, sizeof(digest));
pool.poolpos = sizeof(pool.incoming);
}
void random_add_noise( const RString &noise )
{
unsigned char *p = (unsigned char *) noise.data();
int i;
if (!random_active)
return;
/*
* This function processes HASHINPUT bytes into only HASHSIZE
* bytes, so _if_ we were getting incredibly high entropy
* sources then we would be throwing away valuable stuff.
*/
int length = noise.size();
while (length >= (HASHINPUT - pool.incomingpos)) {
memcpy(pool.incomingb + pool.incomingpos, p,
HASHINPUT - pool.incomingpos);
p += HASHINPUT - pool.incomingpos;
length -= HASHINPUT - pool.incomingpos;
SHATransform((unsigned *) pool.incoming, (unsigned *) pool.incomingb);
for (i = 0; i < HASHSIZE; i++) {
pool.pool[pool.poolpos++] ^= pool.incomingb[i];
if (pool.poolpos >= POOLSIZE)
pool.poolpos = 0;
}
if (pool.poolpos < HASHSIZE)
random_stir();
pool.incomingpos = 0;
}
memcpy(pool.incomingb + pool.incomingpos, p, length);
pool.incomingpos += length;
}
void random_add_heavynoise(void *noise, int length)
{
unsigned char *p = (unsigned char *) noise;
int i;
while (length >= POOLSIZE) {
for (i = 0; i < POOLSIZE; i++)
pool.pool[i] ^= *p++;
random_stir();
length -= POOLSIZE;
}
for (i = 0; i < length; i++)
pool.pool[i] ^= *p++;
random_stir();
}
static void random_add_heavynoise_bitbybit(void *noise, int length)
{
unsigned char *p = (unsigned char *) noise;
int i;
while (length >= POOLSIZE - pool.poolpos) {
for (i = 0; i < POOLSIZE - pool.poolpos; i++)
pool.pool[pool.poolpos + i] ^= *p++;
random_stir();
length -= POOLSIZE - pool.poolpos;
pool.poolpos = 0;
}
for (i = 0; i < length; i++)
pool.pool[i] ^= *p++;
pool.poolpos = i;
}
void random_init(void)
{
if( random_active )
return;
random_active = true;
memset(&pool, 0, sizeof(pool)); /* just to start with */
noise_get_heavy(random_add_heavynoise_bitbybit);
random_stir();
}
unsigned char random_byte(void)
{
if (pool.poolpos >= POOLSIZE)
random_stir();
return pool.pool[pool.poolpos++];
}
void random_get_savedata(char **data, int *len)
{
char *buf = new char[POOLSIZE / 2];
random_stir();
memcpy(buf, pool.pool + pool.poolpos, POOLSIZE / 2);
*len = POOLSIZE / 2;
*data = buf;
random_stir();
}
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-36
View File
@@ -1,36 +0,0 @@
#ifndef SSH_RAND_H
#define SSH_RAND_H
void random_init();
void random_add_noise( const RString &noise );
unsigned char random_byte();
void random_get_savedata( char **data, int *len );
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-390
View File
@@ -1,390 +0,0 @@
/*
* SHA-512 algorithm as described at
*
* http://csrc.nist.gov/cryptval/shs.html
*/
#include "global.h"
#include "CryptSH512.h"
#define BLKSIZE 128
/*
* Arithmetic implementations. Note that AND, XOR and NOT can
* overlap destination with one source, but the others can't.
*/
#define add(r,x,y) ( r.lo = y.lo + x.lo, \
r.hi = y.hi + x.hi + (r.lo < y.lo) )
#define rorB(r,x,y) ( r.lo = (x.hi >> ((y)-32)) | (x.lo << (64-(y))), \
r.hi = (x.lo >> ((y)-32)) | (x.hi << (64-(y))) )
#define rorL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
r.hi = (x.hi >> (y)) | (x.lo << (32-(y))) )
#define shrB(r,x,y) ( r.lo = x.hi >> ((y)-32), r.hi = 0 )
#define shrL(r,x,y) ( r.lo = (x.lo >> (y)) | (x.hi << (32-(y))), \
r.hi = x.hi >> (y) )
#define band(r,x,y) ( r.lo = x.lo & y.lo, r.hi = x.hi & y.hi )
#define bxor(r,x,y) ( r.lo = x.lo ^ y.lo, r.hi = x.hi ^ y.hi )
#define bnot(r,x) ( r.lo = ~x.lo, r.hi = ~x.hi )
#define INIT(h,l) { h, l }
#define BUILD(r,h,l) ( r.hi = h, r.lo = l )
#define EXTRACT(h,l,r) ( h = r.hi, l = r.lo )
/* ----------------------------------------------------------------------
* Core SHA512 algorithm: processes 16-doubleword blocks into a
* message digest.
*/
#define Ch(r,t,x,y,z) ( bnot(t,x), band(r,t,z), band(t,x,y), bxor(r,r,t) )
#define Maj(r,t,x,y,z) ( band(r,x,y), band(t,x,z), bxor(r,r,t), \
band(t,y,z), bxor(r,r,t) )
#define bigsigma0(r,t,x) ( rorL(r,x,28), rorB(t,x,34), bxor(r,r,t), \
rorB(t,x,39), bxor(r,r,t) )
#define bigsigma1(r,t,x) ( rorL(r,x,14), rorL(t,x,18), bxor(r,r,t), \
rorB(t,x,41), bxor(r,r,t) )
#define smallsigma0(r,t,x) ( rorL(r,x,1), rorL(t,x,8), bxor(r,r,t), \
shrL(t,x,7), bxor(r,r,t) )
#define smallsigma1(r,t,x) ( rorL(r,x,19), rorB(t,x,61), bxor(r,r,t), \
shrL(t,x,6), bxor(r,r,t) )
static void SHA512_Core_Init(SHA512_State *s)
{
static const uint64 iv[] = {
INIT(0x6a09e667, 0xf3bcc908),
INIT(0xbb67ae85, 0x84caa73b),
INIT(0x3c6ef372, 0xfe94f82b),
INIT(0xa54ff53a, 0x5f1d36f1),
INIT(0x510e527f, 0xade682d1),
INIT(0x9b05688c, 0x2b3e6c1f),
INIT(0x1f83d9ab, 0xfb41bd6b),
INIT(0x5be0cd19, 0x137e2179),
};
int i;
for (i = 0; i < 8; i++)
s->h[i] = iv[i];
}
static void SHA512_Block(SHA512_State *s, uint64 *block)
{
uint64 w[80];
uint64 a,b,c,d,e,f,g,h;
static const uint64 k[] = {
INIT(0x428a2f98, 0xd728ae22), INIT(0x71374491, 0x23ef65cd),
INIT(0xb5c0fbcf, 0xec4d3b2f), INIT(0xe9b5dba5, 0x8189dbbc),
INIT(0x3956c25b, 0xf348b538), INIT(0x59f111f1, 0xb605d019),
INIT(0x923f82a4, 0xaf194f9b), INIT(0xab1c5ed5, 0xda6d8118),
INIT(0xd807aa98, 0xa3030242), INIT(0x12835b01, 0x45706fbe),
INIT(0x243185be, 0x4ee4b28c), INIT(0x550c7dc3, 0xd5ffb4e2),
INIT(0x72be5d74, 0xf27b896f), INIT(0x80deb1fe, 0x3b1696b1),
INIT(0x9bdc06a7, 0x25c71235), INIT(0xc19bf174, 0xcf692694),
INIT(0xe49b69c1, 0x9ef14ad2), INIT(0xefbe4786, 0x384f25e3),
INIT(0x0fc19dc6, 0x8b8cd5b5), INIT(0x240ca1cc, 0x77ac9c65),
INIT(0x2de92c6f, 0x592b0275), INIT(0x4a7484aa, 0x6ea6e483),
INIT(0x5cb0a9dc, 0xbd41fbd4), INIT(0x76f988da, 0x831153b5),
INIT(0x983e5152, 0xee66dfab), INIT(0xa831c66d, 0x2db43210),
INIT(0xb00327c8, 0x98fb213f), INIT(0xbf597fc7, 0xbeef0ee4),
INIT(0xc6e00bf3, 0x3da88fc2), INIT(0xd5a79147, 0x930aa725),
INIT(0x06ca6351, 0xe003826f), INIT(0x14292967, 0x0a0e6e70),
INIT(0x27b70a85, 0x46d22ffc), INIT(0x2e1b2138, 0x5c26c926),
INIT(0x4d2c6dfc, 0x5ac42aed), INIT(0x53380d13, 0x9d95b3df),
INIT(0x650a7354, 0x8baf63de), INIT(0x766a0abb, 0x3c77b2a8),
INIT(0x81c2c92e, 0x47edaee6), INIT(0x92722c85, 0x1482353b),
INIT(0xa2bfe8a1, 0x4cf10364), INIT(0xa81a664b, 0xbc423001),
INIT(0xc24b8b70, 0xd0f89791), INIT(0xc76c51a3, 0x0654be30),
INIT(0xd192e819, 0xd6ef5218), INIT(0xd6990624, 0x5565a910),
INIT(0xf40e3585, 0x5771202a), INIT(0x106aa070, 0x32bbd1b8),
INIT(0x19a4c116, 0xb8d2d0c8), INIT(0x1e376c08, 0x5141ab53),
INIT(0x2748774c, 0xdf8eeb99), INIT(0x34b0bcb5, 0xe19b48a8),
INIT(0x391c0cb3, 0xc5c95a63), INIT(0x4ed8aa4a, 0xe3418acb),
INIT(0x5b9cca4f, 0x7763e373), INIT(0x682e6ff3, 0xd6b2b8a3),
INIT(0x748f82ee, 0x5defb2fc), INIT(0x78a5636f, 0x43172f60),
INIT(0x84c87814, 0xa1f0ab72), INIT(0x8cc70208, 0x1a6439ec),
INIT(0x90befffa, 0x23631e28), INIT(0xa4506ceb, 0xde82bde9),
INIT(0xbef9a3f7, 0xb2c67915), INIT(0xc67178f2, 0xe372532b),
INIT(0xca273ece, 0xea26619c), INIT(0xd186b8c7, 0x21c0c207),
INIT(0xeada7dd6, 0xcde0eb1e), INIT(0xf57d4f7f, 0xee6ed178),
INIT(0x06f067aa, 0x72176fba), INIT(0x0a637dc5, 0xa2c898a6),
INIT(0x113f9804, 0xbef90dae), INIT(0x1b710b35, 0x131c471b),
INIT(0x28db77f5, 0x23047d84), INIT(0x32caab7b, 0x40c72493),
INIT(0x3c9ebe0a, 0x15c9bebc), INIT(0x431d67c4, 0x9c100d4c),
INIT(0x4cc5d4be, 0xcb3e42b6), INIT(0x597f299c, 0xfc657e2a),
INIT(0x5fcb6fab, 0x3ad6faec), INIT(0x6c44198c, 0x4a475817),
};
int t;
for (t = 0; t < 16; t++)
w[t] = block[t];
for (t = 16; t < 80; t++) {
uint64 p, q, r, tmp;
smallsigma1(p, tmp, w[t-2]);
smallsigma0(q, tmp, w[t-15]);
add(r, p, q);
add(p, r, w[t-7]);
add(w[t], p, w[t-16]);
}
a = s->h[0]; b = s->h[1]; c = s->h[2]; d = s->h[3];
e = s->h[4]; f = s->h[5]; g = s->h[6]; h = s->h[7];
for (t = 0; t < 80; t+=8) {
uint64 tmp, p, q, r;
#define ROUND(j,a,b,c,d,e,f,g,h) \
bigsigma1(p, tmp, e); \
Ch(q, tmp, e, f, g); \
add(r, p, q); \
add(p, r, k[j]) ; \
add(q, p, w[j]); \
add(r, q, h); \
bigsigma0(p, tmp, a); \
Maj(tmp, q, a, b, c); \
add(q, tmp, p); \
add(p, r, d); \
d = p; \
add(h, q, r);
ROUND(t+0, a,b,c,d,e,f,g,h);
ROUND(t+1, h,a,b,c,d,e,f,g);
ROUND(t+2, g,h,a,b,c,d,e,f);
ROUND(t+3, f,g,h,a,b,c,d,e);
ROUND(t+4, e,f,g,h,a,b,c,d);
ROUND(t+5, d,e,f,g,h,a,b,c);
ROUND(t+6, c,d,e,f,g,h,a,b);
ROUND(t+7, b,c,d,e,f,g,h,a);
}
{
uint64 tmp;
#define UPDATE(state, local) ( tmp = state, add(state, tmp, local) )
UPDATE(s->h[0], a); UPDATE(s->h[1], b);
UPDATE(s->h[2], c); UPDATE(s->h[3], d);
UPDATE(s->h[4], e); UPDATE(s->h[5], f);
UPDATE(s->h[6], g); UPDATE(s->h[7], h);
}
}
/* ----------------------------------------------------------------------
* Outer SHA512 algorithm: take an arbitrary length byte string,
* convert it into 16-doubleword blocks with the prescribed padding
* at the end, and pass those blocks to the core SHA512 algorithm.
*/
void SHA512_Init(SHA512_State *s)
{
int i;
SHA512_Core_Init(s);
s->blkused = 0;
for (i = 0; i < 4; i++)
s->len[i] = 0;
}
void SHA512_Bytes(SHA512_State *s, const void *p, int len)
{
unsigned char *q = (unsigned char *)p;
uint64 wordblock[16];
uint32_t lenw = len;
int i;
/*
* Update the length field.
*/
for (i = 0; i < 4; i++) {
s->len[i] += lenw;
lenw = (s->len[i] < lenw);
}
if (s->blkused && s->blkused+len < BLKSIZE) {
/*
* Trivial case: just add to the block.
*/
memcpy(s->block + s->blkused, q, len);
s->blkused += len;
} else {
/*
* We must complete and process at least one block.
*/
while (s->blkused + len >= BLKSIZE) {
memcpy(s->block + s->blkused, q, BLKSIZE - s->blkused);
q += BLKSIZE - s->blkused;
len -= BLKSIZE - s->blkused;
/* Now process the block. Gather bytes big-endian into words */
for (i = 0; i < 16; i++) {
uint32_t h, l;
h = ( ((uint32_t)s->block[i*8+0]) << 24 ) |
( ((uint32_t)s->block[i*8+1]) << 16 ) |
( ((uint32_t)s->block[i*8+2]) << 8 ) |
( ((uint32_t)s->block[i*8+3]) << 0 );
l = ( ((uint32_t)s->block[i*8+4]) << 24 ) |
( ((uint32_t)s->block[i*8+5]) << 16 ) |
( ((uint32_t)s->block[i*8+6]) << 8 ) |
( ((uint32_t)s->block[i*8+7]) << 0 );
BUILD(wordblock[i], h, l);
}
SHA512_Block(s, wordblock);
s->blkused = 0;
}
memcpy(s->block, q, len);
s->blkused = len;
}
}
void SHA512_Final(SHA512_State *s, unsigned char *digest)
{
int i;
int pad;
unsigned char c[BLKSIZE];
uint32_t len[4];
if (s->blkused >= BLKSIZE-16)
pad = (BLKSIZE-16) + BLKSIZE - s->blkused;
else
pad = (BLKSIZE-16) - s->blkused;
for (i = 4; i-- ;) {
uint32_t lenhi = s->len[i];
uint32_t lenlo = i > 0 ? s->len[i-1] : 0;
len[i] = (lenhi << 3) | (lenlo >> (32-3));
}
memset(c, 0, pad);
c[0] = 0x80;
SHA512_Bytes(s, &c, pad);
for (i = 0; i < 4; i++) {
c[i*4+0] = char((len[3-i] >> 24) & 0xFF);
c[i*4+1] = char((len[3-i] >> 16) & 0xFF);
c[i*4+2] = char((len[3-i] >> 8) & 0xFF);
c[i*4+3] = char((len[3-i] >> 0) & 0xFF);
}
SHA512_Bytes(s, &c, 16);
for (i = 0; i < 8; i++) {
uint32_t h, l;
EXTRACT(h, l, s->h[i]);
digest[i*8+0] = char((h >> 24) & 0xFF);
digest[i*8+1] = char((h >> 16) & 0xFF);
digest[i*8+2] = char((h >> 8) & 0xFF);
digest[i*8+3] = char((h >> 0) & 0xFF);
digest[i*8+4] = char((l >> 24) & 0xFF);
digest[i*8+5] = char((l >> 16) & 0xFF);
digest[i*8+6] = char((l >> 8) & 0xFF);
digest[i*8+7] = char((l >> 0) & 0xFF);
}
}
void SHA512_Simple(const void *p, int len, unsigned char *output) {
SHA512_State s;
SHA512_Init(&s);
SHA512_Bytes(&s, p, len);
SHA512_Final(&s, output);
}
#ifdef TEST
#include <cstdio>
#include <cstdlib>
int main(void) {
unsigned char digest[64];
int i, j, errors;
struct {
const char *teststring;
unsigned char digest512[64];
} tests[] = {
{ "abc", {
0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba,
0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8,
0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e,
0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f,
} },
{ "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", {
0x8e, 0x95, 0x9b, 0x75, 0xda, 0xe3, 0x13, 0xda,
0x8c, 0xf4, 0xf7, 0x28, 0x14, 0xfc, 0x14, 0x3f,
0x8f, 0x77, 0x79, 0xc6, 0xeb, 0x9f, 0x7f, 0xa1,
0x72, 0x99, 0xae, 0xad, 0xb6, 0x88, 0x90, 0x18,
0x50, 0x1d, 0x28, 0x9e, 0x49, 0x00, 0xf7, 0xe4,
0x33, 0x1b, 0x99, 0xde, 0xc4, 0xb5, 0x43, 0x3a,
0xc7, 0xd3, 0x29, 0xee, 0xb6, 0xdd, 0x26, 0x54,
0x5e, 0x96, 0xe5, 0x5b, 0x87, 0x4b, 0xe9, 0x09,
} },
{ NULL, {
0xe7, 0x18, 0x48, 0x3d, 0x0c, 0xe7, 0x69, 0x64,
0x4e, 0x2e, 0x42, 0xc7, 0xbc, 0x15, 0xb4, 0x63,
0x8e, 0x1f, 0x98, 0xb1, 0x3b, 0x20, 0x44, 0x28,
0x56, 0x32, 0xa8, 0x03, 0xaf, 0xa9, 0x73, 0xeb,
0xde, 0x0f, 0xf2, 0x44, 0x87, 0x7e, 0xa6, 0x0a,
0x4c, 0xb0, 0x43, 0x2c, 0xe5, 0x77, 0xc3, 0x1b,
0xeb, 0x00, 0x9c, 0x5c, 0x2c, 0x49, 0xaa, 0x2e,
0x4e, 0xad, 0xb2, 0x17, 0xad, 0x8c, 0xc0, 0x9b,
} },
};
errors = 0;
for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) {
if (tests[i].teststring) {
SHA512_Simple(tests[i].teststring,
strlen(tests[i].teststring), digest);
} else {
SHA512_State s;
int n;
SHA512_Init(&s);
for (n = 0; n < 1000000 / 40; n++)
SHA512_Bytes(&s, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
40);
SHA512_Final(&s, digest);
}
for (j = 0; j < 64; j++) {
if (digest[j] != tests[i].digest512[j]) {
fprintf(stderr,
"\"%s\" digest512 byte %d should be 0x%02x, is 0x%02x\n",
tests[i].teststring, j, tests[i].digest512[j],
digest[j]);
errors++;
}
}
}
printf("%d errors\n", errors);
return 0;
}
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-49
View File
@@ -1,49 +0,0 @@
#ifndef SSH_SHA512_H
#define SSH_SHA512_H
typedef struct
{
unsigned long hi, lo;
} uint64, int64;
typedef struct
{
uint64 h[8];
unsigned char block[128];
int blkused;
uint32_t len[4];
} SHA512_State;
void SHA512_Init(SHA512_State * s);
void SHA512_Bytes(SHA512_State * s, const void *p, int len);
void SHA512_Final(SHA512_State * s, unsigned char *output);
void SHA512_Simple(const void *p, int len, unsigned char *output);
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-218
View File
@@ -1,218 +0,0 @@
/*
* SHA1 hash algorithm. Used in SSH2 as a MAC, and the transform is
* also used as a `stirring' function for the PuTTY random number
* pool. Implemented directly from the specification by Simon
* Tatham.
*/
#include "global.h"
#include "CryptSHA.h"
/* ----------------------------------------------------------------------
* Core SHA algorithm: processes 16-word blocks into a message digest.
*/
#define rol(x,y) ( ((x) << (y)) | (((uint32_t)x) >> (32-y)) )
static void SHA_Core_Init(uint32_t h[5])
{
h[0] = 0x67452301;
h[1] = 0xefcdab89;
h[2] = 0x98badcfe;
h[3] = 0x10325476;
h[4] = 0xc3d2e1f0;
}
void SHATransform(unsigned int *digest, unsigned int *block)
{
unsigned int w[80];
unsigned int a, b, c, d, e;
int t;
for (t = 0; t < 16; t++)
w[t] = block[t];
for (t = 16; t < 80; t++) {
unsigned int tmp = w[t - 3] ^ w[t - 8] ^ w[t - 14] ^ w[t - 16];
w[t] = rol(tmp, 1);
}
a = digest[0];
b = digest[1];
c = digest[2];
d = digest[3];
e = digest[4];
for (t = 0; t < 20; t++) {
unsigned int tmp =
rol(a, 5) + ((b & c) | (d & ~b)) + e + w[t] + 0x5a827999;
e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
}
for (t = 20; t < 40; t++) {
unsigned int tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0x6ed9eba1;
e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
}
for (t = 40; t < 60; t++) {
unsigned int tmp = rol(a,
5) + ((b & c) | (b & d) | (c & d)) + e + w[t] +
0x8f1bbcdc;
e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
}
for (t = 60; t < 80; t++) {
unsigned int tmp = rol(a, 5) + (b ^ c ^ d) + e + w[t] + 0xca62c1d6;
e = d;
d = c;
c = rol(b, 30);
b = a;
a = tmp;
}
digest[0] += a;
digest[1] += b;
digest[2] += c;
digest[3] += d;
digest[4] += e;
}
/* ----------------------------------------------------------------------
* Outer SHA algorithm: take an arbitrary length byte string,
* convert it into 16-word blocks with the prescribed padding at
* the end, and pass those blocks to the core SHA algorithm.
*/
void SHA_Init(SHA_State * s)
{
SHA_Core_Init(s->h);
s->blkused = 0;
s->lenhi = s->lenlo = 0;
}
void SHA_Bytes(SHA_State * s, const void *p, int len)
{
unsigned char *q = (unsigned char *) p;
uint32_t wordblock[16];
uint32_t lenw = len;
int i;
/*
* Update the length field.
*/
s->lenlo += lenw;
s->lenhi += (s->lenlo < lenw);
if (s->blkused && s->blkused + len < 64) {
/*
* Trivial case: just add to the block.
*/
memcpy(s->block + s->blkused, q, len);
s->blkused += len;
} else {
/*
* We must complete and process at least one block.
*/
while (s->blkused + len >= 64) {
memcpy(s->block + s->blkused, q, 64 - s->blkused);
q += 64 - s->blkused;
len -= 64 - s->blkused;
/* Now process the block. Gather bytes big-endian into words */
for (i = 0; i < 16; i++) {
wordblock[i] =
(((uint32_t) s->block[i * 4 + 0]) << 24) |
(((uint32_t) s->block[i * 4 + 1]) << 16) |
(((uint32_t) s->block[i * 4 + 2]) << 8) |
(((uint32_t) s->block[i * 4 + 3]) << 0);
}
SHATransform((unsigned int *)s->h, (unsigned int *)wordblock);
s->blkused = 0;
}
memcpy(s->block, q, len);
s->blkused = len;
}
}
void SHA_Final(SHA_State * s, unsigned char *output)
{
int i;
int pad;
unsigned char c[64];
uint32_t lenhi, lenlo;
if (s->blkused >= 56)
pad = 56 + 64 - s->blkused;
else
pad = 56 - s->blkused;
lenhi = (s->lenhi << 3) | (s->lenlo >> (32 - 3));
lenlo = (s->lenlo << 3);
memset(c, 0, pad);
c[0] = 0x80;
SHA_Bytes(s, &c, pad);
c[0] = char((lenhi >> 24) & 0xFF);
c[1] = char((lenhi >> 16) & 0xFF);
c[2] = char((lenhi >> 8) & 0xFF);
c[3] = char((lenhi >> 0) & 0xFF);
c[4] = char((lenlo >> 24) & 0xFF);
c[5] = char((lenlo >> 16) & 0xFF);
c[6] = char((lenlo >> 8) & 0xFF);
c[7] = char((lenlo >> 0) & 0xFF);
SHA_Bytes(s, &c, 8);
for (i = 0; i < 5; i++)
{
output[i * 4] = char((s->h[i] >> 24) & 0xFF);
output[i * 4 + 1] = char((s->h[i] >> 16) & 0xFF);
output[i * 4 + 2] = char((s->h[i] >> 8) & 0xFF);
output[i * 4 + 3] = char((s->h[i]) & 0xFF);
}
}
void SHA_Simple(const void *p, int len, unsigned char *output)
{
SHA_State s;
SHA_Init(&s);
SHA_Bytes(&s, p, len);
SHA_Final(&s, output);
}
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-44
View File
@@ -1,44 +0,0 @@
#ifndef SSHSHA_H
#define SSHSHA_H
typedef struct {
uint32_t h[5];
unsigned char block[64];
int blkused;
uint32_t lenhi, lenlo;
} SHA_State;
void SHA_Init(SHA_State * s);
void SHA_Bytes(SHA_State * s, const void *p, int len);
void SHA_Final(SHA_State * s, unsigned char *output);
void SHA_Simple(const void *p, int len, unsigned char *output);
void SHATransform(unsigned int *digest, unsigned int *block);
#endif
/*
* PuTTY is copyright 1997-2001 Simon Tatham.
*
* Portions copyright Robert de Bath, Joris van Rantwijk, Delian
* Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry,
* Justin Bradford, and CORE SDI S.A.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation files
* (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
-1
View File
@@ -1 +0,0 @@
Baptiste Lepilleur <[email protected]>
-1
View File
@@ -1 +0,0 @@
The json-cpp library and this documentation are in Public Domain.
-117
View File
@@ -1,117 +0,0 @@
* Introduction:
=============
JSON (JavaScript Object Notation) is a lightweight data-interchange format.
It can represent integer, real number, string, an ordered sequence of
value, and a collection of name/value pairs.
JsonCpp is a simple API to manipulate JSON value, handle serialization
and unserialization to string.
It can also preserve existing comment in unserialization/serialization steps,
making it a convenient format to store user input files.
Unserialization parsing is user friendly and provides precise error reports.
* Building/Testing:
=================
JsonCpp uses Scons (http://www.scons.org) as a build system. Scons requires
python to be installed (http://www.python.org).
You download scons-local distribution from the following url:
http://sourceforge.net/project/showfiles.php?group_id=30337&package_id=67375
Unzip it in the directory where you found this README file. scons.py Should be
at the same level as README.
python scons.py platform=PLTFRM [TARGET]
where PLTFRM may be one of:
suncc Sun C++ (Solaris)
vacpp Visual Age C++ (AIX)
mingw
msvc6 Microsoft Visual Studio 6 service pack 5-6
msvc70 Microsoft Visual Studio 2002
msvc71 Microsoft Visual Studio 2003
msvc80 Microsoft Visual Studio 2005
linux-gcc Gnu C++ (linux, also reported to work for Mac OS X)
adding platform is fairly simple. You need to change the Sconstruct file
to do so.
and TARGET may be:
check: build library and run unit tests.
* Running the test manually:
==========================
cd test
# This will run the Reader/Writer tests
python runjsontests.py "path to jsontest.exe"
# This will run the Reader/Writer tests, using JSONChecker test suite
# (http://www.json.org/JSON_checker/).
# Notes: not all tests pass: JsonCpp is too lenient (for example,
# it allows an integer to start with '0'). The goal is to improve
# strict mode parsing to get all tests to pass.
python runjsontests.py --with-json-checker "path to jsontest.exe"
# This will run the unit tests (mostly Value)
python rununittests.py "path to test_lib_json.exe"
You can run the tests using valgrind:
python rununittests.py --valgrind "path to test_lib_json.exe"
* Building the documentation:
===========================
Run the python script doxybuild.py from the top directory:
python doxybuild.py --open --with-dot
See doxybuild.py --help for options.
* Adding a reader/writer test:
============================
To add a test, you need to create two files in test/data:
- a TESTNAME.json file, that contains the input document in JSON format.
- a TESTNAME.expected file, that contains a flatened representation of
the input document.
TESTNAME.expected file format:
- each line represents a JSON element of the element tree represented
by the input document.
- each line has two parts: the path to access the element separated from
the element value by '='. Array and object values are always empty
(e.g. represented by either [] or {}).
- element path: '.' represented the root element, and is used to separate
object members. [N] is used to specify the value of an array element
at index N.
See test_complex_01.json and test_complex_01.expected to better understand
element path.
* Understanding reader/writer test output:
========================================
When a test is run, output files are generated aside the input test files.
Below is a short description of the content of each file:
- test_complex_01.json: input JSON document
- test_complex_01.expected: flattened JSON element tree used to check if
parsing was corrected.
- test_complex_01.actual: flattened JSON element tree produced by
jsontest.exe from reading test_complex_01.json
- test_complex_01.rewrite: JSON document written by jsontest.exe using the
Json::Value parsed from test_complex_01.json and serialized using
Json::StyledWritter.
- test_complex_01.actual-rewrite: flattened JSON element tree produced by
jsontest.exe from reading test_complex_01.rewrite.
test_complex_01.process-output: jsontest.exe output, typically useful to
understand parsing error.
File diff suppressed because it is too large Load Diff
-23
View File
@@ -1,23 +0,0 @@
<hr>
<table width="100%">
<tr>
<td width="10%" align="left" valign="center">
<a href="http://sourceforge.net">
<img
src="http://sourceforge.net/sflogo.php?group_id=144446"
width="88" height="31" border="0" alt="SourceForge Logo"></a>
</td>
<td width="20%" align="left" valign="center">
hosts this site.
</td>
<td>
</td>
<td align="right" valign="center">
Send comments to:<br>
<a href="mailto:[email protected]">Json-cpp Developers</a>
</td>
</tr>
</table>
</body>
</html>
-24
View File
@@ -1,24 +0,0 @@
<html>
<head>
<title>
JsonCpp - JSON data format manipulation library
</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
<link href="tabs.css" rel="stylesheet" type="text/css">
</head>
<body bgcolor="#ffffff">
<table width="100%">
<tr>
<td width="40%" align="left" valign="center">
<a href="http://sourceforge.net/projects/jsoncpp">
JsonCpp project page
</a>
</td>
<td width="40%" align="right" valign="center">
<a href="http://jsoncpp.sourceforge.net">JsonCpp home page</a>
</td>
</tr>
</table>
<hr>
-116
View File
@@ -1,116 +0,0 @@
/**
\mainpage
\section _intro Introduction
<a HREF="http://www.json.org/">JSON (JavaScript Object Notation)</a>
is a lightweight data-interchange format.
It can represent integer, real number, string, an ordered sequence of value, and
a collection of name/value pairs.
Here is an example of JSON data:
\verbatim
// Configuration options
{
// Default encoding for text
"encoding" : "UTF-8",
// Plug-ins loaded at start-up
"plug-ins" : [
"python",
"c++",
"ruby"
],
// Tab indent size
"indent" : { "length" : 3, "use_space" = true }
}
\endverbatim
\section _features Features
- read and write JSON document
- attach C and C++ style comments to element during parsing
- rewrite JSON document preserving original comments
Notes: Comments used to be supported in JSON but where removed for
portability (C like comments are not supported in Python). Since
comments are useful in configuration/input file, this feature was
preserved.
\section _example Code example
\code
Json::Value root; // will contains the root value after parsing.
Json::Reader reader;
bool parsingSuccessful = reader.parse( config_doc, root );
if ( !parsingSuccessful )
{
// report to the user the failure and their locations in the document.
std::cout << "Failed to parse configuration\n"
<< reader.getFormatedErrorMessages();
return;
}
// Get the value of the member of root named 'encoding', return 'UTF-8' if there is no
// such member.
std::string encoding = root.get("encoding", "UTF-8" ).asString();
// Get the value of the member of root named 'encoding', return a 'null' value if
// there is no such member.
const Json::Value plugins = root["plug-ins"];
for ( int index = 0; index < plugins.size(); ++index ) // Iterates over the sequence elements.
loadPlugIn( plugins[index].asString() );
setIndentLength( root["indent"].get("length", 3).asInt() );
setIndentUseSpace( root["indent"].get("use_space", true).asBool() );
// ...
// At application shutdown to make the new configuration document:
// Since Json::Value has implicit constructor for all value types, it is not
// necessary to explicitly construct the Json::Value object:
root["encoding"] = getCurrentEncoding();
root["indent"]["length"] = getCurrentIndentLength();
root["indent"]["use_space"] = getCurrentIndentUseSpace();
Json::StyledWriter writer;
// Make a new JSON document for the configuration. Preserve original comments.
std::string outputConfig = writer.write( root );
// You can also use streams. This will put the contents of any JSON
// stream at a particular sub-value, if you'd like.
std::cin >> root["subtree"];
// And you can write to a stream, using the StyledWriter automatically.
std::cout << root;
\endcode
\section _plinks Build instructions
The build instructions are located in the file
<a HREF="README.txt">README.txt</a> in the top-directory of the project.
Permanent link to the latest revision of the file in subversion:
<a HREF="http://svn.sourceforge.net/viewcvs.cgi/jsoncpp/README.txt?view=markup">latest README.txt</a>
\section _pdownload Download
The sources can be downloaded from
<a HREF="http://sourceforge.net/projects/jsoncpp/files/">SourceForge download page</a>.
The latest version of the source is available in the project's subversion repository:
<a HREF="http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/">
http://jsoncpp.svn.sourceforge.net/svnroot/jsoncpp/trunk/</a>
To checkout the source, see the following
<a HREF="http://sourceforge.net/scm/?type=svn&group_id=144446">instructions</a>.
\section _plinks Project links
- <a HREF="http://jsoncpp.sourceforge.net">json-cpp home</a>
- <a HREF="http://www.sourceforge.net/projects/jsoncpp">json-cpp sourceforge project</a>
\section _rlinks Related links
- <a HREF="http://www.json.org/">JSON</a> Specification and alternate language implementations.
- <a HREF="http://www.yaml.org/">YAML</a> A data format designed for human readability.
- <a HREF="http://www.cl.cam.ac.uk/~mgk25/unicode.html">UTF-8 and Unicode FAQ</a>.
\section _license License
The json-cpp library and this documentation are in Public Domain.
\author Baptiste Lepilleur <[email protected]>
*/
-1
View File
@@ -1 +0,0 @@
The documentation is generated using doxygen (http://www.doxygen.org).
-32
View File
@@ -1,32 +0,0 @@
/*! \page roadmap JsonCpp roadmap
\section ms_release Makes JsonCpp ready for release
- Build system clean-up:
- Fix build on Windows (shared-library build is broken)
- Add enable/disable flag for static and shared library build
- Enhance help
- Platform portability check: (Notes: was ok on last check)
- linux/gcc,
- solaris/cc,
- windows/msvc678,
- aix/vacpp
- Add JsonCpp version to header as numeric for use in preprocessor test
- Remove buggy experimental hash stuff
- Release on sourceforge download
\section ms_strict Adds a strict mode to reader/parser
Strict JSON support as specific in RFC 4627 (http://www.ietf.org/rfc/rfc4627.txt?number=4627).
- Enforce only object or array as root element
- Disable comment support
- Get jsonchecker failing tests to pass in strict mode
\section ms_separation Expose json reader/writer API that do not impose using Json::Value.
Some typical use-case involve an application specific structure to/from a JSON document.
- Event base parser to allow unserializing a Json document directly in datastructure instead of
using the intermediate Json::Value.
- "Stream" based parser to serialized a Json document without using Json::Value as input.
- Performance oriented parser/writer:
- Provides an event based parser. Should allow pulling & skipping events for ease of use.
- Provides a JSON document builder: fast only.
\section ms_perfo Performance tuning
- Provides support for static property name definition avoiding allocation
- Static property dictionnary can be provided to JSON reader
- Performance scenario & benchmarking
*/
-19
View File
@@ -1,19 +0,0 @@
#ifndef JSON_AUTOLINK_H_INCLUDED
# define JSON_AUTOLINK_H_INCLUDED
# include "config.h"
# ifdef JSON_IN_CPPTL
# include <cpptl/cpptl_autolink.h>
# endif
# if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && !defined(JSON_IN_CPPTL)
# define CPPTL_AUTOLINK_NAME "json"
# undef CPPTL_AUTOLINK_DLL
# ifdef JSON_DLL
# define CPPTL_AUTOLINK_DLL
# endif
# include "autolink.h"
# endif
#endif // JSON_AUTOLINK_H_INCLUDED
-43
View File
@@ -1,43 +0,0 @@
#ifndef JSON_CONFIG_H_INCLUDED
# define JSON_CONFIG_H_INCLUDED
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
/// If defined, indicates that Json specific container should be used
/// (hash table & simple deque container with customizable allocator).
/// THIS FEATURE IS STILL EXPERIMENTAL!
//# define JSON_VALUE_USE_INTERNAL_MAP 1
/// Force usage of standard new/malloc based allocator instead of memory pool based allocator.
/// The memory pools allocator used optimization (initializing Value and ValueInternalLink
/// as if it was a POD) that may cause some validation tool to report errors.
/// Only has effects if JSON_VALUE_USE_INTERNAL_MAP is defined.
//# define JSON_USE_SIMPLE_INTERNAL_ALLOCATOR 1
/// If defined, indicates that Json use exception to report invalid type manipulation
/// instead of C assert macro.
# define JSON_USE_EXCEPTION 1
# ifdef JSON_IN_CPPTL
# include <cpptl/config.h>
# ifndef JSON_USE_CPPTL
# define JSON_USE_CPPTL 1
# endif
# endif
# ifdef JSON_IN_CPPTL
# define JSON_API CPPTL_API
# elif defined(JSON_DLL_BUILD)
# define JSON_API __declspec(dllexport)
# elif defined(JSON_DLL)
# define JSON_API __declspec(dllimport)
# else
# define JSON_API
# endif
#endif // JSON_CONFIG_H_INCLUDED
-42
View File
@@ -1,42 +0,0 @@
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
# define CPPTL_JSON_FEATURES_H_INCLUDED
# include "forwards.h"
namespace Json {
/** \brief Configuration passed to reader and writer.
* This configuration object can be used to force the Reader or Writer
* to behave in a standard conforming way.
*/
class JSON_API Features
{
public:
/** \brief A configuration that allows all features and assumes all strings are UTF-8.
* - C & C++ comments are allowed
* - Root object can be any JSON value
* - Assumes Value strings are encoded in UTF-8
*/
static Features all();
/** \brief A configuration that is strictly compatible with the JSON specification.
* - Comments are forbidden.
* - Root object must be either an array or an object value.
* - Assumes Value strings are encoded in UTF-8
*/
static Features strictMode();
/** \brief Initialize the configuration like JsonConfig::allFeatures;
*/
Features();
/// \c true if comments are allowed. Default: \c true.
bool allowComments_;
/// \c true if root must be either an array or an object value. Default: \c false.
bool strictRoot_;
};
} // namespace Json
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
-39
View File
@@ -1,39 +0,0 @@
#ifndef JSON_FORWARDS_H_INCLUDED
# define JSON_FORWARDS_H_INCLUDED
# include "config.h"
namespace Json {
// writer.h
class FastWriter;
class StyledWriter;
// reader.h
class Reader;
// features.h
class Features;
// value.h
typedef int Int;
typedef unsigned int UInt;
class StaticString;
class Path;
class PathArgument;
class Value;
class ValueIteratorBase;
class ValueIterator;
class ValueConstIterator;
#ifdef JSON_VALUE_USE_INTERNAL_MAP
class ValueAllocator;
class ValueMapAllocator;
class ValueInternalLink;
class ValueInternalArray;
class ValueInternalMap;
#endif // #ifdef JSON_VALUE_USE_INTERNAL_MAP
} // namespace Json
#endif // JSON_FORWARDS_H_INCLUDED
-10
View File
@@ -1,10 +0,0 @@
#ifndef JSON_JSON_H_INCLUDED
# define JSON_JSON_H_INCLUDED
# include "autolink.h"
# include "value.h"
# include "reader.h"
# include "writer.h"
# include "features.h"
#endif // JSON_JSON_H_INCLUDED
-196
View File
@@ -1,196 +0,0 @@
#ifndef CPPTL_JSON_READER_H_INCLUDED
# define CPPTL_JSON_READER_H_INCLUDED
# include "features.h"
# include "value.h"
# include <deque>
# include <stack>
# include <string>
# include <iostream>
namespace Json {
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a Value.
*
*/
class JSON_API Reader
{
public:
typedef char Char;
typedef const Char *Location;
/** \brief Constructs a Reader allowing all features
* for parsing.
*/
Reader();
/** \brief Constructs a Reader allowing the specified feature set
* for parsing.
*/
Reader( const Features &features );
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
* \param document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was
* successfully parsed.
* \param collectComments \c true to collect comment and allow writing them back during
* serialization, \c false to discard comments.
* This parameter is ignored if Features::allowComments_
* is \c false.
* \return \c true if the document was successfully parsed, \c false if an error occurred.
*/
bool parse( const std::string &document,
Value &root,
bool collectComments = true );
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a> document.
* \param document UTF-8 encoded string containing the document to read.
* \param root [out] Contains the root value of the document if it was
* successfully parsed.
* \param collectComments \c true to collect comment and allow writing them back during
* serialization, \c false to discard comments.
* This parameter is ignored if Features::allowComments_
* is \c false.
* \return \c true if the document was successfully parsed, \c false if an error occurred.
*/
bool parse( const char *beginDoc, const char *endDoc,
Value &root,
bool collectComments = true );
/// \brief Parse from input stream.
/// \see Json::operator>>(std::istream&, Json::Value&).
bool parse( std::istream &is,
Value &root,
bool collectComments = true );
/** \brief Returns a user friendly string that list errors in the parsed document.
* \return Formatted error message with the list of errors with their location in
* the parsed document. An empty string is returned if no error occurred
* during parsing.
*/
std::string getFormatedErrorMessages() const;
private:
enum TokenType
{
tokenEndOfStream = 0,
tokenObjectBegin,
tokenObjectEnd,
tokenArrayBegin,
tokenArrayEnd,
tokenString,
tokenNumber,
tokenTrue,
tokenFalse,
tokenNull,
tokenArraySeparator,
tokenMemberSeparator,
tokenComment,
tokenError
};
class Token
{
public:
TokenType type_;
Location start_;
Location end_;
};
class ErrorInfo
{
public:
Token token_;
std::string message_;
Location extra_;
};
typedef std::deque<ErrorInfo> Errors;
bool expectToken( TokenType type, Token &token, const char *message );
bool readToken( Token &token );
void skipSpaces();
bool match( Location pattern,
int patternLength );
bool readComment();
bool readCStyleComment();
bool readCppStyleComment();
bool readString();
void readNumber();
bool readValue();
bool readObject( Token &token );
bool readArray( Token &token );
bool decodeNumber( Token &token );
bool decodeString( Token &token );
bool decodeString( Token &token, std::string &decoded );
bool decodeDouble( Token &token );
bool decodeUnicodeCodePoint( Token &token,
Location &current,
Location end,
unsigned int &unicode );
bool decodeUnicodeEscapeSequence( Token &token,
Location &current,
Location end,
unsigned int &unicode );
bool addError( const std::string &message,
Token &token,
Location extra = 0 );
bool recoverFromError( TokenType skipUntilToken );
bool addErrorAndRecover( const std::string &message,
Token &token,
TokenType skipUntilToken );
void skipUntilSpace();
Value &currentValue();
Char getNextChar();
void getLocationLineAndColumn( Location location,
int &line,
int &column ) const;
std::string getLocationLineAndColumn( Location location ) const;
void addComment( Location begin,
Location end,
CommentPlacement placement );
void skipCommentTokens( Token &token );
typedef std::stack<Value *> Nodes;
Nodes nodes_;
Errors errors_;
std::string document_;
Location begin_;
Location end_;
Location current_;
Location lastValueEnd_;
Value *lastValue_;
std::string commentsBefore_;
Features features_;
bool collectComments_;
};
/** \brief Read from 'sin' into 'root'.
Always keep comments from the input JSON.
This can be used to read a file into a particular sub-object.
For example:
\code
Json::Value root;
cin >> root["dir"]["file"];
cout << root;
\endcode
Result:
\verbatim
{
"dir": {
"file": {
// The input stream JSON would be nested here.
}
}
}
\endverbatim
\throw std::exception on parse error.
\see Json::operator<<()
*/
std::istream& operator>>( std::istream&, Value& );
} // namespace Json
#endif // CPPTL_JSON_READER_H_INCLUDED
File diff suppressed because it is too large Load Diff
-174
View File
@@ -1,174 +0,0 @@
#ifndef JSON_WRITER_H_INCLUDED
# define JSON_WRITER_H_INCLUDED
# include "value.h"
# include <vector>
# include <string>
# include <iostream>
namespace Json {
class Value;
/** \brief Abstract class for writers.
*/
class JSON_API Writer
{
public:
virtual ~Writer();
virtual std::string write( const Value &root ) = 0;
};
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format without formatting (not human friendly).
*
* The JSON document is written in a single line. It is not intended for 'human' consumption,
* but may be usefull to support feature such as RPC where bandwith is limited.
* \sa Reader, Value
*/
class JSON_API FastWriter : public Writer
{
public:
FastWriter();
virtual ~FastWriter(){}
void enableYAMLCompatibility();
public: // overridden from Writer
virtual std::string write( const Value &root );
private:
void writeValue( const Value &value );
std::string document_;
bool yamlCompatiblityEnabled_;
};
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way.
*
* The rules for line break and indent are as follow:
* - Object value:
* - if empty then print {} without indent and line break
* - if not empty the print '{', line break & indent, print one value per line
* and then unindent and line break and print '}'.
* - Array value:
* - if empty then print [] without indent and line break
* - if the array contains no object value, empty array or some other value types,
* and all the values fit on one lines, then print the array on a single line.
* - otherwise, it the values do not fit on one line, or the array contains
* object or non empty array, then print one value per line.
*
* If the Value have comments then they are outputed according to their #CommentPlacement.
*
* \sa Reader, Value, Value::setComment()
*/
class JSON_API StyledWriter: public Writer
{
public:
StyledWriter();
virtual ~StyledWriter(){}
public: // overridden from Writer
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param root Value to serialize.
* \return String containing the JSON document that represents the root value.
*/
virtual std::string write( const Value &root );
private:
void writeValue( const Value &value );
void writeArrayValue( const Value &value );
bool isMultineArray( const Value &value );
void pushValue( const std::string &value );
void writeIndent();
void writeWithIndent( const std::string &value );
void indent();
void unindent();
void writeCommentBeforeValue( const Value &root );
void writeCommentAfterValueOnSameLine( const Value &root );
bool hasCommentForValue( const Value &value );
static std::string normalizeEOL( const std::string &text );
typedef std::vector<std::string> ChildValues;
ChildValues childValues_;
std::string document_;
std::string indentString_;
int rightMargin_;
int indentSize_;
bool addChildValues_;
};
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a human friendly way,
to a stream rather than to a string.
*
* The rules for line break and indent are as follow:
* - Object value:
* - if empty then print {} without indent and line break
* - if not empty the print '{', line break & indent, print one value per line
* and then unindent and line break and print '}'.
* - Array value:
* - if empty then print [] without indent and line break
* - if the array contains no object value, empty array or some other value types,
* and all the values fit on one lines, then print the array on a single line.
* - otherwise, it the values do not fit on one line, or the array contains
* object or non empty array, then print one value per line.
*
* If the Value have comments then they are outputed according to their #CommentPlacement.
*
* \param indentation Each level will be indented by this amount extra.
* \sa Reader, Value, Value::setComment()
*/
class JSON_API StyledStreamWriter
{
public:
StyledStreamWriter( std::string indentation="\t" );
~StyledStreamWriter(){}
public:
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param out Stream to write to. (Can be ostringstream, e.g.)
* \param root Value to serialize.
* \note There is no point in deriving from Writer, since write() should not return a value.
*/
void write( std::ostream &out, const Value &root );
private:
void writeValue( const Value &value );
void writeArrayValue( const Value &value );
bool isMultineArray( const Value &value );
void pushValue( const std::string &value );
void writeIndent();
void writeWithIndent( const std::string &value );
void indent();
void unindent();
void writeCommentBeforeValue( const Value &root );
void writeCommentAfterValueOnSameLine( const Value &root );
bool hasCommentForValue( const Value &value );
static std::string normalizeEOL( const std::string &text );
typedef std::vector<std::string> ChildValues;
ChildValues childValues_;
std::ostream* document_;
std::string indentString_;
int rightMargin_;
std::string indentation_;
bool addChildValues_;
};
std::string JSON_API valueToString( Int value );
std::string JSON_API valueToString( UInt value );
std::string JSON_API valueToString( double value );
std::string JSON_API valueToString( bool value );
std::string JSON_API valueToQuotedString( const char *value );
/// \brief Output using the StyledStreamWriter.
/// \see Json::operator>>()
std::ostream& operator<<( std::ostream&, const Value &root );
} // namespace Json
#endif // JSON_WRITER_H_INCLUDED
@@ -1,125 +0,0 @@
#ifndef JSONCPP_BATCHALLOCATOR_H_INCLUDED
# define JSONCPP_BATCHALLOCATOR_H_INCLUDED
# include <stdlib.h>
# include <assert.h>
# ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
namespace Json {
/* Fast memory allocator.
*
* This memory allocator allocates memory for a batch of object (specified by
* the page size, the number of object in each page).
*
* It does not allow the destruction of a single object. All the allocated objects
* can be destroyed at once. The memory can be either released or reused for future
* allocation.
*
* The in-place new operator must be used to construct the object using the pointer
* returned by allocate.
*/
template<typename AllocatedType
,const unsigned int objectPerAllocation>
class BatchAllocator
{
public:
typedef AllocatedType Type;
BatchAllocator( unsigned int objectsPerPage = 255 )
: freeHead_( 0 )
, objectsPerPage_( objectsPerPage )
{
// printf( "Size: %d => %s\n", sizeof(AllocatedType), typeid(AllocatedType).name() );
assert( sizeof(AllocatedType) * objectPerAllocation >= sizeof(AllocatedType *) ); // We must be able to store a slist in the object free space.
assert( objectsPerPage >= 16 );
batches_ = allocateBatch( 0 ); // allocated a dummy page
currentBatch_ = batches_;
}
~BatchAllocator()
{
for ( BatchInfo *batch = batches_; batch; )
{
BatchInfo *nextBatch = batch->next_;
free( batch );
batch = nextBatch;
}
}
/// allocate space for an array of objectPerAllocation object.
/// @warning it is the responsability of the caller to call objects constructors.
AllocatedType *allocate()
{
if ( freeHead_ ) // returns node from free list.
{
AllocatedType *object = freeHead_;
freeHead_ = *(AllocatedType **)object;
return object;
}
if ( currentBatch_->used_ == currentBatch_->end_ )
{
currentBatch_ = currentBatch_->next_;
while ( currentBatch_ && currentBatch_->used_ == currentBatch_->end_ )
currentBatch_ = currentBatch_->next_;
if ( !currentBatch_ ) // no free batch found, allocate a new one
{
currentBatch_ = allocateBatch( objectsPerPage_ );
currentBatch_->next_ = batches_; // insert at the head of the list
batches_ = currentBatch_;
}
}
AllocatedType *allocated = currentBatch_->used_;
currentBatch_->used_ += objectPerAllocation;
return allocated;
}
/// Release the object.
/// @warning it is the responsability of the caller to actually destruct the object.
void release( AllocatedType *object )
{
assert( object != 0 );
*(AllocatedType **)object = freeHead_;
freeHead_ = object;
}
private:
struct BatchInfo
{
BatchInfo *next_;
AllocatedType *used_;
AllocatedType *end_;
AllocatedType buffer_[objectPerAllocation];
};
// disabled copy constructor and assignement operator.
BatchAllocator( const BatchAllocator & );
void operator =( const BatchAllocator &);
static BatchInfo *allocateBatch( unsigned int objectsPerPage )
{
const unsigned int mallocSize = sizeof(BatchInfo) - sizeof(AllocatedType)* objectPerAllocation
+ sizeof(AllocatedType) * objectPerAllocation * objectsPerPage;
BatchInfo *batch = static_cast<BatchInfo*>( malloc( mallocSize ) );
batch->next_ = 0;
batch->used_ = batch->buffer_;
batch->end_ = batch->buffer_ + objectsPerPage;
return batch;
}
BatchInfo *batches_;
BatchInfo *currentBatch_;
/// Head of a single linked list within the allocated space of freeed object
AllocatedType *freeHead_;
unsigned int objectsPerPage_;
};
} // namespace Json
# endif // ifndef JSONCPP_DOC_INCLUDE_IMPLEMENTATION
#endif // JSONCPP_BATCHALLOCATOR_H_INCLUDED
@@ -1,448 +0,0 @@
// included by json_value.cpp
// everything is within Json namespace
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class ValueInternalArray
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
ValueArrayAllocator::~ValueArrayAllocator()
{
}
// //////////////////////////////////////////////////////////////////
// class DefaultValueArrayAllocator
// //////////////////////////////////////////////////////////////////
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
class DefaultValueArrayAllocator : public ValueArrayAllocator
{
public: // overridden from ValueArrayAllocator
virtual ~DefaultValueArrayAllocator()
{
}
virtual ValueInternalArray *newArray()
{
return new ValueInternalArray();
}
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
{
return new ValueInternalArray( other );
}
virtual void destructArray( ValueInternalArray *array )
{
delete array;
}
virtual void reallocateArrayPageIndex( Value **&indexes,
ValueInternalArray::PageIndex &indexCount,
ValueInternalArray::PageIndex minNewIndexCount )
{
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
if ( minNewIndexCount > newIndexCount )
newIndexCount = minNewIndexCount;
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
if ( !newIndexes )
throw std::bad_alloc();
indexCount = newIndexCount;
indexes = static_cast<Value **>( newIndexes );
}
virtual void releaseArrayPageIndex( Value **indexes,
ValueInternalArray::PageIndex indexCount )
{
if ( indexes )
free( indexes );
}
virtual Value *allocateArrayPage()
{
return static_cast<Value *>( malloc( sizeof(Value) * ValueInternalArray::itemsPerPage ) );
}
virtual void releaseArrayPage( Value *value )
{
if ( value )
free( value );
}
};
#else // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
/// @todo make this thread-safe (lock when accessign batch allocator)
class DefaultValueArrayAllocator : public ValueArrayAllocator
{
public: // overridden from ValueArrayAllocator
virtual ~DefaultValueArrayAllocator()
{
}
virtual ValueInternalArray *newArray()
{
ValueInternalArray *array = arraysAllocator_.allocate();
new (array) ValueInternalArray(); // placement new
return array;
}
virtual ValueInternalArray *newArrayCopy( const ValueInternalArray &other )
{
ValueInternalArray *array = arraysAllocator_.allocate();
new (array) ValueInternalArray( other ); // placement new
return array;
}
virtual void destructArray( ValueInternalArray *array )
{
if ( array )
{
array->~ValueInternalArray();
arraysAllocator_.release( array );
}
}
virtual void reallocateArrayPageIndex( Value **&indexes,
ValueInternalArray::PageIndex &indexCount,
ValueInternalArray::PageIndex minNewIndexCount )
{
ValueInternalArray::PageIndex newIndexCount = (indexCount*3)/2 + 1;
if ( minNewIndexCount > newIndexCount )
newIndexCount = minNewIndexCount;
void *newIndexes = realloc( indexes, sizeof(Value*) * newIndexCount );
if ( !newIndexes )
throw std::bad_alloc();
indexCount = newIndexCount;
indexes = static_cast<Value **>( newIndexes );
}
virtual void releaseArrayPageIndex( Value **indexes,
ValueInternalArray::PageIndex indexCount )
{
if ( indexes )
free( indexes );
}
virtual Value *allocateArrayPage()
{
return static_cast<Value *>( pagesAllocator_.allocate() );
}
virtual void releaseArrayPage( Value *value )
{
if ( value )
pagesAllocator_.release( value );
}
private:
BatchAllocator<ValueInternalArray,1> arraysAllocator_;
BatchAllocator<Value,ValueInternalArray::itemsPerPage> pagesAllocator_;
};
#endif // #ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
static ValueArrayAllocator *&arrayAllocator()
{
static DefaultValueArrayAllocator defaultAllocator;
static ValueArrayAllocator *arrayAllocator = &defaultAllocator;
return arrayAllocator;
}
static struct DummyArrayAllocatorInitializer {
DummyArrayAllocatorInitializer()
{
arrayAllocator(); // ensure arrayAllocator() statics are initialized before main().
}
} dummyArrayAllocatorInitializer;
// //////////////////////////////////////////////////////////////////
// class ValueInternalArray
// //////////////////////////////////////////////////////////////////
bool
ValueInternalArray::equals( const IteratorState &x,
const IteratorState &other )
{
return x.array_ == other.array_
&& x.currentItemIndex_ == other.currentItemIndex_
&& x.currentPageIndex_ == other.currentPageIndex_;
}
void
ValueInternalArray::increment( IteratorState &it )
{
JSON_ASSERT_MESSAGE( it.array_ &&
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
!= it.array_->size_,
"ValueInternalArray::increment(): moving iterator beyond end" );
++(it.currentItemIndex_);
if ( it.currentItemIndex_ == itemsPerPage )
{
it.currentItemIndex_ = 0;
++(it.currentPageIndex_);
}
}
void
ValueInternalArray::decrement( IteratorState &it )
{
JSON_ASSERT_MESSAGE( it.array_ && it.currentPageIndex_ == it.array_->pages_
&& it.currentItemIndex_ == 0,
"ValueInternalArray::decrement(): moving iterator beyond end" );
if ( it.currentItemIndex_ == 0 )
{
it.currentItemIndex_ = itemsPerPage-1;
--(it.currentPageIndex_);
}
else
{
--(it.currentItemIndex_);
}
}
Value &
ValueInternalArray::unsafeDereference( const IteratorState &it )
{
return (*(it.currentPageIndex_))[it.currentItemIndex_];
}
Value &
ValueInternalArray::dereference( const IteratorState &it )
{
JSON_ASSERT_MESSAGE( it.array_ &&
(it.currentPageIndex_ - it.array_->pages_)*itemsPerPage + it.currentItemIndex_
< it.array_->size_,
"ValueInternalArray::dereference(): dereferencing invalid iterator" );
return unsafeDereference( it );
}
void
ValueInternalArray::makeBeginIterator( IteratorState &it ) const
{
it.array_ = const_cast<ValueInternalArray *>( this );
it.currentItemIndex_ = 0;
it.currentPageIndex_ = pages_;
}
void
ValueInternalArray::makeIterator( IteratorState &it, ArrayIndex index ) const
{
it.array_ = const_cast<ValueInternalArray *>( this );
it.currentItemIndex_ = index % itemsPerPage;
it.currentPageIndex_ = pages_ + index / itemsPerPage;
}
void
ValueInternalArray::makeEndIterator( IteratorState &it ) const
{
makeIterator( it, size_ );
}
ValueInternalArray::ValueInternalArray()
: pages_( 0 )
, size_( 0 )
, pageCount_( 0 )
{
}
ValueInternalArray::ValueInternalArray( const ValueInternalArray &other )
: pages_( 0 )
, pageCount_( 0 )
, size_( other.size_ )
{
PageIndex minNewPages = other.size_ / itemsPerPage;
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages,
"ValueInternalArray::reserve(): bad reallocation" );
IteratorState itOther;
other.makeBeginIterator( itOther );
Value *value;
for ( ArrayIndex index = 0; index < size_; ++index, increment(itOther) )
{
if ( index % itemsPerPage == 0 )
{
PageIndex pageIndex = index / itemsPerPage;
value = arrayAllocator()->allocateArrayPage();
pages_[pageIndex] = value;
}
new (value) Value( dereference( itOther ) );
}
}
ValueInternalArray &
ValueInternalArray::operator =( const ValueInternalArray &other )
{
ValueInternalArray temp( other );
swap( temp );
return *this;
}
ValueInternalArray::~ValueInternalArray()
{
// destroy all constructed items
IteratorState it;
IteratorState itEnd;
makeBeginIterator( it);
makeEndIterator( itEnd );
for ( ; !equals(it,itEnd); increment(it) )
{
Value *value = &dereference(it);
value->~Value();
}
// release all pages
PageIndex lastPageIndex = size_ / itemsPerPage;
for ( PageIndex pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex )
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
// release pages index
arrayAllocator()->releaseArrayPageIndex( pages_, pageCount_ );
}
void
ValueInternalArray::swap( ValueInternalArray &other )
{
Value **tempPages = pages_;
pages_ = other.pages_;
other.pages_ = tempPages;
ArrayIndex tempSize = size_;
size_ = other.size_;
other.size_ = tempSize;
PageIndex tempPageCount = pageCount_;
pageCount_ = other.pageCount_;
other.pageCount_ = tempPageCount;
}
void
ValueInternalArray::clear()
{
ValueInternalArray dummy;
swap( dummy );
}
void
ValueInternalArray::resize( ArrayIndex newSize )
{
if ( newSize == 0 )
clear();
else if ( newSize < size_ )
{
IteratorState it;
IteratorState itEnd;
makeIterator( it, newSize );
makeIterator( itEnd, size_ );
for ( ; !equals(it,itEnd); increment(it) )
{
Value *value = &dereference(it);
value->~Value();
}
PageIndex pageIndex = (newSize + itemsPerPage - 1) / itemsPerPage;
PageIndex lastPageIndex = size_ / itemsPerPage;
for ( ; pageIndex < lastPageIndex; ++pageIndex )
arrayAllocator()->releaseArrayPage( pages_[pageIndex] );
size_ = newSize;
}
else if ( newSize > size_ )
resolveReference( newSize );
}
void
ValueInternalArray::makeIndexValid( ArrayIndex index )
{
// Need to enlarge page index ?
if ( index >= pageCount_ * itemsPerPage )
{
PageIndex minNewPages = (index + 1) / itemsPerPage;
arrayAllocator()->reallocateArrayPageIndex( pages_, pageCount_, minNewPages );
JSON_ASSERT_MESSAGE( pageCount_ >= minNewPages, "ValueInternalArray::reserve(): bad reallocation" );
}
// Need to allocate new pages ?
ArrayIndex nextPageIndex =
(size_ % itemsPerPage) != 0 ? size_ - (size_%itemsPerPage) + itemsPerPage
: size_;
if ( nextPageIndex <= index )
{
PageIndex pageIndex = nextPageIndex / itemsPerPage;
PageIndex pageToAllocate = (index - nextPageIndex) / itemsPerPage + 1;
for ( ; pageToAllocate-- > 0; ++pageIndex )
pages_[pageIndex] = arrayAllocator()->allocateArrayPage();
}
// Initialize all new entries
IteratorState it;
IteratorState itEnd;
makeIterator( it, size_ );
size_ = index + 1;
makeIterator( itEnd, size_ );
for ( ; !equals(it,itEnd); increment(it) )
{
Value *value = &dereference(it);
new (value) Value(); // Construct a default value using placement new
}
}
Value &
ValueInternalArray::resolveReference( ArrayIndex index )
{
if ( index >= size_ )
makeIndexValid( index );
return pages_[index/itemsPerPage][index%itemsPerPage];
}
Value *
ValueInternalArray::find( ArrayIndex index ) const
{
if ( index >= size_ )
return 0;
return &(pages_[index/itemsPerPage][index%itemsPerPage]);
}
ValueInternalArray::ArrayIndex
ValueInternalArray::size() const
{
return size_;
}
int
ValueInternalArray::distance( const IteratorState &x, const IteratorState &y )
{
return indexOf(y) - indexOf(x);
}
ValueInternalArray::ArrayIndex
ValueInternalArray::indexOf( const IteratorState &iterator )
{
if ( !iterator.array_ )
return ArrayIndex(-1);
return ArrayIndex(
(iterator.currentPageIndex_ - iterator.array_->pages_) * itemsPerPage
+ iterator.currentItemIndex_ );
}
int
ValueInternalArray::compare( const ValueInternalArray &other ) const
{
int sizeDiff( size_ - other.size_ );
if ( sizeDiff != 0 )
return sizeDiff;
for ( ArrayIndex index =0; index < size_; ++index )
{
int diff = pages_[index/itemsPerPage][index%itemsPerPage].compare(
other.pages_[index/itemsPerPage][index%itemsPerPage] );
if ( diff != 0 )
return diff;
}
return 0;
}
@@ -1,607 +0,0 @@
// included by json_value.cpp
// everything is within Json namespace
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class ValueInternalMap
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
/** \internal MUST be safely initialized using memset( this, 0, sizeof(ValueInternalLink) );
* This optimization is used by the fast allocator.
*/
ValueInternalLink::ValueInternalLink()
: previous_( 0 )
, next_( 0 )
{
}
ValueInternalLink::~ValueInternalLink()
{
for ( int index =0; index < itemPerLink; ++index )
{
if ( !items_[index].isItemAvailable() )
{
if ( !items_[index].isMemberNameStatic() )
free( keys_[index] );
}
else
break;
}
}
ValueMapAllocator::~ValueMapAllocator()
{
}
#ifdef JSON_USE_SIMPLE_INTERNAL_ALLOCATOR
class DefaultValueMapAllocator : public ValueMapAllocator
{
public: // overridden from ValueMapAllocator
virtual ValueInternalMap *newMap()
{
return new ValueInternalMap();
}
virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
{
return new ValueInternalMap( other );
}
virtual void destructMap( ValueInternalMap *map )
{
delete map;
}
virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
{
return new ValueInternalLink[size];
}
virtual void releaseMapBuckets( ValueInternalLink *links )
{
delete [] links;
}
virtual ValueInternalLink *allocateMapLink()
{
return new ValueInternalLink();
}
virtual void releaseMapLink( ValueInternalLink *link )
{
delete link;
}
};
#else
/// @todo make this thread-safe (lock when accessign batch allocator)
class DefaultValueMapAllocator : public ValueMapAllocator
{
public: // overridden from ValueMapAllocator
virtual ValueInternalMap *newMap()
{
ValueInternalMap *map = mapsAllocator_.allocate();
new (map) ValueInternalMap(); // placement new
return map;
}
virtual ValueInternalMap *newMapCopy( const ValueInternalMap &other )
{
ValueInternalMap *map = mapsAllocator_.allocate();
new (map) ValueInternalMap( other ); // placement new
return map;
}
virtual void destructMap( ValueInternalMap *map )
{
if ( map )
{
map->~ValueInternalMap();
mapsAllocator_.release( map );
}
}
virtual ValueInternalLink *allocateMapBuckets( unsigned int size )
{
return new ValueInternalLink[size];
}
virtual void releaseMapBuckets( ValueInternalLink *links )
{
delete [] links;
}
virtual ValueInternalLink *allocateMapLink()
{
ValueInternalLink *link = linksAllocator_.allocate();
memset( link, 0, sizeof(ValueInternalLink) );
return link;
}
virtual void releaseMapLink( ValueInternalLink *link )
{
link->~ValueInternalLink();
linksAllocator_.release( link );
}
private:
BatchAllocator<ValueInternalMap,1> mapsAllocator_;
BatchAllocator<ValueInternalLink,1> linksAllocator_;
};
#endif
static ValueMapAllocator *&mapAllocator()
{
static DefaultValueMapAllocator defaultAllocator;
static ValueMapAllocator *mapAllocator = &defaultAllocator;
return mapAllocator;
}
static struct DummyMapAllocatorInitializer {
DummyMapAllocatorInitializer()
{
mapAllocator(); // ensure mapAllocator() statics are initialized before main().
}
} dummyMapAllocatorInitializer;
// h(K) = value * K >> w ; with w = 32 & K prime w.r.t. 2^32.
/*
use linked list hash map.
buckets array is a container.
linked list element contains 6 key/values. (memory = (16+4) * 6 + 4 = 124)
value have extra state: valid, available, deleted
*/
ValueInternalMap::ValueInternalMap()
: buckets_( 0 )
, tailLink_( 0 )
, bucketsSize_( 0 )
, itemCount_( 0 )
{
}
ValueInternalMap::ValueInternalMap( const ValueInternalMap &other )
: buckets_( 0 )
, tailLink_( 0 )
, bucketsSize_( 0 )
, itemCount_( 0 )
{
reserve( other.itemCount_ );
IteratorState it;
IteratorState itEnd;
other.makeBeginIterator( it );
other.makeEndIterator( itEnd );
for ( ; !equals(it,itEnd); increment(it) )
{
bool isStatic;
const char *memberName = key( it, isStatic );
const Value &aValue = value( it );
resolveReference(memberName, isStatic) = aValue;
}
}
ValueInternalMap &
ValueInternalMap::operator =( const ValueInternalMap &other )
{
ValueInternalMap dummy( other );
swap( dummy );
return *this;
}
ValueInternalMap::~ValueInternalMap()
{
if ( buckets_ )
{
for ( BucketIndex bucketIndex =0; bucketIndex < bucketsSize_; ++bucketIndex )
{
ValueInternalLink *link = buckets_[bucketIndex].next_;
while ( link )
{
ValueInternalLink *linkToRelease = link;
link = link->next_;
mapAllocator()->releaseMapLink( linkToRelease );
}
}
mapAllocator()->releaseMapBuckets( buckets_ );
}
}
void
ValueInternalMap::swap( ValueInternalMap &other )
{
ValueInternalLink *tempBuckets = buckets_;
buckets_ = other.buckets_;
other.buckets_ = tempBuckets;
ValueInternalLink *tempTailLink = tailLink_;
tailLink_ = other.tailLink_;
other.tailLink_ = tempTailLink;
BucketIndex tempBucketsSize = bucketsSize_;
bucketsSize_ = other.bucketsSize_;
other.bucketsSize_ = tempBucketsSize;
BucketIndex tempItemCount = itemCount_;
itemCount_ = other.itemCount_;
other.itemCount_ = tempItemCount;
}
void
ValueInternalMap::clear()
{
ValueInternalMap dummy;
swap( dummy );
}
ValueInternalMap::BucketIndex
ValueInternalMap::size() const
{
return itemCount_;
}
bool
ValueInternalMap::reserveDelta( BucketIndex growth )
{
return reserve( itemCount_ + growth );
}
bool
ValueInternalMap::reserve( BucketIndex newItemCount )
{
if ( !buckets_ && newItemCount > 0 )
{
buckets_ = mapAllocator()->allocateMapBuckets( 1 );
bucketsSize_ = 1;
tailLink_ = &buckets_[0];
}
// BucketIndex idealBucketCount = (newItemCount + ValueInternalLink::itemPerLink) / ValueInternalLink::itemPerLink;
return true;
}
const Value *
ValueInternalMap::find( const char *key ) const
{
if ( !bucketsSize_ )
return 0;
HashKey hashedKey = hash( key );
BucketIndex bucketIndex = hashedKey % bucketsSize_;
for ( const ValueInternalLink *current = &buckets_[bucketIndex];
current != 0;
current = current->next_ )
{
for ( BucketIndex index=0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( current->items_[index].isItemAvailable() )
return 0;
if ( strcmp( key, current->keys_[index] ) == 0 )
return &current->items_[index];
}
}
return 0;
}
Value *
ValueInternalMap::find( const char *key )
{
const ValueInternalMap *constThis = this;
return const_cast<Value *>( constThis->find( key ) );
}
Value &
ValueInternalMap::resolveReference( const char *key,
bool isStatic )
{
HashKey hashedKey = hash( key );
if ( bucketsSize_ )
{
BucketIndex bucketIndex = hashedKey % bucketsSize_;
ValueInternalLink **previous = 0;
BucketIndex index;
for ( ValueInternalLink *current = &buckets_[bucketIndex];
current != 0;
previous = &current->next_, current = current->next_ )
{
for ( index=0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( current->items_[index].isItemAvailable() )
return setNewItem( key, isStatic, current, index );
if ( strcmp( key, current->keys_[index] ) == 0 )
return current->items_[index];
}
}
}
reserveDelta( 1 );
return unsafeAdd( key, isStatic, hashedKey );
}
void
ValueInternalMap::remove( const char *key )
{
HashKey hashedKey = hash( key );
if ( !bucketsSize_ )
return;
BucketIndex bucketIndex = hashedKey % bucketsSize_;
for ( ValueInternalLink *link = &buckets_[bucketIndex];
link != 0;
link = link->next_ )
{
BucketIndex index;
for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( link->items_[index].isItemAvailable() )
return;
if ( strcmp( key, link->keys_[index] ) == 0 )
{
doActualRemove( link, index, bucketIndex );
return;
}
}
}
}
void
ValueInternalMap::doActualRemove( ValueInternalLink *link,
BucketIndex index,
BucketIndex bucketIndex )
{
// find last item of the bucket and swap it with the 'removed' one.
// set removed items flags to 'available'.
// if last page only contains 'available' items, then desallocate it (it's empty)
ValueInternalLink *&lastLink = getLastLinkInBucket( index );
BucketIndex lastItemIndex = 1; // a link can never be empty, so start at 1
for ( ;
lastItemIndex < ValueInternalLink::itemPerLink;
++lastItemIndex ) // may be optimized with dicotomic search
{
if ( lastLink->items_[lastItemIndex].isItemAvailable() )
break;
}
BucketIndex lastUsedIndex = lastItemIndex - 1;
Value *valueToDelete = &link->items_[index];
Value *valueToPreserve = &lastLink->items_[lastUsedIndex];
if ( valueToDelete != valueToPreserve )
valueToDelete->swap( *valueToPreserve );
if ( lastUsedIndex == 0 ) // page is now empty
{ // remove it from bucket linked list and delete it.
ValueInternalLink *linkPreviousToLast = lastLink->previous_;
if ( linkPreviousToLast != 0 ) // can not deleted bucket link.
{
mapAllocator()->releaseMapLink( lastLink );
linkPreviousToLast->next_ = 0;
lastLink = linkPreviousToLast;
}
}
else
{
Value dummy;
valueToPreserve->swap( dummy ); // restore deleted to default Value.
valueToPreserve->setItemUsed( false );
}
--itemCount_;
}
ValueInternalLink *&
ValueInternalMap::getLastLinkInBucket( BucketIndex bucketIndex )
{
if ( bucketIndex == bucketsSize_ - 1 )
return tailLink_;
ValueInternalLink *&previous = buckets_[bucketIndex+1].previous_;
if ( !previous )
previous = &buckets_[bucketIndex];
return previous;
}
Value &
ValueInternalMap::setNewItem( const char *key,
bool isStatic,
ValueInternalLink *link,
BucketIndex index )
{
char *duplicatedKey = valueAllocator()->makeMemberName( key );
++itemCount_;
link->keys_[index] = duplicatedKey;
link->items_[index].setItemUsed();
link->items_[index].setMemberNameIsStatic( isStatic );
return link->items_[index]; // items already default constructed.
}
Value &
ValueInternalMap::unsafeAdd( const char *key,
bool isStatic,
HashKey hashedKey )
{
JSON_ASSERT_MESSAGE( bucketsSize_ > 0, "ValueInternalMap::unsafeAdd(): internal logic error." );
BucketIndex bucketIndex = hashedKey % bucketsSize_;
ValueInternalLink *&previousLink = getLastLinkInBucket( bucketIndex );
ValueInternalLink *link = previousLink;
BucketIndex index;
for ( index =0; index < ValueInternalLink::itemPerLink; ++index )
{
if ( link->items_[index].isItemAvailable() )
break;
}
if ( index == ValueInternalLink::itemPerLink ) // need to add a new page
{
ValueInternalLink *newLink = mapAllocator()->allocateMapLink();
index = 0;
link->next_ = newLink;
previousLink = newLink;
link = newLink;
}
return setNewItem( key, isStatic, link, index );
}
ValueInternalMap::HashKey
ValueInternalMap::hash( const char *key ) const
{
HashKey hash = 0;
while ( *key )
hash += *key++ * 37;
return hash;
}
int
ValueInternalMap::compare( const ValueInternalMap &other ) const
{
int sizeDiff( itemCount_ - other.itemCount_ );
if ( sizeDiff != 0 )
return sizeDiff;
// Strict order guaranty is required. Compare all keys FIRST, then compare values.
IteratorState it;
IteratorState itEnd;
makeBeginIterator( it );
makeEndIterator( itEnd );
for ( ; !equals(it,itEnd); increment(it) )
{
if ( !other.find( key( it ) ) )
return 1;
}
// All keys are equals, let's compare values
makeBeginIterator( it );
for ( ; !equals(it,itEnd); increment(it) )
{
const Value *otherValue = other.find( key( it ) );
int valueDiff = value(it).compare( *otherValue );
if ( valueDiff != 0 )
return valueDiff;
}
return 0;
}
void
ValueInternalMap::makeBeginIterator( IteratorState &it ) const
{
it.map_ = const_cast<ValueInternalMap *>( this );
it.bucketIndex_ = 0;
it.itemIndex_ = 0;
it.link_ = buckets_;
}
void
ValueInternalMap::makeEndIterator( IteratorState &it ) const
{
it.map_ = const_cast<ValueInternalMap *>( this );
it.bucketIndex_ = bucketsSize_;
it.itemIndex_ = 0;
it.link_ = 0;
}
bool
ValueInternalMap::equals( const IteratorState &x, const IteratorState &other )
{
return x.map_ == other.map_
&& x.bucketIndex_ == other.bucketIndex_
&& x.link_ == other.link_
&& x.itemIndex_ == other.itemIndex_;
}
void
ValueInternalMap::incrementBucket( IteratorState &iterator )
{
++iterator.bucketIndex_;
JSON_ASSERT_MESSAGE( iterator.bucketIndex_ <= iterator.map_->bucketsSize_,
"ValueInternalMap::increment(): attempting to iterate beyond end." );
if ( iterator.bucketIndex_ == iterator.map_->bucketsSize_ )
iterator.link_ = 0;
else
iterator.link_ = &(iterator.map_->buckets_[iterator.bucketIndex_]);
iterator.itemIndex_ = 0;
}
void
ValueInternalMap::increment( IteratorState &iterator )
{
JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterator using invalid iterator." );
++iterator.itemIndex_;
if ( iterator.itemIndex_ == ValueInternalLink::itemPerLink )
{
JSON_ASSERT_MESSAGE( iterator.link_ != 0,
"ValueInternalMap::increment(): attempting to iterate beyond end." );
iterator.link_ = iterator.link_->next_;
if ( iterator.link_ == 0 )
incrementBucket( iterator );
}
else if ( iterator.link_->items_[iterator.itemIndex_].isItemAvailable() )
{
incrementBucket( iterator );
}
}
void
ValueInternalMap::decrement( IteratorState &iterator )
{
if ( iterator.itemIndex_ == 0 )
{
JSON_ASSERT_MESSAGE( iterator.map_, "Attempting to iterate using invalid iterator." );
if ( iterator.link_ == &iterator.map_->buckets_[iterator.bucketIndex_] )
{
JSON_ASSERT_MESSAGE( iterator.bucketIndex_ > 0, "Attempting to iterate beyond beginning." );
--(iterator.bucketIndex_);
}
iterator.link_ = iterator.link_->previous_;
iterator.itemIndex_ = ValueInternalLink::itemPerLink - 1;
}
}
const char *
ValueInternalMap::key( const IteratorState &iterator )
{
JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
return iterator.link_->keys_[iterator.itemIndex_];
}
const char *
ValueInternalMap::key( const IteratorState &iterator, bool &isStatic )
{
JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
isStatic = iterator.link_->items_[iterator.itemIndex_].isMemberNameStatic();
return iterator.link_->keys_[iterator.itemIndex_];
}
Value &
ValueInternalMap::value( const IteratorState &iterator )
{
JSON_ASSERT_MESSAGE( iterator.link_, "Attempting to iterate using invalid iterator." );
return iterator.link_->items_[iterator.itemIndex_];
}
int
ValueInternalMap::distance( const IteratorState &x, const IteratorState &y )
{
int offset = 0;
IteratorState it = x;
while ( !equals( it, y ) )
increment( it );
return offset;
}
-886
View File
@@ -1,886 +0,0 @@
#include <jsoncpp/include/json/reader.h>
#include <jsoncpp/include/json/value.h>
#include <utility>
#include <cstdio>
#include <cassert>
#include <cstring>
#include <iostream>
#include <stdexcept>
#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
#endif
namespace Json {
// Implementation of class Features
// ////////////////////////////////
Features::Features()
: allowComments_( true )
, strictRoot_( false )
{
}
Features
Features::all()
{
return Features();
}
Features
Features::strictMode()
{
Features features;
features.allowComments_ = false;
features.strictRoot_ = true;
return features;
}
// Implementation of class Reader
// ////////////////////////////////
static inline bool
in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4 )
{
return c == c1 || c == c2 || c == c3 || c == c4;
}
static inline bool
in( Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4, Reader::Char c5 )
{
return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
}
static bool
containsNewLine( Reader::Location begin,
Reader::Location end )
{
for ( ;begin < end; ++begin )
if ( *begin == '\n' || *begin == '\r' )
return true;
return false;
}
static std::string codePointToUTF8(unsigned int cp)
{
std::string result;
// based on description from http://en.wikipedia.org/wiki/UTF-8
if (cp <= 0x7f)
{
result.resize(1);
result[0] = static_cast<char>(cp);
}
else if (cp <= 0x7FF)
{
result.resize(2);
result[1] = static_cast<char>(0x80 | (0x3f & cp));
result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
}
else if (cp <= 0xFFFF)
{
result.resize(3);
result[2] = static_cast<char>(0x80 | (0x3f & cp));
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
}
else if (cp <= 0x10FFFF)
{
result.resize(4);
result[3] = static_cast<char>(0x80 | (0x3f & cp));
result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
}
return result;
}
// Class Reader
// //////////////////////////////////////////////////////////////////
Reader::Reader()
: features_( Features::all() )
{
}
Reader::Reader( const Features &features )
: features_( features )
{
}
bool
Reader::parse( const std::string &document,
Value &root,
bool collectComments )
{
document_ = document;
const char *begin = document_.c_str();
const char *end = begin + document_.length();
return parse( begin, end, root, collectComments );
}
bool
Reader::parse( std::istream& sin,
Value &root,
bool collectComments )
{
//std::istream_iterator<char> begin(sin);
//std::istream_iterator<char> end;
// Those would allow streamed input from a file, if parse() were a
// template function.
// Since std::string is reference-counted, this at least does not
// create an extra copy.
std::string doc;
std::getline(sin, doc, (char)EOF);
return parse( doc, root, collectComments );
}
bool
Reader::parse( const char *beginDoc, const char *endDoc,
Value &root,
bool collectComments )
{
if ( !features_.allowComments_ )
{
collectComments = false;
}
begin_ = beginDoc;
end_ = endDoc;
collectComments_ = collectComments;
current_ = begin_;
lastValueEnd_ = 0;
lastValue_ = 0;
commentsBefore_ = "";
errors_.clear();
while ( !nodes_.empty() )
nodes_.pop();
nodes_.push( &root );
bool successful = readValue();
Token token;
skipCommentTokens( token );
if ( collectComments_ && !commentsBefore_.empty() )
root.setComment( commentsBefore_, commentAfter );
if ( features_.strictRoot_ )
{
if ( !root.isArray() && !root.isObject() )
{
// Set error location to start of doc, ideally should be first token found in doc
token.type_ = tokenError;
token.start_ = beginDoc;
token.end_ = endDoc;
addError( "A valid JSON document must be either an array or an object value.",
token );
return false;
}
}
return successful;
}
bool
Reader::readValue()
{
Token token;
skipCommentTokens( token );
bool successful = true;
if ( collectComments_ && !commentsBefore_.empty() )
{
currentValue().setComment( commentsBefore_, commentBefore );
commentsBefore_ = "";
}
switch ( token.type_ )
{
case tokenObjectBegin:
successful = readObject( token );
break;
case tokenArrayBegin:
successful = readArray( token );
break;
case tokenNumber:
successful = decodeNumber( token );
break;
case tokenString:
successful = decodeString( token );
break;
case tokenTrue:
currentValue() = true;
break;
case tokenFalse:
currentValue() = false;
break;
case tokenNull:
currentValue() = Value();
break;
default:
return addError( "Syntax error: value, object or array expected.", token );
}
if ( collectComments_ )
{
lastValueEnd_ = current_;
lastValue_ = &currentValue();
}
return successful;
}
void
Reader::skipCommentTokens( Token &token )
{
if ( features_.allowComments_ )
{
do
{
readToken( token );
}
while ( token.type_ == tokenComment );
}
else
{
readToken( token );
}
}
bool
Reader::expectToken( TokenType type, Token &token, const char *message )
{
readToken( token );
if ( token.type_ != type )
return addError( message, token );
return true;
}
bool
Reader::readToken( Token &token )
{
skipSpaces();
token.start_ = current_;
Char c = getNextChar();
bool ok = true;
switch ( c )
{
case '{':
token.type_ = tokenObjectBegin;
break;
case '}':
token.type_ = tokenObjectEnd;
break;
case '[':
token.type_ = tokenArrayBegin;
break;
case ']':
token.type_ = tokenArrayEnd;
break;
case '"':
token.type_ = tokenString;
ok = readString();
break;
case '/':
token.type_ = tokenComment;
ok = readComment();
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
token.type_ = tokenNumber;
readNumber();
break;
case 't':
token.type_ = tokenTrue;
ok = match( "rue", 3 );
break;
case 'f':
token.type_ = tokenFalse;
ok = match( "alse", 4 );
break;
case 'n':
token.type_ = tokenNull;
ok = match( "ull", 3 );
break;
case ',':
token.type_ = tokenArraySeparator;
break;
case ':':
token.type_ = tokenMemberSeparator;
break;
case 0:
token.type_ = tokenEndOfStream;
break;
default:
ok = false;
break;
}
if ( !ok )
token.type_ = tokenError;
token.end_ = current_;
return true;
}
void
Reader::skipSpaces()
{
while ( current_ != end_ )
{
Char c = *current_;
if ( c == ' ' || c == '\t' || c == '\r' || c == '\n' )
++current_;
else
break;
}
}
bool
Reader::match( Location pattern,
int patternLength )
{
if ( end_ - current_ < patternLength )
return false;
int index = patternLength;
while ( index-- )
if ( current_[index] != pattern[index] )
return false;
current_ += patternLength;
return true;
}
bool
Reader::readComment()
{
Location commentBegin = current_ - 1;
Char c = getNextChar();
bool successful = false;
if ( c == '*' )
successful = readCStyleComment();
else if ( c == '/' )
successful = readCppStyleComment();
if ( !successful )
return false;
if ( collectComments_ )
{
CommentPlacement placement = commentBefore;
if ( lastValueEnd_ && !containsNewLine( lastValueEnd_, commentBegin ) )
{
if ( c != '*' || !containsNewLine( commentBegin, current_ ) )
placement = commentAfterOnSameLine;
}
addComment( commentBegin, current_, placement );
}
return true;
}
void
Reader::addComment( Location begin,
Location end,
CommentPlacement placement )
{
assert( collectComments_ );
if ( placement == commentAfterOnSameLine )
{
assert( lastValue_ != 0 );
lastValue_->setComment( std::string( begin, end ), placement );
}
else
{
if ( !commentsBefore_.empty() )
commentsBefore_ += "\n";
commentsBefore_ += std::string( begin, end );
}
}
bool
Reader::readCStyleComment()
{
while ( current_ != end_ )
{
Char c = getNextChar();
if ( c == '*' && *current_ == '/' )
break;
}
return getNextChar() == '/';
}
bool
Reader::readCppStyleComment()
{
while ( current_ != end_ )
{
Char c = getNextChar();
if ( c == '\r' || c == '\n' )
break;
}
return true;
}
void
Reader::readNumber()
{
while ( current_ != end_ )
{
if ( !(*current_ >= '0' && *current_ <= '9') &&
!in( *current_, '.', 'e', 'E', '+', '-' ) )
break;
++current_;
}
}
bool
Reader::readString()
{
Char c = 0;
while ( current_ != end_ )
{
c = getNextChar();
if ( c == '\\' )
getNextChar();
else if ( c == '"' )
break;
}
return c == '"';
}
bool
Reader::readObject( Token &tokenStart )
{
Token tokenName;
std::string name;
currentValue() = Value( objectValue );
while ( readToken( tokenName ) )
{
bool initialTokenOk = true;
while ( tokenName.type_ == tokenComment && initialTokenOk )
initialTokenOk = readToken( tokenName );
if ( !initialTokenOk )
break;
if ( tokenName.type_ == tokenObjectEnd && name.empty() ) // empty object
return true;
if ( tokenName.type_ != tokenString )
break;
name = "";
if ( !decodeString( tokenName, name ) )
return recoverFromError( tokenObjectEnd );
Token colon;
if ( !readToken( colon ) || colon.type_ != tokenMemberSeparator )
{
return addErrorAndRecover( "Missing ':' after object member name",
colon,
tokenObjectEnd );
}
Value &value = currentValue()[ name ];
nodes_.push( &value );
bool ok = readValue();
nodes_.pop();
if ( !ok ) // error already set
return recoverFromError( tokenObjectEnd );
Token comma;
if ( !readToken( comma )
|| ( comma.type_ != tokenObjectEnd &&
comma.type_ != tokenArraySeparator &&
comma.type_ != tokenComment ) )
{
return addErrorAndRecover( "Missing ',' or '}' in object declaration",
comma,
tokenObjectEnd );
}
bool finalizeTokenOk = true;
while ( comma.type_ == tokenComment &&
finalizeTokenOk )
finalizeTokenOk = readToken( comma );
if ( comma.type_ == tokenObjectEnd )
return true;
}
return addErrorAndRecover( "Missing '}' or object member name",
tokenName,
tokenObjectEnd );
}
bool
Reader::readArray( Token &tokenStart )
{
currentValue() = Value( arrayValue );
skipSpaces();
if ( *current_ == ']' ) // empty array
{
Token endArray;
readToken( endArray );
return true;
}
int index = 0;
while ( true )
{
Value &value = currentValue()[ index++ ];
nodes_.push( &value );
bool ok = readValue();
nodes_.pop();
if ( !ok ) // error already set
return recoverFromError( tokenArrayEnd );
Token token;
// Accept Comment after last item in the array.
ok = readToken( token );
while ( token.type_ == tokenComment && ok )
{
ok = readToken( token );
}
bool badTokenType = ( token.type_ == tokenArraySeparator &&
token.type_ == tokenArrayEnd );
if ( !ok || badTokenType )
{
return addErrorAndRecover( "Missing ',' or ']' in array declaration",
token,
tokenArrayEnd );
}
if ( token.type_ == tokenArrayEnd )
break;
}
return true;
}
bool
Reader::decodeNumber( Token &token )
{
bool isDouble = false;
for ( Location inspect = token.start_; inspect != token.end_; ++inspect )
{
isDouble = isDouble
|| in( *inspect, '.', 'e', 'E', '+' )
|| ( *inspect == '-' && inspect != token.start_ );
}
if ( isDouble )
return decodeDouble( token );
Location current = token.start_;
bool isNegative = *current == '-';
if ( isNegative )
++current;
Value::UInt threshold = (isNegative ? Value::UInt(-Value::minInt)
: Value::maxUInt) / 10;
Value::UInt value = 0;
while ( current < token.end_ )
{
Char c = *current++;
if ( c < '0' || c > '9' )
return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
if ( value >= threshold )
return decodeDouble( token );
value = value * 10 + Value::UInt(c - '0');
}
if ( isNegative )
currentValue() = -Value::Int( value );
else if ( value <= Value::UInt(Value::maxInt) )
currentValue() = Value::Int( value );
else
currentValue() = value;
return true;
}
bool
Reader::decodeDouble( Token &token )
{
double value = 0;
const int bufferSize = 32;
int count;
int length = int(token.end_ - token.start_);
if ( length <= bufferSize )
{
Char buffer[bufferSize];
memcpy( buffer, token.start_, length );
buffer[length] = 0;
count = sscanf( buffer, "%lf", &value );
}
else
{
std::string buffer( token.start_, token.end_ );
count = sscanf( buffer.c_str(), "%lf", &value );
}
if ( count != 1 )
return addError( "'" + std::string( token.start_, token.end_ ) + "' is not a number.", token );
currentValue() = value;
return true;
}
bool
Reader::decodeString( Token &token )
{
std::string decoded;
if ( !decodeString( token, decoded ) )
return false;
currentValue() = decoded;
return true;
}
bool
Reader::decodeString( Token &token, std::string &decoded )
{
decoded.reserve( token.end_ - token.start_ - 2 );
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
while ( current != end )
{
Char c = *current++;
if ( c == '"' )
break;
else if ( c == '\\' )
{
if ( current == end )
return addError( "Empty escape sequence in string", token, current );
Char escape = *current++;
switch ( escape )
{
case '"': decoded += '"'; break;
case '/': decoded += '/'; break;
case '\\': decoded += '\\'; break;
case 'b': decoded += '\b'; break;
case 'f': decoded += '\f'; break;
case 'n': decoded += '\n'; break;
case 'r': decoded += '\r'; break;
case 't': decoded += '\t'; break;
case 'u':
{
unsigned int unicode;
if ( !decodeUnicodeCodePoint( token, current, end, unicode ) )
return false;
decoded += codePointToUTF8(unicode);
}
break;
default:
return addError( "Bad escape sequence in string", token, current );
}
}
else
{
decoded += c;
}
}
return true;
}
bool
Reader::decodeUnicodeCodePoint( Token &token,
Location &current,
Location end,
unsigned int &unicode )
{
if ( !decodeUnicodeEscapeSequence( token, current, end, unicode ) )
return false;
if (unicode >= 0xD800 && unicode <= 0xDBFF)
{
// surrogate pairs
if (end - current < 6)
return addError( "additional six characters expected to parse unicode surrogate pair.", token, current );
unsigned int surrogatePair;
if (*(current++) == '\\' && *(current++)== 'u')
{
if (decodeUnicodeEscapeSequence( token, current, end, surrogatePair ))
{
unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
}
else
return false;
}
else
return addError( "expecting another \\u token to begin the second half of a unicode surrogate pair", token, current );
}
return true;
}
bool
Reader::decodeUnicodeEscapeSequence( Token &token,
Location &current,
Location end,
unsigned int &unicode )
{
if ( end - current < 4 )
return addError( "Bad unicode escape sequence in string: four digits expected.", token, current );
unicode = 0;
for ( int index =0; index < 4; ++index )
{
Char c = *current++;
unicode *= 16;
if ( c >= '0' && c <= '9' )
unicode += c - '0';
else if ( c >= 'a' && c <= 'f' )
unicode += c - 'a' + 10;
else if ( c >= 'A' && c <= 'F' )
unicode += c - 'A' + 10;
else
return addError( "Bad unicode escape sequence in string: hexadecimal digit expected.", token, current );
}
return true;
}
bool
Reader::addError( const std::string &message,
Token &token,
Location extra )
{
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = extra;
errors_.push_back( info );
return false;
}
bool
Reader::recoverFromError( TokenType skipUntilToken )
{
int errorCount = int(errors_.size());
Token skip;
while ( true )
{
if ( !readToken(skip) )
errors_.resize( errorCount ); // discard errors caused by recovery
if ( skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream )
break;
}
errors_.resize( errorCount );
return false;
}
bool
Reader::addErrorAndRecover( const std::string &message,
Token &token,
TokenType skipUntilToken )
{
addError( message, token );
return recoverFromError( skipUntilToken );
}
Value &
Reader::currentValue()
{
return *(nodes_.top());
}
Reader::Char
Reader::getNextChar()
{
if ( current_ == end_ )
return 0;
return *current_++;
}
void
Reader::getLocationLineAndColumn( Location location,
int &line,
int &column ) const
{
Location current = begin_;
Location lastLineStart = current;
line = 0;
while ( current < location && current != end_ )
{
Char c = *current++;
if ( c == '\r' )
{
if ( *current == '\n' )
++current;
lastLineStart = current;
++line;
}
else if ( c == '\n' )
{
lastLineStart = current;
++line;
}
}
// column & line start at 1
column = int(location - lastLineStart) + 1;
++line;
}
std::string
Reader::getLocationLineAndColumn( Location location ) const
{
int line, column;
getLocationLineAndColumn( location, line, column );
char buffer[18+16+16+1];
sprintf( buffer, "Line %d, Column %d", line, column );
return buffer;
}
std::string
Reader::getFormatedErrorMessages() const
{
std::string formattedMessage;
for ( Errors::const_iterator itError = errors_.begin();
itError != errors_.end();
++itError )
{
const ErrorInfo &error = *itError;
formattedMessage += "* " + getLocationLineAndColumn( error.token_.start_ ) + "\n";
formattedMessage += " " + error.message_ + "\n";
if ( error.extra_ )
formattedMessage += "See " + getLocationLineAndColumn( error.extra_ ) + " for detail.\n";
}
return formattedMessage;
}
std::istream& operator>>( std::istream &sin, Value &root )
{
Json::Reader reader;
bool ok = reader.parse(sin, root, true);
//JSON_ASSERT( ok );
// if (!ok) throw std::runtime_error(reader.getFormatedErrorMessages());
assert(ok);
return sin;
}
} // namespace Json
File diff suppressed because it is too large Load Diff
@@ -1,292 +0,0 @@
// included by json_value.cpp
// everything is within Json namespace
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class ValueIteratorBase
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
ValueIteratorBase::ValueIteratorBase()
#ifndef JSON_VALUE_USE_INTERNAL_MAP
: current_()
, isNull_( true )
{
}
#else
: isArray_( true )
, isNull_( true )
{
iterator_.array_ = ValueInternalArray::IteratorState();
}
#endif
#ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIteratorBase::ValueIteratorBase( const Value::ObjectValues::iterator &current )
: current_( current )
, isNull_( false )
{
}
#else
ValueIteratorBase::ValueIteratorBase( const ValueInternalArray::IteratorState &state )
: isArray_( true )
{
iterator_.array_ = state;
}
ValueIteratorBase::ValueIteratorBase( const ValueInternalMap::IteratorState &state )
: isArray_( false )
{
iterator_.map_ = state;
}
#endif
Value &
ValueIteratorBase::deref() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
return current_->second;
#else
if ( isArray_ )
return ValueInternalArray::dereference( iterator_.array_ );
return ValueInternalMap::value( iterator_.map_ );
#endif
}
void
ValueIteratorBase::increment()
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
++current_;
#else
if ( isArray_ )
ValueInternalArray::increment( iterator_.array_ );
ValueInternalMap::increment( iterator_.map_ );
#endif
}
void
ValueIteratorBase::decrement()
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
--current_;
#else
if ( isArray_ )
ValueInternalArray::decrement( iterator_.array_ );
ValueInternalMap::decrement( iterator_.map_ );
#endif
}
ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance( const SelfType &other ) const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
# ifdef JSON_USE_CPPTL_SMALLMAP
return current_ - other.current_;
# else
// Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default
// std::map::iterator. As begin() and end() are two instance
// of the default std::map::iterator, they can not be compared.
// To allow this, we handle this comparison specifically.
if ( isNull_ && other.isNull_ )
{
return 0;
}
// Usage of std::distance is not portable (does not compile with Sun Studio 12 RogueWave STL,
// which is the one used by default).
// Using a portable hand-made version for non random iterator instead:
// return difference_type( std::distance( current_, other.current_ ) );
difference_type myDistance = 0;
for ( Value::ObjectValues::iterator it = current_; it != other.current_; ++it )
{
++myDistance;
}
return myDistance;
# endif
#else
if ( isArray_ )
return ValueInternalArray::distance( iterator_.array_, other.iterator_.array_ );
return ValueInternalMap::distance( iterator_.map_, other.iterator_.map_ );
#endif
}
bool
ValueIteratorBase::isEqual( const SelfType &other ) const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
if ( isNull_ )
{
return other.isNull_;
}
return current_ == other.current_;
#else
if ( isArray_ )
return ValueInternalArray::equals( iterator_.array_, other.iterator_.array_ );
return ValueInternalMap::equals( iterator_.map_, other.iterator_.map_ );
#endif
}
void
ValueIteratorBase::copy( const SelfType &other )
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
current_ = other.current_;
#else
if ( isArray_ )
iterator_.array_ = other.iterator_.array_;
iterator_.map_ = other.iterator_.map_;
#endif
}
Value
ValueIteratorBase::key() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first;
if ( czstring.c_str() )
{
if ( czstring.isStaticString() )
return Value( StaticString( czstring.c_str() ) );
return Value( czstring.c_str() );
}
return Value( czstring.index() );
#else
if ( isArray_ )
return Value( ValueInternalArray::indexOf( iterator_.array_ ) );
bool isStatic;
const char *memberName = ValueInternalMap::key( iterator_.map_, isStatic );
if ( isStatic )
return Value( StaticString( memberName ) );
return Value( memberName );
#endif
}
UInt
ValueIteratorBase::index() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
const Value::CZString czstring = (*current_).first;
if ( !czstring.c_str() )
return czstring.index();
return Value::UInt( -1 );
#else
if ( isArray_ )
return Value::UInt( ValueInternalArray::indexOf( iterator_.array_ ) );
return Value::UInt( -1 );
#endif
}
const char *
ValueIteratorBase::memberName() const
{
#ifndef JSON_VALUE_USE_INTERNAL_MAP
const char *name = (*current_).first.c_str();
return name ? name : "";
#else
if ( !isArray_ )
return ValueInternalMap::key( iterator_.map_ );
return "";
#endif
}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class ValueConstIterator
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
ValueConstIterator::ValueConstIterator()
{
}
#ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueConstIterator::ValueConstIterator( const Value::ObjectValues::iterator &current )
: ValueIteratorBase( current )
{
}
#else
ValueConstIterator::ValueConstIterator( const ValueInternalArray::IteratorState &state )
: ValueIteratorBase( state )
{
}
ValueConstIterator::ValueConstIterator( const ValueInternalMap::IteratorState &state )
: ValueIteratorBase( state )
{
}
#endif
ValueConstIterator &
ValueConstIterator::operator =( const ValueIteratorBase &other )
{
copy( other );
return *this;
}
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// class ValueIterator
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
ValueIterator::ValueIterator()
{
}
#ifndef JSON_VALUE_USE_INTERNAL_MAP
ValueIterator::ValueIterator( const Value::ObjectValues::iterator &current )
: ValueIteratorBase( current )
{
}
#else
ValueIterator::ValueIterator( const ValueInternalArray::IteratorState &state )
: ValueIteratorBase( state )
{
}
ValueIterator::ValueIterator( const ValueInternalMap::IteratorState &state )
: ValueIteratorBase( state )
{
}
#endif
ValueIterator::ValueIterator( const ValueConstIterator &other )
: ValueIteratorBase( other )
{
}
ValueIterator::ValueIterator( const ValueIterator &other )
: ValueIteratorBase( other )
{
}
ValueIterator &
ValueIterator::operator =( const SelfType &other )
{
copy( other );
return *this;
}
-829
View File
@@ -1,829 +0,0 @@
#include <jsoncpp/include/json/writer.h>
#include <utility>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <sstream>
#include <iomanip>
#if _MSC_VER >= 1400 // VC++ 8.0
#pragma warning( disable : 4996 ) // disable warning about strdup being deprecated.
#endif
namespace Json {
static bool isControlCharacter(char ch)
{
return ch > 0 && ch <= 0x1F;
}
static bool containsControlCharacter( const char* str )
{
while ( *str )
{
if ( isControlCharacter( *(str++) ) )
return true;
}
return false;
}
static void uintToString( unsigned int value,
char *&current )
{
*--current = 0;
do
{
*--current = (value % 10) + '0';
value /= 10;
}
while ( value != 0 );
}
std::string valueToString( Int value )
{
char buffer[32];
char *current = buffer + sizeof(buffer);
bool isNegative = value < 0;
if ( isNegative )
value = -value;
uintToString( UInt(value), current );
if ( isNegative )
*--current = '-';
assert( current >= buffer );
return current;
}
std::string valueToString( UInt value )
{
char buffer[32];
char *current = buffer + sizeof(buffer);
uintToString( value, current );
assert( current >= buffer );
return current;
}
std::string valueToString( double value )
{
char buffer[32];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with visual studio 2005 to avoid warning.
sprintf_s(buffer, sizeof(buffer), "%#.16g", value);
#else
sprintf(buffer, "%#.16g", value);
#endif
char* ch = buffer + strlen(buffer) - 1;
if (*ch != '0') return buffer; // nothing to truncate, so save time
while(ch > buffer && *ch == '0'){
--ch;
}
char* last_nonzero = ch;
while(ch >= buffer){
switch(*ch){
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
--ch;
continue;
case '.':
// Truncate zeroes to save bytes in output, but keep one.
*(last_nonzero+2) = '\0';
return buffer;
default:
return buffer;
}
}
return buffer;
}
std::string valueToString( bool value )
{
return value ? "true" : "false";
}
std::string valueToQuotedString( const char *value )
{
// Not sure how to handle unicode...
if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter( value ))
return std::string("\"") + value + "\"";
// We have to walk value and escape any special characters.
// Appending to std::string is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
unsigned maxsize = strlen(value)*2 + 3; // allescaped+quotes+NULL
std::string result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
for (const char* c=value; *c != 0; ++c)
{
switch(*c)
{
case '\"':
result += "\\\"";
break;
case '\\':
result += "\\\\";
break;
case '\b':
result += "\\b";
break;
case '\f':
result += "\\f";
break;
case '\n':
result += "\\n";
break;
case '\r':
result += "\\r";
break;
case '\t':
result += "\\t";
break;
//case '/':
// Even though \/ is considered a legal escape in JSON, a bare
// slash is also legal, so I see no reason to escape it.
// (I hope I am not misunderstanding something.
// blep notes: actually escaping \/ may be useful in javascript to avoid </
// sequence.
// Should add a flag to allow this compatibility mode and prevent this
// sequence from occurring.
default:
if ( isControlCharacter( *c ) )
{
std::ostringstream oss;
oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4) << static_cast<int>(*c);
result += oss.str();
}
else
{
result += *c;
}
break;
}
}
result += "\"";
return result;
}
// Class Writer
// //////////////////////////////////////////////////////////////////
Writer::~Writer()
{
}
// Class FastWriter
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
: yamlCompatiblityEnabled_( false )
{
}
void
FastWriter::enableYAMLCompatibility()
{
yamlCompatiblityEnabled_ = true;
}
std::string
FastWriter::write( const Value &root )
{
document_ = "";
writeValue( root );
document_ += "\n";
return document_;
}
void
FastWriter::writeValue( const Value &value )
{
switch ( value.type() )
{
case nullValue:
document_ += "null";
break;
case intValue:
document_ += valueToString( value.asInt() );
break;
case uintValue:
document_ += valueToString( value.asUInt() );
break;
case realValue:
document_ += valueToString( value.asDouble() );
break;
case stringValue:
document_ += valueToQuotedString( value.asCString() );
break;
case booleanValue:
document_ += valueToString( value.asBool() );
break;
case arrayValue:
{
document_ += "[";
int size = value.size();
for ( int index =0; index < size; ++index )
{
if ( index > 0 )
document_ += ",";
writeValue( value[index] );
}
document_ += "]";
}
break;
case objectValue:
{
Value::Members members( value.getMemberNames() );
document_ += "{";
for ( Value::Members::iterator it = members.begin();
it != members.end();
++it )
{
const std::string &name = *it;
if ( it != members.begin() )
document_ += ",";
document_ += valueToQuotedString( name.c_str() );
document_ += yamlCompatiblityEnabled_ ? ": "
: ":";
writeValue( value[name] );
}
document_ += "}";
}
break;
}
}
// Class StyledWriter
// //////////////////////////////////////////////////////////////////
StyledWriter::StyledWriter()
: rightMargin_( 74 )
, indentSize_( 3 )
{
}
std::string
StyledWriter::write( const Value &root )
{
document_ = "";
addChildValues_ = false;
indentString_ = "";
writeCommentBeforeValue( root );
writeValue( root );
writeCommentAfterValueOnSameLine( root );
document_ += "\n";
return document_;
}
void
StyledWriter::writeValue( const Value &value )
{
switch ( value.type() )
{
case nullValue:
pushValue( "null" );
break;
case intValue:
pushValue( valueToString( value.asInt() ) );
break;
case uintValue:
pushValue( valueToString( value.asUInt() ) );
break;
case realValue:
pushValue( valueToString( value.asDouble() ) );
break;
case stringValue:
pushValue( valueToQuotedString( value.asCString() ) );
break;
case booleanValue:
pushValue( valueToString( value.asBool() ) );
break;
case arrayValue:
writeArrayValue( value);
break;
case objectValue:
{
Value::Members members( value.getMemberNames() );
if ( members.empty() )
pushValue( "{}" );
else
{
writeWithIndent( "{" );
indent();
Value::Members::iterator it = members.begin();
while ( true )
{
const std::string &name = *it;
const Value &childValue = value[name];
writeCommentBeforeValue( childValue );
writeWithIndent( valueToQuotedString( name.c_str() ) );
document_ += " : ";
writeValue( childValue );
if ( ++it == members.end() )
{
writeCommentAfterValueOnSameLine( childValue );
break;
}
document_ += ",";
writeCommentAfterValueOnSameLine( childValue );
}
unindent();
writeWithIndent( "}" );
}
}
break;
}
}
void
StyledWriter::writeArrayValue( const Value &value )
{
unsigned size = value.size();
if ( size == 0 )
pushValue( "[]" );
else
{
bool isArrayMultiLine = isMultineArray( value );
if ( isArrayMultiLine )
{
writeWithIndent( "[" );
indent();
bool hasChildValue = !childValues_.empty();
unsigned index =0;
while ( true )
{
const Value &childValue = value[index];
writeCommentBeforeValue( childValue );
if ( hasChildValue )
writeWithIndent( childValues_[index] );
else
{
writeIndent();
writeValue( childValue );
}
if ( ++index == size )
{
writeCommentAfterValueOnSameLine( childValue );
break;
}
document_ += ",";
writeCommentAfterValueOnSameLine( childValue );
}
unindent();
writeWithIndent( "]" );
}
else // output on a single line
{
assert( childValues_.size() == size );
document_ += "[ ";
for ( unsigned index =0; index < size; ++index )
{
if ( index > 0 )
document_ += ", ";
document_ += childValues_[index];
}
document_ += " ]";
}
}
}
bool
StyledWriter::isMultineArray( const Value &value )
{
int size = value.size();
bool isMultiLine = size*3 >= rightMargin_ ;
childValues_.clear();
for ( int index =0; index < size && !isMultiLine; ++index )
{
const Value &childValue = value[index];
isMultiLine = isMultiLine ||
( (childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0 );
}
if ( !isMultiLine ) // check if line length > max line length
{
childValues_.reserve( size );
addChildValues_ = true;
int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
for ( int index =0; index < size && !isMultiLine; ++index )
{
writeValue( value[index] );
lineLength += int( childValues_[index].length() );
isMultiLine = isMultiLine && hasCommentForValue( value[index] );
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
}
return isMultiLine;
}
void
StyledWriter::pushValue( const std::string &value )
{
if ( addChildValues_ )
childValues_.push_back( value );
else
document_ += value;
}
void
StyledWriter::writeIndent()
{
if ( !document_.empty() )
{
char last = document_[document_.length()-1];
if ( last == ' ' ) // already indented
return;
if ( last != '\n' ) // Comments may add new-line
document_ += '\n';
}
document_ += indentString_;
}
void
StyledWriter::writeWithIndent( const std::string &value )
{
writeIndent();
document_ += value;
}
void
StyledWriter::indent()
{
indentString_ += std::string( indentSize_, ' ' );
}
void
StyledWriter::unindent()
{
assert( int(indentString_.size()) >= indentSize_ );
indentString_.resize( indentString_.size() - indentSize_ );
}
void
StyledWriter::writeCommentBeforeValue( const Value &root )
{
if ( !root.hasComment( commentBefore ) )
return;
document_ += normalizeEOL( root.getComment( commentBefore ) );
document_ += "\n";
}
void
StyledWriter::writeCommentAfterValueOnSameLine( const Value &root )
{
if ( root.hasComment( commentAfterOnSameLine ) )
document_ += " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
if ( root.hasComment( commentAfter ) )
{
document_ += "\n";
document_ += normalizeEOL( root.getComment( commentAfter ) );
document_ += "\n";
}
}
bool
StyledWriter::hasCommentForValue( const Value &value )
{
return value.hasComment( commentBefore )
|| value.hasComment( commentAfterOnSameLine )
|| value.hasComment( commentAfter );
}
std::string
StyledWriter::normalizeEOL( const std::string &text )
{
std::string normalized;
normalized.reserve( text.length() );
const char *begin = text.c_str();
const char *end = begin + text.length();
const char *current = begin;
while ( current != end )
{
char c = *current++;
if ( c == '\r' ) // mac or dos EOL
{
if ( *current == '\n' ) // convert dos EOL
++current;
normalized += '\n';
}
else // handle unix EOL & other char
normalized += c;
}
return normalized;
}
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
StyledStreamWriter::StyledStreamWriter( std::string indentation )
: document_(NULL)
, rightMargin_( 74 )
, indentation_( indentation )
{
}
void
StyledStreamWriter::write( std::ostream &out, const Value &root )
{
document_ = &out;
addChildValues_ = false;
indentString_ = "";
writeCommentBeforeValue( root );
writeValue( root );
writeCommentAfterValueOnSameLine( root );
*document_ << "\n";
document_ = NULL; // Forget the stream, for safety.
}
void
StyledStreamWriter::writeValue( const Value &value )
{
switch ( value.type() )
{
case nullValue:
pushValue( "null" );
break;
case intValue:
pushValue( valueToString( value.asInt() ) );
break;
case uintValue:
pushValue( valueToString( value.asUInt() ) );
break;
case realValue:
pushValue( valueToString( value.asDouble() ) );
break;
case stringValue:
pushValue( valueToQuotedString( value.asCString() ) );
break;
case booleanValue:
pushValue( valueToString( value.asBool() ) );
break;
case arrayValue:
writeArrayValue( value);
break;
case objectValue:
{
Value::Members members( value.getMemberNames() );
if ( members.empty() )
pushValue( "{}" );
else
{
writeWithIndent( "{" );
indent();
Value::Members::iterator it = members.begin();
while ( true )
{
const std::string &name = *it;
const Value &childValue = value[name];
writeCommentBeforeValue( childValue );
writeWithIndent( valueToQuotedString( name.c_str() ) );
*document_ << " : ";
writeValue( childValue );
if ( ++it == members.end() )
{
writeCommentAfterValueOnSameLine( childValue );
break;
}
*document_ << ",";
writeCommentAfterValueOnSameLine( childValue );
}
unindent();
writeWithIndent( "}" );
}
}
break;
}
}
void
StyledStreamWriter::writeArrayValue( const Value &value )
{
unsigned size = value.size();
if ( size == 0 )
pushValue( "[]" );
else
{
bool isArrayMultiLine = isMultineArray( value );
if ( isArrayMultiLine )
{
writeWithIndent( "[" );
indent();
bool hasChildValue = !childValues_.empty();
unsigned index =0;
while ( true )
{
const Value &childValue = value[index];
writeCommentBeforeValue( childValue );
if ( hasChildValue )
writeWithIndent( childValues_[index] );
else
{
writeIndent();
writeValue( childValue );
}
if ( ++index == size )
{
writeCommentAfterValueOnSameLine( childValue );
break;
}
*document_ << ",";
writeCommentAfterValueOnSameLine( childValue );
}
unindent();
writeWithIndent( "]" );
}
else // output on a single line
{
assert( childValues_.size() == size );
*document_ << "[ ";
for ( unsigned index =0; index < size; ++index )
{
if ( index > 0 )
*document_ << ", ";
*document_ << childValues_[index];
}
*document_ << " ]";
}
}
}
bool
StyledStreamWriter::isMultineArray( const Value &value )
{
int size = value.size();
bool isMultiLine = size*3 >= rightMargin_ ;
childValues_.clear();
for ( int index =0; index < size && !isMultiLine; ++index )
{
const Value &childValue = value[index];
isMultiLine = isMultiLine ||
( (childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0 );
}
if ( !isMultiLine ) // check if line length > max line length
{
childValues_.reserve( size );
addChildValues_ = true;
int lineLength = 4 + (size-1)*2; // '[ ' + ', '*n + ' ]'
for ( int index =0; index < size && !isMultiLine; ++index )
{
writeValue( value[index] );
lineLength += int( childValues_[index].length() );
isMultiLine = isMultiLine && hasCommentForValue( value[index] );
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
}
return isMultiLine;
}
void
StyledStreamWriter::pushValue( const std::string &value )
{
if ( addChildValues_ )
childValues_.push_back( value );
else
*document_ << value;
}
void
StyledStreamWriter::writeIndent()
{
/*
Some comments in this method would have been nice. ;-)
if ( !document_.empty() )
{
char last = document_[document_.length()-1];
if ( last == ' ' ) // already indented
return;
if ( last != '\n' ) // Comments may add new-line
*document_ << '\n';
}
*/
*document_ << '\n' << indentString_;
}
void
StyledStreamWriter::writeWithIndent( const std::string &value )
{
writeIndent();
*document_ << value;
}
void
StyledStreamWriter::indent()
{
indentString_ += indentation_;
}
void
StyledStreamWriter::unindent()
{
assert( indentString_.size() >= indentation_.size() );
indentString_.resize( indentString_.size() - indentation_.size() );
}
void
StyledStreamWriter::writeCommentBeforeValue( const Value &root )
{
if ( !root.hasComment( commentBefore ) )
return;
*document_ << normalizeEOL( root.getComment( commentBefore ) );
*document_ << "\n";
}
void
StyledStreamWriter::writeCommentAfterValueOnSameLine( const Value &root )
{
if ( root.hasComment( commentAfterOnSameLine ) )
*document_ << " " + normalizeEOL( root.getComment( commentAfterOnSameLine ) );
if ( root.hasComment( commentAfter ) )
{
*document_ << "\n";
*document_ << normalizeEOL( root.getComment( commentAfter ) );
*document_ << "\n";
}
}
bool
StyledStreamWriter::hasCommentForValue( const Value &value )
{
return value.hasComment( commentBefore )
|| value.hasComment( commentAfterOnSameLine )
|| value.hasComment( commentAfter );
}
std::string
StyledStreamWriter::normalizeEOL( const std::string &text )
{
std::string normalized;
normalized.reserve( text.length() );
const char *begin = text.c_str();
const char *end = begin + text.length();
const char *current = begin;
while ( current != end )
{
char c = *current++;
if ( c == '\r' ) // mac or dos EOL
{
if ( *current == '\n' ) // convert dos EOL
++current;
normalized += '\n';
}
else // handle unix EOL & other char
normalized += c;
}
return normalized;
}
std::ostream& operator<<( std::ostream &sout, const Value &root )
{
Json::StyledStreamWriter writer;
writer.write(sout, root);
return sout;
}
} // namespace Json
-8
View File
@@ -1,8 +0,0 @@
Import( 'env buildLibrary' )
buildLibrary( env, Split( """
json_reader.cpp
json_value.cpp
json_writer.cpp
""" ),
'json' )
-1
View File
@@ -1 +0,0 @@
0.5.0
-38
View File
@@ -1,38 +0,0 @@
/* jconfig.xmingw32msvc --- jconfig.h for mingw32/msvc. */
/* see jconfig.doc for explanations */
#define HAVE_PROTOTYPES
#define HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_SHORT
/* #define void char */
/* #define const */
#undef CHAR_IS_UNSIGNED
#define HAVE_STDDEF_H
#define HAVE_STDLIB_H
#undef NEED_BSD_STRINGS
#undef NEED_SYS_TYPES_H
#undef NEED_FAR_POINTERS /* win32 uses flat 32-bit addressing */
#undef NEED_SHORT_EXTERNAL_NAMES
#undef INCOMPLETE_TYPES_BROKEN
#ifdef JPEG_INTERNALS
#undef RIGHT_SHIFT_IS_UNSIGNED
#endif /* JPEG_INTERNALS */
#ifdef JPEG_CJPEG_DJPEG
#define BMP_SUPPORTED /* BMP image file format */
#define GIF_SUPPORTED /* GIF image file format */
#define PPM_SUPPORTED /* PBMPLUS PPM/PGM image file format */
#undef RLE_SUPPORTED /* Utah RLE image file format */
#define TARGA_SUPPORTED /* Targa image file format */
#undef TWO_FILE_COMMANDLINE /* optional */
#define USE_SETMODE /* Needed to make one-file style work in DJGPP */
#undef NEED_SIGNAL_CATCHER /* Define this if you use jmemname.c */
#undef DONT_USE_B_MODE
#undef PROGRESS_REPORT /* optional */
#endif /* JPEG_CJPEG_DJPEG */
-291
View File
@@ -1,291 +0,0 @@
/*
* jerror.h
*
* Copyright (C) 1994-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file defines the error and message codes for the JPEG library.
* Edit this file to add new codes, or to translate the message strings to
* some other language.
* A set of error-reporting macros are defined too. Some applications using
* the JPEG library may wish to include this file to get the error codes
* and/or the macros.
*/
/*
* To define the enum list of message codes, include this file without
* defining macro JMESSAGE. To create a message string table, include it
* again with a suitable JMESSAGE definition (see jerror.c for an example).
*/
#ifndef JMESSAGE
#ifndef JERROR_H
/* First time through, define the enum list */
#define JMAKE_ENUM_LIST
#else
/* Repeated inclusions of this file are no-ops unless JMESSAGE is defined */
#define JMESSAGE(code,string)
#endif /* JERROR_H */
#endif /* JMESSAGE */
#ifdef JMAKE_ENUM_LIST
typedef enum {
#define JMESSAGE(code,string) code ,
#endif /* JMAKE_ENUM_LIST */
JMESSAGE(JMSG_NOMESSAGE, "Bogus message code %d") /* Must be first entry! */
/* For maintenance convenience, list is alphabetical by message code name */
JMESSAGE(JERR_ARITH_NOTIMPL,
"Sorry, there are legal restrictions on arithmetic coding")
JMESSAGE(JERR_BAD_ALIGN_TYPE, "ALIGN_TYPE is wrong, please fix")
JMESSAGE(JERR_BAD_ALLOC_CHUNK, "MAX_ALLOC_CHUNK is wrong, please fix")
JMESSAGE(JERR_BAD_BUFFER_MODE, "Bogus buffer control mode")
JMESSAGE(JERR_BAD_COMPONENT_ID, "Invalid component ID %d in SOS")
JMESSAGE(JERR_BAD_DCT_COEF, "DCT coefficient out of range")
JMESSAGE(JERR_BAD_DCTSIZE, "IDCT output block size %d not supported")
JMESSAGE(JERR_BAD_HUFF_TABLE, "Bogus Huffman table definition")
JMESSAGE(JERR_BAD_IN_COLORSPACE, "Bogus input colorspace")
JMESSAGE(JERR_BAD_J_COLORSPACE, "Bogus JPEG colorspace")
JMESSAGE(JERR_BAD_LENGTH, "Bogus marker length")
JMESSAGE(JERR_BAD_LIB_VERSION,
"Wrong JPEG library version: library is %d, caller expects %d")
JMESSAGE(JERR_BAD_MCU_SIZE, "Sampling factors too large for interleaved scan")
JMESSAGE(JERR_BAD_POOL_ID, "Invalid memory pool code %d")
JMESSAGE(JERR_BAD_PRECISION, "Unsupported JPEG data precision %d")
JMESSAGE(JERR_BAD_PROGRESSION,
"Invalid progressive parameters Ss=%d Se=%d Ah=%d Al=%d")
JMESSAGE(JERR_BAD_PROG_SCRIPT,
"Invalid progressive parameters at scan script entry %d")
JMESSAGE(JERR_BAD_SAMPLING, "Bogus sampling factors")
JMESSAGE(JERR_BAD_SCAN_SCRIPT, "Invalid scan script at entry %d")
JMESSAGE(JERR_BAD_STATE, "Improper call to JPEG library in state %d")
JMESSAGE(JERR_BAD_STRUCT_SIZE,
"JPEG parameter struct mismatch: library thinks size is %u, caller expects %u")
JMESSAGE(JERR_BAD_VIRTUAL_ACCESS, "Bogus virtual array access")
JMESSAGE(JERR_BUFFER_SIZE, "Buffer passed to JPEG library is too small")
JMESSAGE(JERR_CANT_SUSPEND, "Suspension not allowed here")
JMESSAGE(JERR_CCIR601_NOTIMPL, "CCIR601 sampling not implemented yet")
JMESSAGE(JERR_COMPONENT_COUNT, "Too many color components: %d, max %d")
JMESSAGE(JERR_CONVERSION_NOTIMPL, "Unsupported color conversion request")
JMESSAGE(JERR_DAC_INDEX, "Bogus DAC index %d")
JMESSAGE(JERR_DAC_VALUE, "Bogus DAC value 0x%x")
JMESSAGE(JERR_DHT_INDEX, "Bogus DHT index %d")
JMESSAGE(JERR_DQT_INDEX, "Bogus DQT index %d")
JMESSAGE(JERR_EMPTY_IMAGE, "Empty JPEG image (DNL not supported)")
JMESSAGE(JERR_EMS_READ, "Read from EMS failed")
JMESSAGE(JERR_EMS_WRITE, "Write to EMS failed")
JMESSAGE(JERR_EOI_EXPECTED, "Didn't expect more than one scan")
JMESSAGE(JERR_FILE_READ, "Input file read error")
JMESSAGE(JERR_FILE_WRITE, "Output file write error --- out of disk space?")
JMESSAGE(JERR_FRACT_SAMPLE_NOTIMPL, "Fractional sampling not implemented yet")
JMESSAGE(JERR_HUFF_CLEN_OVERFLOW, "Huffman code size table overflow")
JMESSAGE(JERR_HUFF_MISSING_CODE, "Missing Huffman code table entry")
JMESSAGE(JERR_IMAGE_TOO_BIG, "Maximum supported image dimension is %u pixels")
JMESSAGE(JERR_INPUT_EMPTY, "Empty input file")
JMESSAGE(JERR_INPUT_EOF, "Premature end of input file")
JMESSAGE(JERR_MISMATCHED_QUANT_TABLE,
"Cannot transcode due to multiple use of quantization table %d")
JMESSAGE(JERR_MISSING_DATA, "Scan script does not transmit all data")
JMESSAGE(JERR_MODE_CHANGE, "Invalid color quantization mode change")
JMESSAGE(JERR_NOTIMPL, "Not implemented yet")
JMESSAGE(JERR_NOT_COMPILED, "Requested feature was omitted at compile time")
JMESSAGE(JERR_NO_BACKING_STORE, "Backing store not supported")
JMESSAGE(JERR_NO_HUFF_TABLE, "Huffman table 0x%02x was not defined")
JMESSAGE(JERR_NO_IMAGE, "JPEG datastream contains no image")
JMESSAGE(JERR_NO_QUANT_TABLE, "Quantization table 0x%02x was not defined")
JMESSAGE(JERR_NO_SOI, "Not a JPEG file: starts with 0x%02x 0x%02x")
JMESSAGE(JERR_OUT_OF_MEMORY, "Insufficient memory (case %d)")
JMESSAGE(JERR_QUANT_COMPONENTS,
"Cannot quantize more than %d color components")
JMESSAGE(JERR_QUANT_FEW_COLORS, "Cannot quantize to fewer than %d colors")
JMESSAGE(JERR_QUANT_MANY_COLORS, "Cannot quantize to more than %d colors")
JMESSAGE(JERR_SOF_DUPLICATE, "Invalid JPEG file structure: two SOF markers")
JMESSAGE(JERR_SOF_NO_SOS, "Invalid JPEG file structure: missing SOS marker")
JMESSAGE(JERR_SOF_UNSUPPORTED, "Unsupported JPEG process: SOF type 0x%02x")
JMESSAGE(JERR_SOI_DUPLICATE, "Invalid JPEG file structure: two SOI markers")
JMESSAGE(JERR_SOS_NO_SOF, "Invalid JPEG file structure: SOS before SOF")
JMESSAGE(JERR_TFILE_CREATE, "Failed to create temporary file %s")
JMESSAGE(JERR_TFILE_READ, "Read failed on temporary file")
JMESSAGE(JERR_TFILE_SEEK, "Seek failed on temporary file")
JMESSAGE(JERR_TFILE_WRITE,
"Write failed on temporary file --- out of disk space?")
JMESSAGE(JERR_TOO_LITTLE_DATA, "Application transferred too few scanlines")
JMESSAGE(JERR_UNKNOWN_MARKER, "Unsupported marker type 0x%02x")
JMESSAGE(JERR_VIRTUAL_BUG, "Virtual array controller messed up")
JMESSAGE(JERR_WIDTH_OVERFLOW, "Image too wide for this implementation")
JMESSAGE(JERR_XMS_READ, "Read from XMS failed")
JMESSAGE(JERR_XMS_WRITE, "Write to XMS failed")
JMESSAGE(JMSG_COPYRIGHT, JCOPYRIGHT)
JMESSAGE(JMSG_VERSION, JVERSION)
JMESSAGE(JTRC_16BIT_TABLES,
"Caution: quantization tables are too coarse for baseline JPEG")
JMESSAGE(JTRC_ADOBE,
"Adobe APP14 marker: version %d, flags 0x%04x 0x%04x, transform %d")
JMESSAGE(JTRC_APP0, "Unknown APP0 marker (not JFIF), length %u")
JMESSAGE(JTRC_APP14, "Unknown APP14 marker (not Adobe), length %u")
JMESSAGE(JTRC_DAC, "Define Arithmetic Table 0x%02x: 0x%02x")
JMESSAGE(JTRC_DHT, "Define Huffman Table 0x%02x")
JMESSAGE(JTRC_DQT, "Define Quantization Table %d precision %d")
JMESSAGE(JTRC_DRI, "Define Restart Interval %u")
JMESSAGE(JTRC_EMS_CLOSE, "Freed EMS handle %u")
JMESSAGE(JTRC_EMS_OPEN, "Obtained EMS handle %u")
JMESSAGE(JTRC_EOI, "End Of Image")
JMESSAGE(JTRC_HUFFBITS, " %3d %3d %3d %3d %3d %3d %3d %3d")
JMESSAGE(JTRC_JFIF, "JFIF APP0 marker: version %d.%02d, density %dx%d %d")
JMESSAGE(JTRC_JFIF_BADTHUMBNAILSIZE,
"Warning: thumbnail image size does not match data length %u")
JMESSAGE(JTRC_JFIF_EXTENSION,
"JFIF extension marker: type 0x%02x, length %u")
JMESSAGE(JTRC_JFIF_THUMBNAIL, " with %d x %d thumbnail image")
JMESSAGE(JTRC_MISC_MARKER, "Miscellaneous marker 0x%02x, length %u")
JMESSAGE(JTRC_PARMLESS_MARKER, "Unexpected marker 0x%02x")
JMESSAGE(JTRC_QUANTVALS, " %4u %4u %4u %4u %4u %4u %4u %4u")
JMESSAGE(JTRC_QUANT_3_NCOLORS, "Quantizing to %d = %d*%d*%d colors")
JMESSAGE(JTRC_QUANT_NCOLORS, "Quantizing to %d colors")
JMESSAGE(JTRC_QUANT_SELECTED, "Selected %d colors for quantization")
JMESSAGE(JTRC_RECOVERY_ACTION, "At marker 0x%02x, recovery action %d")
JMESSAGE(JTRC_RST, "RST%d")
JMESSAGE(JTRC_SMOOTH_NOTIMPL,
"Smoothing not supported with nonstandard sampling ratios")
JMESSAGE(JTRC_SOF, "Start Of Frame 0x%02x: width=%u, height=%u, components=%d")
JMESSAGE(JTRC_SOF_COMPONENT, " Component %d: %dhx%dv q=%d")
JMESSAGE(JTRC_SOI, "Start of Image")
JMESSAGE(JTRC_SOS, "Start Of Scan: %d components")
JMESSAGE(JTRC_SOS_COMPONENT, " Component %d: dc=%d ac=%d")
JMESSAGE(JTRC_SOS_PARAMS, " Ss=%d, Se=%d, Ah=%d, Al=%d")
JMESSAGE(JTRC_TFILE_CLOSE, "Closed temporary file %s")
JMESSAGE(JTRC_TFILE_OPEN, "Opened temporary file %s")
JMESSAGE(JTRC_THUMB_JPEG,
"JFIF extension marker: JPEG-compressed thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_PALETTE,
"JFIF extension marker: palette thumbnail image, length %u")
JMESSAGE(JTRC_THUMB_RGB,
"JFIF extension marker: RGB thumbnail image, length %u")
JMESSAGE(JTRC_UNKNOWN_IDS,
"Unrecognized component IDs %d %d %d, assuming YCbCr")
JMESSAGE(JTRC_XMS_CLOSE, "Freed XMS handle %u")
JMESSAGE(JTRC_XMS_OPEN, "Obtained XMS handle %u")
JMESSAGE(JWRN_ADOBE_XFORM, "Unknown Adobe color transform code %d")
JMESSAGE(JWRN_BOGUS_PROGRESSION,
"Inconsistent progression sequence for component %d coefficient %d")
JMESSAGE(JWRN_EXTRANEOUS_DATA,
"Corrupt JPEG data: %u extraneous bytes before marker 0x%02x")
JMESSAGE(JWRN_HIT_MARKER, "Corrupt JPEG data: premature end of data segment")
JMESSAGE(JWRN_HUFF_BAD_CODE, "Corrupt JPEG data: bad Huffman code")
JMESSAGE(JWRN_JFIF_MAJOR, "Warning: unknown JFIF revision number %d.%02d")
JMESSAGE(JWRN_JPEG_EOF, "Premature end of JPEG file")
JMESSAGE(JWRN_MUST_RESYNC,
"Corrupt JPEG data: found marker 0x%02x instead of RST%d")
JMESSAGE(JWRN_NOT_SEQUENTIAL, "Invalid SOS parameters for sequential JPEG")
JMESSAGE(JWRN_TOO_MUCH_DATA, "Application transferred too many scanlines")
#ifdef JMAKE_ENUM_LIST
JMSG_LASTMSGCODE
} J_MESSAGE_CODE;
#undef JMAKE_ENUM_LIST
#endif /* JMAKE_ENUM_LIST */
/* Zap JMESSAGE macro so that future re-inclusions do nothing by default */
#undef JMESSAGE
#ifndef JERROR_H
#define JERROR_H
/* Macros to simplify using the error and trace message stuff */
/* The first parameter is either type of cinfo pointer */
/* Fatal errors (print message and exit) */
#define ERREXIT(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT3(cinfo,code,p1,p2,p3) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(cinfo)->err->msg_parm.i[2] = (p3), \
(cinfo)->err->msg_parm.i[3] = (p4), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define ERREXITS(cinfo,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo)))
#define MAKESTMT(stuff) do { stuff } while (0)
/* Nonfatal errors (we can keep going, but the data is probably corrupt) */
#define WARNMS(cinfo,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS1(cinfo,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
#define WARNMS2(cinfo,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1))
/* Informational/debugging messages */
#define TRACEMS(cinfo,lvl,code) \
((cinfo)->err->msg_code = (code), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS1(cinfo,lvl,code,p1) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS2(cinfo,lvl,code,p1,p2) \
((cinfo)->err->msg_code = (code), \
(cinfo)->err->msg_parm.i[0] = (p1), \
(cinfo)->err->msg_parm.i[1] = (p2), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \
MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \
_mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \
_mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \
(cinfo)->err->msg_code = (code); \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); )
#define TRACEMSS(cinfo,lvl,code,str) \
((cinfo)->err->msg_code = (code), \
strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \
(*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)))
#endif /* JERROR_H */
-371
View File
@@ -1,371 +0,0 @@
/*
* jmorecfg.h
*
* Copyright (C) 1991-1997, Thomas G. Lane.
* This file is part of the Independent JPEG Group's software.
* For conditions of distribution and use, see the accompanying README file.
*
* This file contains additional configuration options that customize the
* JPEG software for special applications or support machine-dependent
* optimizations. Most users will not need to touch this file.
*/
/*
* Define BITS_IN_JSAMPLE as either
* 8 for 8-bit sample values (the usual setting)
* 12 for 12-bit sample values
* Only 8 and 12 are legal data precisions for lossy JPEG according to the
* JPEG standard, and the IJG code does not support anything else!
* We do not support run-time selection of data precision, sorry.
*/
#define BITS_IN_JSAMPLE 8 /* use 8 or 12 */
/*
* Maximum number of components (color channels) allowed in JPEG image.
* To meet the letter of the JPEG spec, set this to 255. However, darn
* few applications need more than 4 channels (maybe 5 for CMYK + alpha
* mask). We recommend 10 as a reasonable compromise; use 4 if you are
* really short on memory. (Each allowed component costs a hundred or so
* bytes of storage, whether actually used in an image or not.)
*/
#define MAX_COMPONENTS 10 /* maximum number of image components */
/*
* Basic data types.
* You may need to change these if you have a machine with unusual data
* type sizes; for example, "char" not 8 bits, "short" not 16 bits,
* or "long" not 32 bits. We don't care whether "int" is 16 or 32 bits,
* but it had better be at least 16.
*/
/* Representation of a single sample (pixel element value).
* We frequently allocate large arrays of these, so it's important to keep
* them small. But if you have memory to burn and access to char or short
* arrays is very slow on your hardware, you might want to change these.
*/
#if BITS_IN_JSAMPLE == 8
/* JSAMPLE should be the smallest type that will hold the values 0..255.
* You can use a signed char by having GETJSAMPLE mask it with 0xFF.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JSAMPLE;
#ifdef CHAR_IS_UNSIGNED
#define GETJSAMPLE(value) ((int) (value))
#else
#define GETJSAMPLE(value) ((int) (value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
#define MAXJSAMPLE 255
#define CENTERJSAMPLE 128
#endif /* BITS_IN_JSAMPLE == 8 */
#if BITS_IN_JSAMPLE == 12
/* JSAMPLE should be the smallest type that will hold the values 0..4095.
* On nearly all machines "short" will do nicely.
*/
typedef short JSAMPLE;
#define GETJSAMPLE(value) ((int) (value))
#define MAXJSAMPLE 4095
#define CENTERJSAMPLE 2048
#endif /* BITS_IN_JSAMPLE == 12 */
/* Representation of a DCT frequency coefficient.
* This should be a signed value of at least 16 bits; "short" is usually OK.
* Again, we allocate large arrays of these, but you can change to int
* if you have memory to burn and "short" is really slow.
*/
typedef short JCOEF;
/* Compressed datastreams are represented as arrays of JOCTET.
* These must be EXACTLY 8 bits wide, at least once they are written to
* external storage. Note that when using the stdio data source/destination
* managers, this is also the data type passed to fread/fwrite.
*/
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char JOCTET;
#define GETJOCTET(value) (value)
#else /* not HAVE_UNSIGNED_CHAR */
typedef char JOCTET;
#ifdef CHAR_IS_UNSIGNED
#define GETJOCTET(value) (value)
#else
#define GETJOCTET(value) ((value) & 0xFF)
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* These typedefs are used for various table entries and so forth.
* They must be at least as wide as specified; but making them too big
* won't cost a huge amount of memory, so we don't provide special
* extraction code like we did for JSAMPLE. (In other words, these
* typedefs live at a different point on the speed/space tradeoff curve.)
*/
/* UINT8 must hold at least the values 0..255. */
#ifdef HAVE_UNSIGNED_CHAR
typedef unsigned char UINT8;
#else /* not HAVE_UNSIGNED_CHAR */
#ifdef CHAR_IS_UNSIGNED
typedef char UINT8;
#else /* not CHAR_IS_UNSIGNED */
typedef short UINT8;
#endif /* CHAR_IS_UNSIGNED */
#endif /* HAVE_UNSIGNED_CHAR */
/* UINT16 must hold at least the values 0..65535. */
#ifdef HAVE_UNSIGNED_SHORT
typedef unsigned short UINT16;
#else /* not HAVE_UNSIGNED_SHORT */
typedef unsigned int UINT16;
#endif /* HAVE_UNSIGNED_SHORT */
/* INT16 must hold at least the values -32768..32767. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT16 */
typedef short INT16;
#endif
/* INT32 must hold at least signed 32-bit values. */
#ifndef XMD_H /* X11/xmd.h correctly defines INT32 */
typedef long INT32;
#endif
/* Datatype used for image dimensions. The JPEG standard only supports
* images up to 64K*64K due to 16-bit fields in SOF markers. Therefore
* "unsigned int" is sufficient on all machines. However, if you need to
* handle larger images and you don't mind deviating from the spec, you
* can change this datatype.
*/
typedef unsigned int JDIMENSION;
#define JPEG_MAX_DIMENSION 65500L /* a tad under 64K to prevent overflows */
/* These macros are used in all function definitions and extern declarations.
* You could modify them if you need to change function linkage conventions;
* in particular, you'll need to do that to make the library a Windows DLL.
* Another application is to make all functions global for use with debuggers
* or code profilers that require it.
*/
/* a function called through method pointers: */
#define METHODDEF(type) static type
/* a function used only in its module: */
#define LOCAL(type) static type
/* a function referenced thru EXTERNs: */
#define GLOBAL(type) type
/* a reference to a GLOBAL function: */
#if defined(WIN32)
# ifdef BUILDING_JPEG_DLL
# define DLLIMPORT __declspec (dllexport)
# else
# define DLLIMPORT __declspec (dllimport)
# endif
# define EXTERN(type) DLLIMPORT extern type
#else
#define EXTERN(type) extern type
#endif
/* This macro is used to declare a "method", that is, a function pointer.
* We want to supply prototype parameters if the compiler can cope.
* Note that the arglist parameter must be parenthesized!
* Again, you can customize this if you need special linkage keywords.
*/
#ifdef HAVE_PROTOTYPES
#define JMETHOD(type,methodname,arglist) type (*methodname) arglist
#else
#define JMETHOD(type,methodname,arglist) type (*methodname) ()
#endif
/* Here is the pseudo-keyword for declaring pointers that must be "far"
* on 80x86 machines. Most of the specialized coding for 80x86 is handled
* by just saying "FAR *" where such a pointer is needed. In a few places
* explicit coding is needed; see uses of the NEED_FAR_POINTERS symbol.
*/
#ifdef NEED_FAR_POINTERS
#define FAR far
#else
#define FAR
#endif
/*
* On a few systems, type boolean and/or its values FALSE, TRUE may appear
* in standard header files. Or you may have conflicts with application-
* specific header files that you want to include together with these files.
* Defining HAVE_BOOLEAN before including jpeglib.h should make it work.
*/
#ifndef HAVE_BOOLEAN
typedef int boolean;
#endif
#ifndef FALSE /* in case these macros already exist */
#define FALSE 0 /* values of boolean */
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
* The remaining options affect code selection within the JPEG library,
* but they don't need to be visible to most applications using the library.
* To minimize application namespace pollution, the symbols won't be
* defined unless JPEG_INTERNALS or JPEG_INTERNAL_OPTIONS has been defined.
*/
#ifdef JPEG_INTERNALS
#define JPEG_INTERNAL_OPTIONS
#endif
#ifdef JPEG_INTERNAL_OPTIONS
/*
* These defines indicate whether to include various optional functions.
* Undefining some of these symbols will produce a smaller but less capable
* library. Note that you can leave certain source files out of the
* compilation/linking process if you've #undef'd the corresponding symbols.
* (You may HAVE to do that if your compiler doesn't like null source files.)
*/
/* Arithmetic coding is unsupported for legal reasons. Complaints to IBM. */
/* Capability options common to encoder and decoder: */
#define DCT_ISLOW_SUPPORTED /* slow but accurate integer algorithm */
#define DCT_IFAST_SUPPORTED /* faster, less accurate integer method */
#define DCT_FLOAT_SUPPORTED /* floating-point: accurate, fast on fast HW */
/* Encoder capability options: */
#undef C_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define C_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define C_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define ENTROPY_OPT_SUPPORTED /* Optimization of entropy coding parms? */
/* Note: if you selected 12-bit data precision, it is dangerous to turn off
* ENTROPY_OPT_SUPPORTED. The standard Huffman tables are only good for 8-bit
* precision, so jchuff.c normally uses entropy optimization to compute
* usable tables for higher precision. If you don't want to do optimization,
* you'll have to supply different default Huffman tables.
* The exact same statements apply for progressive JPEG: the default tables
* don't work for progressive mode. (This may get fixed, however.)
*/
#define INPUT_SMOOTHING_SUPPORTED /* Input image smoothing option? */
/* Decoder capability options: */
#undef D_ARITH_CODING_SUPPORTED /* Arithmetic coding back end? */
#define D_MULTISCAN_FILES_SUPPORTED /* Multiple-scan JPEG files? */
#define D_PROGRESSIVE_SUPPORTED /* Progressive JPEG? (Requires MULTISCAN)*/
#define SAVE_MARKERS_SUPPORTED /* jpeg_save_markers() needed? */
#define BLOCK_SMOOTHING_SUPPORTED /* Block smoothing? (Progressive only) */
#define IDCT_SCALING_SUPPORTED /* Output rescaling via IDCT? */
#undef UPSAMPLE_SCALING_SUPPORTED /* Output rescaling at upsample stage? */
#define UPSAMPLE_MERGING_SUPPORTED /* Fast path for sloppy upsampling? */
#define QUANT_1PASS_SUPPORTED /* 1-pass color quantization? */
#define QUANT_2PASS_SUPPORTED /* 2-pass color quantization? */
/* more capability options later, no doubt */
/*
* Ordering of RGB data in scanlines passed to or from the application.
* If your application wants to deal with data in the order B,G,R, just
* change these macros. You can also deal with formats such as R,G,B,X
* (one extra byte per pixel) by changing RGB_PIXELSIZE. Note that changing
* the offsets will also change the order in which colormap data is organized.
* RESTRICTIONS:
* 1. The sample applications cjpeg,djpeg do NOT support modified RGB formats.
* 2. These macros only affect RGB<=>YCbCr color conversion, so they are not
* useful if you are using JPEG color spaces other than YCbCr or grayscale.
* 3. The color quantizer modules will not behave desirably if RGB_PIXELSIZE
* is not 3 (they don't understand about dummy color components!). So you
* can't use color quantization if you change that value.
*/
#define RGB_RED 0 /* Offset of Red in an RGB scanline element */
#define RGB_GREEN 1 /* Offset of Green */
#define RGB_BLUE 2 /* Offset of Blue */
#define RGB_PIXELSIZE 3 /* JSAMPLEs per RGB scanline element */
/* Definitions for speed-related optimizations. */
/* If your compiler supports inline functions, define INLINE
* as the inline keyword; otherwise define it as empty.
*/
#ifndef INLINE
#ifdef __GNUC__ /* for instance, GNU C knows about inline */
#define INLINE __inline__
#endif
#ifndef INLINE
#define INLINE /* default is to define it as empty */
#endif
#endif
/* On some machines (notably 68000 series) "int" is 32 bits, but multiplying
* two 16-bit shorts is faster than multiplying two ints. Define MULTIPLIER
* as short on such a machine. MULTIPLIER must be at least 16 bits wide.
*/
#ifndef MULTIPLIER
#define MULTIPLIER int /* type for fastest integer multiply */
#endif
/* FAST_FLOAT should be either float or double, whichever is done faster
* by your compiler. (Note that this type is only used in the floating point
* DCT routines, so it only matters if you've defined DCT_FLOAT_SUPPORTED.)
* Typically, float is faster in ANSI C compilers, while double is faster in
* pre-ANSI compilers (because they insist on converting to double anyway).
* The code below therefore chooses float if we have ANSI-style prototypes.
*/
#ifndef FAST_FLOAT
#ifdef HAVE_PROTOTYPES
#define FAST_FLOAT float
#else
#define FAST_FLOAT double
#endif
#endif
#endif /* JPEG_INTERNAL_OPTIONS */
Binary file not shown.
File diff suppressed because it is too large Load Diff
Binary file not shown.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
-34
View File
@@ -1,34 +0,0 @@
Lua License
-----------
Lua is licensed under the terms of the MIT license reproduced below.
This means that Lua is free software and can be used for both academic
and commercial purposes at absolutely no cost.
For details and rationale, see http://www.lua.org/license.html .
===============================================================================
Copyright (C) 1994-2006 Lua.org, PUC-Rio.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
===============================================================================
(end of COPYRIGHT)

Some files were not shown because too many files have changed in this diff Show More