@@ -46,7 +46,7 @@ protected DocumentLoader()
4646 public virtual uint MaxCacheSize
4747 {
4848 get => 0 ;
49- set => throw new NotSupportedException ( "Loader does not support caching" ) ;
49+ set => throw new NotSupportedException ( "The document loader does not support caching" ) ;
5050 }
5151
5252 /// <summary>
@@ -101,6 +101,30 @@ public virtual Document LoadDocument(DocumentSettings settings, DocumentInfo? so
101101 /// </remarks>
102102 public abstract Task < Document > LoadDocumentAsync ( DocumentSettings settings , DocumentInfo ? sourceInfo , string specifier , DocumentCategory category , DocumentContextCallback contextCallback ) ;
103103
104+ /// <summary>
105+ /// Searches for a cached document by <see cref="DocumentInfo.Uri">URI</see>.
106+ /// </summary>
107+ /// <param name="uri">The document URI for which to search.</param>
108+ /// <returns>The cached document if it was found, <c>null</c> otherwise.</returns>
109+ public virtual Document GetCachedDocument ( Uri uri )
110+ {
111+ return null ;
112+ }
113+
114+ /// <summary>
115+ /// Stores a document in the cache.
116+ /// </summary>
117+ /// <param name="document">The document to store in the cache.</param>
118+ /// <param name="replace"><c>True</c> to replace any existing document with the same URI, <c>false</c> otherwise.</param>
119+ /// <returns>The cached document, which may be different from <paramref name="document"/> if <paramref name="replace"/> is <c>false</c>.</returns>
120+ /// <remarks>
121+ /// A cached document must have an absolute <see cref="DocumentInfo.Uri">URI</see>.
122+ /// </remarks>
123+ public virtual Document CacheDocument ( Document document , bool replace )
124+ {
125+ throw new NotSupportedException ( "The document loader does not support caching" ) ;
126+ }
127+
104128 /// <summary>
105129 /// Discards all cached documents.
106130 /// </summary>
@@ -359,48 +383,7 @@ private async Task<Document> LoadDocumentAsync(DocumentSettings settings, Uri ur
359383 var callback = settings . LoadCallback ;
360384 callback ? . Invoke ( ref documentInfo ) ;
361385
362- return CacheDocument ( new StringDocument ( documentInfo , contents ) ) ;
363- }
364-
365- private Document GetCachedDocument ( Uri uri )
366- {
367- lock ( cache )
368- {
369- for ( var index = 0 ; index < cache . Count ; index ++ )
370- {
371- var cachedDocument = cache [ index ] ;
372- if ( cachedDocument . Info . Uri == uri )
373- {
374- cache . RemoveAt ( index ) ;
375- cache . Insert ( 0 , cachedDocument ) ;
376- return cachedDocument ;
377- }
378- }
379-
380- return null ;
381- }
382- }
383-
384- private Document CacheDocument ( Document document )
385- {
386- lock ( cache )
387- {
388- var cachedDocument = cache . FirstOrDefault ( testDocument => testDocument . Info . Uri == document . Info . Uri ) ;
389- if ( cachedDocument != null )
390- {
391- Debug . Assert ( cachedDocument . Contents . ReadToEnd ( ) . SequenceEqual ( document . Contents . ReadToEnd ( ) ) ) ;
392- return cachedDocument ;
393- }
394-
395- var maxCacheSize = Math . Max ( 16 , Convert . ToInt32 ( Math . Min ( MaxCacheSize , int . MaxValue ) ) ) ;
396- while ( cache . Count >= maxCacheSize )
397- {
398- cache . RemoveAt ( cache . Count - 1 ) ;
399- }
400-
401- cache . Insert ( 0 , document ) ;
402- return document ;
403- }
386+ return CacheDocument ( new StringDocument ( documentInfo , contents ) , false ) ;
404387 }
405388
406389 #region DocumentLoader overrides
@@ -481,14 +464,71 @@ public override async Task<Document> LoadDocumentAsync(DocumentSettings settings
481464 throw new AggregateException ( exceptions ) . Flatten ( ) ;
482465 }
483466
467+ public override Document GetCachedDocument ( Uri uri )
468+ {
469+ lock ( cache )
470+ {
471+ for ( var index = 0 ; index < cache . Count ; index ++ )
472+ {
473+ var cachedDocument = cache [ index ] ;
474+ if ( cachedDocument . Info . Uri == uri )
475+ {
476+ cache . RemoveAt ( index ) ;
477+ cache . Insert ( 0 , cachedDocument ) ;
478+ return cachedDocument ;
479+ }
480+ }
481+
482+ return null ;
483+ }
484+ }
485+
486+ public override Document CacheDocument ( Document document , bool replace )
487+ {
488+ MiscHelpers . VerifyNonNullArgument ( document , nameof ( document ) ) ;
489+ if ( ! document . Info . Uri . IsAbsoluteUri )
490+ {
491+ throw new ArgumentException ( "The document must have an absolute URI" ) ;
492+ }
493+
494+ lock ( cache )
495+ {
496+ for ( var index = 0 ; index < cache . Count ; )
497+ {
498+ var cachedDocument = cache [ index ] ;
499+ if ( cachedDocument . Info . Uri != document . Info . Uri )
500+ {
501+ index ++ ;
502+ }
503+ else
504+ {
505+ if ( ! replace )
506+ {
507+ Debug . Assert ( cachedDocument . Contents . ReadToEnd ( ) . SequenceEqual ( document . Contents . ReadToEnd ( ) ) ) ;
508+ return cachedDocument ;
509+ }
510+
511+ cache . RemoveAt ( index ) ;
512+ }
513+ }
514+
515+ var maxCacheSize = Math . Max ( 16 , Convert . ToInt32 ( Math . Min ( MaxCacheSize , int . MaxValue ) ) ) ;
516+ while ( cache . Count >= maxCacheSize )
517+ {
518+ cache . RemoveAt ( cache . Count - 1 ) ;
519+ }
520+
521+ cache . Insert ( 0 , document ) ;
522+ return document ;
523+ }
524+ }
525+
484526 public override void DiscardCachedDocuments ( )
485527 {
486528 lock ( cache )
487529 {
488530 cache . Clear ( ) ;
489531 }
490-
491- base . DiscardCachedDocuments ( ) ;
492532 }
493533
494534 #endregion
0 commit comments