<commit_before>﻿using System;
using System.Collections.Generic;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text;

namespace AgateLib.Storage
{
    /// <summary>
    /// Interface that provides storage on a per-user basis.
    /// </summary>
    public interface IUserStorage
    {
        bool FileExists(string path);
        Stream OpenFile(string path, FileMode fileMode);
        Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess);
        Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare);
    }

    /// <summary>
    /// Class that provides storage on a per-user basis.
    /// </summary>
    [Singleton]
    public class UserStorage : IUserStorage
    {
        private IsolatedStorageFile iso;

        public UserStorage()
        {
#if WINDOWS_UWP
            iso = IsolatedStorageFile.GetUserStoreForApplication();
#else
            iso = IsolatedStorageFile.GetUserStoreForDomain();
#endif
        }

        public bool FileExists(string path)
        {
            return iso.FileExists(path);
        }

        public Stream OpenFile(string path, FileMode fileMode)
        {
            CreateDirectoryIfApplicable(path, fileMode);

            return iso.OpenFile(path, fileMode);
        }
        
        public Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess)
        {
            CreateDirectoryIfApplicable(path, fileMode);

            return iso.OpenFile(path, fileMode, fileAccess);
        }

        public Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare)
        {
            CreateDirectoryIfApplicable(path, fileMode);

            return iso.OpenFile(path, fileMode, fileAccess, fileShare);
        }

        private void CreateDirectoryIfApplicable(string path, FileMode fileMode)
        {
            if (fileMode == FileMode.Create ||
                            fileMode == FileMode.CreateNew ||
                            fileMode == FileMode.OpenOrCreate)
            {
                iso.CreateDirectory(Path.GetDirectoryName(path));
            }
        }
    }
}<commit_msg>Move away from using isolated storage for desktops, because it changes for different versions.<commit_after>﻿using System;
using System.IO;
using System.IO.IsolatedStorage;

namespace AgateLib.Storage
{
    /// <summary>
    /// Interface that provides storage on a per-user basis.
    /// </summary>
    public interface IUserStorage
    {
        /// <summary>
        /// For desktop platforms, sets the folder inside the root app data folder for the storage
        /// for this user.
        /// </summary>
        /// <param name="folderName">Name of the folder. Recommended is to use
        /// company_name/product_name, eg. "VermilionTower/ThornbridgeSaga"</param>
        /// <returns></returns>
        void SetApplicationDataFolder(string folderName);

        bool FileExists(string path);
        Stream OpenFile(string path, FileMode fileMode);
        Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess);
        Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare);
    }

    /// <summary>
    /// Class that provides storage on a per-user basis.
    /// </summary>
    [Singleton]
    public class UserStorage : IUserStorage
    {
#if DESKTOP
        private bool appDataFolderSet, noRootWarning;

        private string appDataFolder;
        private string rootFolder;

        public UserStorage()
        {
            appDataFolder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
            rootFolder = Path.Combine(appDataFolder, "UnknownApplication");
        }

        public void SetApplicationDataFolder(string folderName)
        {
            if (string.IsNullOrWhiteSpace(folderName))
                throw new ArgumentException(nameof(folderName));

            rootFolder = Path.Combine(appDataFolder, folderName);

            appDataFolderSet = true;
            noRootWarning = false;

            Log.Info($"User storage set to {rootFolder}.");
        }

        public bool FileExists(string path)
        {
            WarnIfNoRoot();

            return File.Exists(Path.Combine(rootFolder, path));
        }

        public Stream OpenFile(string path, FileMode fileMode)
        {
            WarnIfNoRoot();

            CreateDirectoryIfApplicable(path, fileMode);

            return File.Open(path, fileMode);
        }

        public Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess)
        {
            WarnIfNoRoot();

            CreateDirectoryIfApplicable(path, fileMode);

            return File.Open(path, fileMode, fileAccess);
        }

        public Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare)
        {
            WarnIfNoRoot();

            CreateDirectoryIfApplicable(path, fileMode);

            return File.Open(path, fileMode, fileAccess, fileShare);
        }

        private void CreateDirectoryIfApplicable(string path, FileMode fileMode)
        {
            if (fileMode == FileMode.Create ||
                fileMode == FileMode.CreateNew ||
                fileMode == FileMode.OpenOrCreate)
            {
                Directory.CreateDirectory(Path.GetDirectoryName(path));
            }
        }

        private void WarnIfNoRoot()
        {
            if (appDataFolderSet)
                return;

            if (noRootWarning)
                return;

            Log.Warn($"No root folder set. User data is stored in {rootFolder}");
            noRootWarning = true;
        }
#endif

        #region --- UWP ---
#if WINDOWS_UWP || ANDROID
        private IsolatedStorageFile iso;

        public UserStorage()
        {
            iso = IsolatedStorageFile.GetUserStoreForApplication();
            
            // If the above line doesn't work, this one might suffice.
            // iso = IsolatedStorageFile.GetUserStoreForDomain();
        }

        public void SetApplicationDataFolder(string folderName)
        {
            // no-op, since we're using isolated storage.
        }

        public bool FileExists(string path)
        {
            return iso.FileExists(path);
        }

        public Stream OpenFile(string path, FileMode fileMode)
        {
            CreateDirectoryIfApplicable(path, fileMode);

            return iso.OpenFile(path, fileMode);
        }
        
        public Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess)
        {
            CreateDirectoryIfApplicable(path, fileMode);

            return iso.OpenFile(path, fileMode, fileAccess);
        }

        public Stream OpenFile(string path, FileMode fileMode, FileAccess fileAccess, FileShare fileShare)
        {
            CreateDirectoryIfApplicable(path, fileMode);

            return iso.OpenFile(path, fileMode, fileAccess, fileShare);
        }

        private void CreateDirectoryIfApplicable(string path, FileMode fileMode)
        {
            if (fileMode == FileMode.Create ||
                            fileMode == FileMode.CreateNew ||
                            fileMode == FileMode.OpenOrCreate)
            {
                iso.CreateDirectory(Path.GetDirectoryName(path));
            }
        }
#endif

        #endregion
    }
}
{'fraction_non_alphanumeric': 0.08264686022957461, 'fraction_numerical': 0.0, 'mean_word_length': 2.0203915171288744, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4987471', 'n_tokens_mistral': 1927, 'n_tokens_neox': 1844, 'n_words': 475}