001package squidpony;
002
003import squidpony.store.json.JsonStorage;
004
005/**
006 * Helps games store information in libGDX's Preferences class as Strings, then get it back out.
007 * Created by Tommy Ettinger on 9/16/2016.
008 */
009public class SquidStorage extends JsonStorage {
010    /**
011     * Please don't use this constructor if possible; it simply calls {@link #SquidStorage(String)} with the constant
012     * String "nameless". This could easily overlap with other files/sections in Preferences, so you should always
013     * prefer giving a String argument to the constructor, typically the name of the game.
014     * @see #SquidStorage(String) the recommended constructor to use
015     */
016    public SquidStorage()
017    {
018        super("nameless");
019    }
020
021    /**
022     * Creates a SquidStorage with the given fileName to save using Preferences from libGDX. The name should generally
023     * be the name of this game or application, and must be a valid name for a file (so no slashes, backslashes, colons,
024     * semicolons, or commas for certain, and other non-alphanumeric characters are also probably invalid). You should
025     * not assume anything is present in the Preferences storage unless you have put it there, and this applies doubly
026     * to games or applications other than your own; you should avoid values for fileName that might overlap with
027     * another game's Preferences values.
028     * <br>
029     * To organize saved data into sub-sections, you specify logical units (like different players' saved games) with a
030     * String outerName when you call {@link #store(String)}, and can further distinguish data under the outerName when
031     * you call {@link #put(String, Object)} to put each individual item into the saved storage with its own innerName.
032     * <br>
033     * Calling this also sets up custom serializers for several important types in SquidLib; char[][], OrderedMap,
034     * IntDoubleOrderedMap, FakeLanguageGen, GreasedRegion, and notably Pattern from RegExodus all have smaller
035     * serialized representations than the default. OrderedMap allows non-String keys, which gets around a limitation in
036     * JSON maps normally, and both FakeLanguageGen and Pattern are amazingly smaller with the custom representation.
037     * The custom char[][] representation is about half the normal size by omitting commas after each char.
038     * @param fileName the valid file name to create or open from Preferences; typically the name of the game/app.
039     */
040    public SquidStorage(final String fileName)
041    {
042        super(fileName);
043    }
044    /**
045     * Creates a SquidStorage with the given fileName to save using Preferences from libGDX. The name should generally
046     * be the name of this game or application, and must be a valid name for a file (so no slashes, backslashes, colons,
047     * semicolons, or commas for certain, and other non-alphanumeric characters are also probably invalid). You should
048     * not assume anything is present in the Preferences storage unless you have put it there, and this applies doubly
049     * to games or applications other than your own; you should avoid values for fileName that might overlap with
050     * another game's Preferences values. This constructor also allows you to specify a "garble" String; if this is
051     * non-null, it will be used as a key to obfuscate the output and de-obfuscate the loaded input using fairly basic
052     * methods. If garble is null, it is ignored.
053     * <br>
054     * To organize saved data into sub-sections, you specify logical units (like different players' saved games) with a
055     * String outerName when you call {@link #store(String)}, and can further distinguish data under the outerName when
056     * you call {@link #put(String, Object)} to put each individual item into the saved storage with its own innerName.
057     * <br>
058     * Calling this also sets up custom serializers for several important types in SquidLib; char[][], OrderedMap,
059     * IntDoubleOrderedMap, FakeLanguageGen, GreasedRegion, and notably Pattern from RegExodus all have smaller
060     * serialized representations than the default. OrderedMap allows non-String keys, which gets around a limitation in
061     * JSON maps normally, and both FakeLanguageGen and Pattern are amazingly smaller with the custom representation.
062     * The custom char[][] representation is about half the normal size by omitting commas after each char.
063     * @param fileName the valid file name to create or open from Preferences; typically the name of the game/app.
064     * @param garble a String that will be used as a key to obfuscate the saved output if non-null
065     */
066    public SquidStorage(final String fileName, final String garble)
067    {
068        super(fileName, garble);
069    }
070    /**
071     * Creates a SquidStorage with the given fileName to save using Preferences from libGDX. The name should generally
072     * be the name of this game or application, and must be a valid name for a file (so no slashes, backslashes, colons,
073     * semicolons, or commas for certain, and other non-alphanumeric characters are also probably invalid). You should
074     * not assume anything is present in the Preferences storage unless you have put it there, and this applies doubly
075     * to games or applications other than your own; you should avoid values for fileName that might overlap with
076     * another game's Preferences values. This constructor also allows you to specify a "garble" long array; if this is
077     * non-empty, it will be used as a key to obfuscate the output and de-obfuscate the loaded input using fairly basic
078     * methods. If garble is null or empty, it is ignored.
079     * <br>
080     * To organize saved data into sub-sections, you specify logical units (like different players' saved games) with a
081     * String outerName when you call {@link #store(String)}, and can further distinguish data under the outerName when
082     * you call {@link #put(String, Object)} to put each individual item into the saved storage with its own innerName.
083     * <br>
084     * Calling this also sets up custom serializers for several important types in SquidLib; char[][], OrderedMap,
085     * IntDoubleOrderedMap, FakeLanguageGen, GreasedRegion, and notably Pattern from RegExodus all have smaller
086     * serialized representations than the default. OrderedMap allows non-String keys, which gets around a limitation in
087     * JSON maps normally, and both FakeLanguageGen and Pattern are amazingly smaller with the custom representation.
088     * The custom char[][] representation is about half the normal size by omitting commas after each char.
089     * @param fileName the valid file name to create or open from Preferences; typically the name of the game/app.
090     * @param garble a long array that will be used as a key to obfuscate the saved output if non-null
091     */
092    public SquidStorage(final String fileName, final long[] garble)
093    {
094        super(fileName, garble);
095    }
096    /**
097     * Prepares to store the Object {@code o} to be retrieved with {@code innerName} in the current group of objects.
098     * Does not write to a permanent location until {@link #store(String)} is called. The innerName used to store an
099     * object is required to get it back again, and can also be used to remove it before storing (or storing again).
100     * @param innerName one of the two Strings needed to retrieve this later
101     * @param o the Object to prepare to store
102     * @return this for chaining
103     */
104    public SquidStorage put(String innerName, Object o)
105    {
106        super.put(innerName, o);
107        return this;
108    }
109
110    /**
111     * Actually stores all objects that had previously been prepared with {@link #put(String, Object)}, with
112     * {@code outerName} used as a key to retrieve any object in the current group. Flushes the preferences, making the
113     * changes permanent (until overwritten), but does not change the current group (you may want to call this method
114     * again with additional items in the current group, and that would simply involve calling put() again). If you want
115     * to clear the current group, use {@link #clear()}. If you want to remove just one object from the current group,
116     * use {@link #remove(String)}.
117     * @param outerName one of the two Strings needed to retrieve any of the objects in the current group
118     * @return this for chaining
119     */
120    public SquidStorage store(String outerName)
121    {
122        super.store(outerName);
123        return this;
124    }
125
126    /**
127     * Gets a String representation of the data that would be saved when {@link #store(String)} is called. This can be
128     * useful for finding particularly problematic objects that require unnecessary space when serialized.
129     * @return a String that previews what would be stored permanently when {@link #store(String)} is called
130     */
131    public String show()
132    {
133        return super.show();
134    }
135
136    /**
137     * Clears the current group of objects; recommended if you intend to store under multiple outerName keys.
138     * @return this for chaining
139     */
140    public SquidStorage clear()
141    {
142        super.clear();
143        return this;
144    }
145
146    /**
147     * Removes one object from the current group by the {@code innerName} it was prepared with using
148     * {@link #put(String, Object)}. This does not affect already-stored objects unless {@link #store(String)} is called
149     * after this, in which case the new version of the current group, without the object this removed, is stored.
150     * @param innerName the String key used to put an object in the current group with {@link #put(String, Object)}
151     * @return this for chaining
152     */
153    public SquidStorage remove(String innerName)
154    {
155        super.remove(innerName);
156        return this;
157    }
158
159    /**
160     * Gets an object from the storage by the given {@code outerName} key from {@link #store(String)} and
161     * {@code innerName} key from {@link #put(String, Object)}, and uses the class given by {@code type} for the
162     * returned value, assuming it matches the object that was originally put with those keys. If no such object is
163     * present, returns null. Results are undefined if {@code type} doesn't match the actual class of the stored object.
164     * @param outerName the key used to store the group of objects with {@link #store(String)}
165     * @param innerName the key used to store the specific object with {@link #put(String, Object)}
166     * @param type the class of the value; for a class like RNG, use {@code RNG.class}, but changed to fit
167     * @param <T> the type of the value to retrieve; if type was {@code RNG.class}, this would be {@code RNG}
168     * @return the retrieved value if successful, or null otherwise
169     */
170    public <T> T get(String outerName, String innerName, Class<T> type)
171    {
172        return super.get(outerName, innerName, type);
173    }
174
175    /**
176     * Gets the approximate size of the currently-stored preferences. This assumes UTF-16 storage, which is the case for
177     * GWT's LocalStorage. Since GWT is restricted to the size the browser permits for LocalStorage, and this limit can
178     * be rather small (about 5 MB, sometimes more but not reliably), this method is especially useful there, but it may
179     * yield inaccurate sizes on other platforms that save Preferences data differently.
180     * @return the size, in bytes, of the already-stored preferences
181     */
182    public int preferencesSize()
183    {
184        return super.preferencesSize();
185    }
186
187}