diff --git a/.factorypath b/.factorypath new file mode 100644 index 0000000..318adcd --- /dev/null +++ b/.factorypath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 2d56834..0000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. -Provide code examples if possible, names of affected classes, etc... - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Goals and expected behavior** -A clear and concise description of what you expected to happen. What are your goals? - -**Additional context** -Add any other context about the problem here. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1c5818 --- /dev/null +++ b/.gitignore @@ -0,0 +1,46 @@ +# Specifies intentionally untracked files to ignore when using Git +# http://git-scm.com/docs/gitignore + +*~ +*.sw[mnpcod] +.tmp +*.tmp +*.tmp.* +*.sublime-project +*.sublime-workspace +.DS_Store +Thumbs.db +UserInterfaceState.xcuserstate +$RECYCLE.BIN/ + +*.log +*_bench.juss +jfr_out/ +.jfr +log.txt +npm-debug.log* + +/.idea +/.ionic +/.sass-cache +/.sourcemaps +/.versions +/.vscode +/coverage +/dist +/node_modules +/platforms +/plugins +/www + +bin/ +tmp/ +.metadata +.classpath +.settings +.project +.factorypath + +target/ + +src/kop/ \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md deleted file mode 100644 index 1ea9608..0000000 --- a/CONTRIBUTING.md +++ /dev/null @@ -1,42 +0,0 @@ -# Contributing to SerialX - -First off, thank you for considering contributing to this project. It's people like you that make this project even better! - -## How Can I Contribute? - -### Reporting Bugs - -- **Ensure the bug was not already reported** by searching through [Issues section](https://github.com/PetoPetko/Java-SerialX/issues). -- If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/PetoPetko/Java-SerialX/issues/new). - - Make sure that the issue contains decent description and if possible some additional data as well, such as code examples. This can help to better understand the issue or ease the reproduction process. - -### Your First Code Contribution - -- Fork the repo. -- Windows only: Download [Git bash x64](https://git-scm.com/download/) if you do not have it already. -- Open bash/git bash then run the following command and write in your GitHub account name (SimplyProgrammer in my case). This command should properly clone your forked SerialX repo: -``` -read -p "Enter your GitHub account name: " name && mkdir -p SerialX && cd "$_" && -git clone --single-branch --branch dev "https://github.com/$name/Java-SerialX.git" SerialXDev && -git clone --single-branch --branch tests-and-experimental-features "https://github.com/$name/Java-SerialX.git" SerialXTest -``` -- Import both SerialXDev and SerialXTest together with all of their modules into your editor of choice, I recommend Eclipse. -- Make some changes (add something feature, fix some bugs, improve Javadocs...) -- Go to SerialXTest and run `examples.implementations.GeneralExample`, `examples.implementations.SimpleQuerying` and `examples.implementations.SerializingWithJson` junit tests. Acknowledge that only changes that meet all the tests can be added to the library! -- If all the tests are green you can `git add .` -- Commit your changes (`git commit -am 'describe what you have done (adding/fixing/improving/... something)'`). -- Push to the branch (`git push`). -- When you are done, open a new Pull Request. - -## Styleguides and code requirements -- Follow general Java conventions. -- Introduce as few boundaries as possible, try making things as universal as possible (do not use final or private if possible). -- Try for your code to not stick out stylistically ;) -- Every added feature must have an outreaching purpose, must be tested, and perform reasonably. - - Make sure to NOT alter any of the tests unless your use case explicitly requires it, in that case, make sure to document it! -- Every added class and method must be documented (/** doc */) and contain @author and @version. Method does not need to have @author, especially @author of the class is the same. -- Note: Version does not have to be incremented in any way, adding _SNAPSHOT at the end should be sufficient. - -## Additional - -Thank you for contributing to SerialX! diff --git a/Changelog.md b/Changelog.md deleted file mode 100644 index 3a7b3ba..0000000 --- a/Changelog.md +++ /dev/null @@ -1,296 +0,0 @@ -# SerialX 1.0.0 (beta) - -Release date: 8.14.2020 (Evening) - -What was added: -* Serializer utility class. -* 2 build-in protocols. -# - -# SerialX 1.0.5 (beta) - -Release date: 8.20.2020 (Night) - -What was added: -* Ability to generate comments. -* Fixing some small bugs. -# - -# SerialX 1.0.6 - -Release date: 8.22.2020 (Noon) - -What was added: -* Improveing way to serialize numbers. -* Adding suffixes fot double "d", short "s" and byte "y"! -* Java Base64 serialized object now does not need to start with "#"! -* Objects serialized using protocol with no arguments will now not by serialized with null argument! -* Repairing an error with long suffix! -# - -# SerialX 1.1.0 - -Release date: 9.22.2020 (Afternoon) - -What was added: -* Adding decimal number formatter! -* "unserialize" method in SerializationProtocol now throws Exception which makes reflection stuff easier! -* Fixing some problems such as "Too big objects simply disappear during serialization!" -* Better optimization. Improving the performance of Serializing and Unserializing astronomically! -* Some characters now can be serialized using regular Java way for example 'a'! However SerialX syntax characters such as { or } must be still serialized using ASCII code! -Numbers must have additional character behind for example '4/' otherwise they will be taken as ASCII code! -* Some new methods and stuff! -# - -# SerialX 1.1.2 - -Release date: 9.27.2020 (Evening) - -What was added: -* Integers now can be serialized using Java binary and hexadecimal form (0b1111, 0xffff)! -* Numbers can be separated with underscore (just like in Java)! -* Fixing the bug when formatter mess up decimals suffixes and integers! -# - -# SerialX 1.1.5 - -Release date: 12.6.2020 (Evening) - -What was added: -* Variable system! Now "order" is not only possibility. -* Functions working with variable system! -* Functions that allows you to insert custom code (comments and stuff)! -* Fixing "long-lived" bugs such as the on with double slash comment, hopefuly for the last! -# - -# SerialX 1.2.0_pre - V2 - -Release date: 3.18.2021 (Afternoon) - -What was added: -* New Scope object that are now values and variables loaded in to so now its not necesarry to load indepednent values and variables separatly! -* Scope is the physical manifestation of loaded content in your program! -* Ability to create sub-scopes / neasted scopes in side of parent scopes or file itself similarly to JSON! For example: { \/\*scope\*\/ } -* Ability to serialize string normaly in quotes like in java! But certain syntactical characters from SerialX cant be present! -* "splitValues" method was removed becasue it was out of purpous of library itself. -* Comma now works as semicolon! -* Tremendous reading performence boost! Large quantity reading is now up to 50x faster than in previous version. -* Fixing a bug when order of elements being messed up during serialization. -* Fixing a bug with hexadecimal and binary number formats. -* Fixing some other less important bugs. -* Note: Since this is pre release, there are probably some bugs but hopefully nothing totaly broken. Also this prerelease can only read scopes, not write! -# - -# SerialX 1.2.2 - -Release date: 4.11.2021 (Afternoon) - -What was added: -* Ability to serialize Scope object! -* Ability to clone Objects using Serializer! -* Ability to instantiate any object using Serializer by calling shortest public constructor! -* Now you can access Java utility from SerialX, you can invoke public static methods and fields directly from SerialX! -* SelfSerializable interface which gives you ability to serialize objects without protocol by calling public constructors! -* Static field "new" to obtain clone of variable and "class" to obtain class of variables value! -* 4 new protocols: - * MapProtocol - to serialize maps! - * ScopeProtocol (reading only) to read scopes using protocol! - * AutoProtocol - will automatically serialize selected fields with getters and setters! - * EnumProtocol - to serialize any java enum! - * SelfSerializableProtocol - operates with SelfSerializable interface! -* Tremendous writing performance boost! Large quantity writing is now up to 80x faster than in previous version. -* Eliminating usage of Regex completely which results into even faster reading! -* Now you can access variables of scopes by "." directly in SerialX! -* Fixing bug when blank characters despair from string, also now string can contains any character except quote and nextline! -* SerialX API is now partially opensource, the sources are included in main Jar, however according to the License you cant appropriate any of this code without including its origins! -# - -# SerialX 1.2.5 - -Release date: 4.11.2021 (Afternoon) - -What was added: -* Serializer can now serialize into any Appendable which includes all Writers, StringBuilder and many others which gives you a lot of opportunities! -* Serializer can now read from any CharSequence or any Reader object! -* Serializer is now fully capable of reading JSON! -* Serializer can read specific object or variable while ignoring any other stuff which saves a lot of performance (this is experimental)! -* Slight increase of reading performance! -* Utility to work with JSON like JsonScope! -* A lot of new utility in Scope object such as filtering or object transformation! -* Small bugs fixed! -# - -# SerialX 1.3.0 - -Release date: 8.8.2021 (Night) - -What was added: -* Revelation of compiler that is now Recursive descent parser that is customizable and configurable. -* Structure of entire API was generally reorganized in to 3 main sections: - * Serializer - which is main class that operates entire API. Is responsible for input and output, formatting and general utility! - * DataParser and DataConverter API - is recursive descent parser itself that is responsible for converting objects to strings and parsing them back! In default SerialX API implementation now known as JUSS (Java universal serial script) are these parsers and converters available: - * NumberConverter - for converting and parsing numbers (integers, decimals, hexa, bin)! - * BooleanConverter - for converting and parsing booleans! - * CharacterConverter - for converting and parsing chars! - * StringConverter - for converting and parsing strings ("Hello world!", "And others...")! - * NullConverter - for converting and parsing null! - * ObjectConverter - for converting and parsing SerializationProtocol expressions and Scopes! - * VariableConverter - for converting and parsing JUSS variables (Map.Entry)! - * SerializableBase64Converter - for converting and parsing Base64 expressions (java.io.Serializable)! - * ArrayConverter - for converting and parsing primitive arrays! - ## - * OperationGroups - for parsing expression groups such as (5 + 5) / 2 - * ArithmeticOperators - for parsing arithmetic expression such as 2 + 5 * 4 ** 2 - * LogicalOperators - for parsing logical expression such as true && false || true - * ComparisonOperators - for comparing objects, for instance 6 > 5 - * ConditionalAssignmentOperators - that provides ternary operator (?:) and null coalescing (??) - * NegationOperator - to negate stuff, for example !true - ## - * As mentioned. you can create your own parsers or even replace already existing ones with yours! - * SerializationProtocol API - long known protocol system for more complex objects. It contains 8 protocols as before! Now protocols are operated by ObjectConverter! -* New import system that allows you to import some class once with certain alias and then use it with that alias, similar to java! -* Too big integers are now automatically converted into long without necessarily of using L suffix! -* Small new syntax features and alot of small enhancements (shortened version of variable being initialized to scope)! -* Alot of string utility methods from Serializer become public and some were moved into converters where they are mainly used! -* Registry object which is Collection type that can store only one instance per class! -* Some new functions in Scope! -* Deprecated methods were removed! -* Source code was excluded from main jar to save space and is now available in separate src.zip file! Now on java doc files will not be provided and src.zip should be used instead! -* Small bugs fixed but there were alot of internal changes in this update so they might be another bugs so I encourage you to report any bug you encounter! -# - -# SerialX 1.3.2 - -Release date: 10.25.2021 (Morning) - -What was added: -* Serializer now abstract class which inherits Scope so now it is Scope that can serialize itself! Serialization and deserialization methods are now not static and original functionality has been split into two separated objects that inherit Serializer: - * JussSerializer - which is responsible for serializing and deserializing objects using Juss format (original functionality of Serializer). - * JsonSerializer - which is responsible for serializing and deserializing objects using Json format (successors of JsonSelxUtils) -* JsonSelxUtils was replaced with JsonSerializer that is capable of both reading and writing Json! -* Main formatting and reading algorithms can be now overridden by extending JsonSerializer, JussSerializer or Serializer! -* Ability to set multiple variables on one value, for example x = y = z = 5 -* Ability to remove multiple variables by setting them on null! -* Variables of scope are now settable from outer world, for example someScope.x = 9 -* Compare identity operator (triple equals) was added and transtype comparison logic was changed, mainly between primitive datatypes! -* Logical operators now have higher precedence over comparison operators by default! -* Logic behind operators can now be overridden by extending belonging operator DataParser! -* Adding some new utility and functionalities! -* Small syntax features (scopes now don't have to be separated with semicolon if they are in new line)! -* Package name was renamed from "ugp.org.SerialX" to "org.ugp.serialx"! -* Fixing some bugs with formatting and reading! -# - -# SerialX 1.3.5 - -Release date: 8.30.2022 (Night) - -What was added: -* Scope was split into 2 separate classes: - * GenericScope - that allows you to set generic types of keys and values. Furthermore, it can be serialized with generic types preserved! - * Scope - that you already know which poses the same functionality as before now as a child class of GenericScope! -* Imports system was redesigned and splitted into multiple separate classes, each handling some part of functionality! - * Also imports are now Serializer specific rather than global! -* Precedence of ConditionalAssignmentOperators ?: and ?? was slightly altered to closely resemble behavior of these operators in other languages. Also, these operators now can be nested without necessity of (). -* Parser API (DataParser and DataConverter) was redesigned and is now handled by ParserRegistry which can provide additional functionality such as caching to improve performance! -* Serialization syntax of Serializable objects using Base64 via SerializableBase64Converter was slightly altered to mitigate conflicts with the rest of JUSS syntax! -* New "from/into API" which is now part of the Scope that allows you to map almost any java object into a scope and any scope into corresponding java object! -* AutoProtocol is now based on "from/into API" making it more flexible! -* New UniversalObjectInstantiationProtocol that can deserialize any object by calling its constructor (something similar to ObjectClass::new)! -* SerializationProtocols now have a "mode" that can define what they can do! -* JsonSerializer will now serialize JUSS protocols as JSON objects to achieve more JSON compatibility out of the box! -* LogProvider which is now responsible for logging errors and allows you to implement your own form of logging! -* SerializationDebugger that provides ability to debug serialization and deserialization! -* New utility across API and small new functionalities and changes! -* Fixing bugs (hopefully not adding new ones): - * Long live bug with // and /* comments in strings now fixed for good (I hope...) - * Bug with wrong formatting when serializing Json in Juss and revers! - * Some other small ones! -* New examples were added! -# - -# SerialX 1.3.8 - -Release date: 9.22.2024 (Night) - -What was added:
-### Maven: -* The whole library was modularized using Maven into the following modules: - * SerialX-core - Contains core features and utilities shared across the library. It also contains basic protocols and parsers that resemble the functionalities of pre-1.2.X SerialX. - * SerialX-juss - Now contains everything JUSS related, features that were added roughly in 1.2 and later... This includes things like JussSerializer, ArrayConverter, OperationGroups etc... - * SerialX-json - A relatively small extension of the JUSS module that is more narrowly focused on JSON. This is now where SerialX support for JSON is located. - * SerialX-operators - An extensional module, this is now where all operator parsers are located. - * SerialX-devtools - Small module containing tools for debugging the library, mainly Parser/Converter API. It is intended for DSL developers and people who want to add their own data formats. -* From now on Maven will be used for dependency management and building of this library. -* Distribution of this library will be conducted using Maven from now on. - * This greatly simplifies a lot of lengthy, complex IDE-specific processes. - -### Unit tests and benchmarks: -* Some examples are now used as unit tests, this should greatly simplify the testing process and reduce the chance of bug introduction in the future. -* These are now located on the new "tests-and-experimental-features" branch. This branch will be used for demonstrations, benchmarking, testing and experimenting. Note that this branch is not part of the main API. - -  - -### Specific changes: -* Library is now compatible with JDK versions up to 21 (probably even newer but it was not tested)! -* ImportsProvider now implements caching for Imports. -* ParserRegistry now implements DataParser allowing for easier creation of more complex (context-free) languages. -* NumberConverter was refactored, now providing all in one parsing numberOf function that is on average 12x faster than the old implementation. - * New numberOf function supports octadecimal numbers and has improved handling of E-notation. - * Java integer caching is now in place. - * DecimalFormater was dumped in favor of the more customizable overridable format method. -* BooleanConverter and NullConverter were slightly refactored allowing for near O(1) complexity of parsing. -* ObjectConverter got a significant refactor! - * It was separated into 2 separate classes across 2 modules. Now it is ProtocolConverter that is extended by ObjectConverter. - * Static member invocation is now only allowed on a small carefully selected group of classes, fixing the major security (arbitrary code execution) exploit that would allow an attacker to call any static function of any class in a hypothetical REST implementation scenario. Note that this is only a mitigation that allows you to whitelist the specific classes for static member invocation so the maximal caution is still advised when doing so. - * Both ObjectConverter and ProtocolConverter were slightly optimized. -* StringConverter was slightly optimized by introducing caching. It is disabled by default, by enabling it the same String instance will be returned for the same strings during parsing. - * Static variables were made instance-specific allowing for more flexibility. -* GenericScope and Scope received various API improvements, the most notable ones being: - * GenericScope now implements Collection instead of just Iterable making it part of Java collection API. - * From/Into API now partially supports recognition for generic types of declared Object variables, making it more useful for non-JUSS formats such as JSON. This enhances also AutoProtocol and UniversalObjectInstantiationProtocol together with SelfSerializableProtocol. -* Mode of SerializationProtocol is now implemented with 64 int (long) bit-packing which allows for chaining of multiple modes which can now be understood as protocol types. This trades an overall number of unique modes for greater utility. -* Serializer (and core high-level changes): - * The concept of scope parent variable inheritance was abandoned due to being unacceptable and inefficient (both time and space-wise...), quite error-prone and tedious to work with as well as and potentially dangerous. Not mentioning the fact that the only reason for its existence was to allow you to access variables declared in the parent scope, for which it suboptimal solution to say at least... - * In a similar fashion, the notion of each parser having to return the new instance of the respective object for every parsed string was abandoned as well and is no longer required, allowing for more flexibility and concepts such as already mentioned caching! - * OOP NULL was abandoned as well as it was a biproduct of sub-optimal decisions mentioned above and therefore conceptually flawed. It is deprecated and should not be used! -* All static utility functions (for instance string analyses and processing functions) were separated into new Utils class, in order to achieve better separation of concerns... - * All string analyses and processing utility functions (for example indexOfNotInObj or splitValues) were rewritten into more "finite state machine"-like form which slightly increases their performance... - * Some new utility functions were added and existing ones were improved! - -  -* Operation group mark of OperationGroups (parentheses operator) is no longer static and always the same, now it is shorter and pseudo-randomly generated which slightly increases the performance and highly mitigates the hypothetical "Group mark injection" attack which would result in unauthorized access to group mark at runtime. -* UniversalObjectInstantiationProtocol is no longer registered by default and now requires manual registration for a specific class, this enhances security since instantiation of any object (dangerous or not) is prevented. - * The same goes for SelfSerializableProtocol. - -  -* JsonSerializer received many improvements and bug fixes in order to match JSON more accurately. - * Dedicated JsonCharacterConverter and JsonNumberConverter were added for this. Also, JsonObjectConverter was separated into its own class. - -  -* Operators class was added, which is used for injecting all operator parsers into the specific registry. -* Almost every operator parser was refactored, resulting in shorter, far simpler and therefore more optimized code. The most notable ones are: - * ArithmeticOperators which now also allows you to declare your own arithmetic operators and/or specify their precedence. - * Due to refactoring, ResultWrapper is no longer needed and will be removed, this extends to LogicalOperators as well. -* NegationOperator now supports separate handling of logical negation (! operator) and mathematical negation (- operator), however by default their behavior is the same. - -  -* The ability to specify custom output PrintWriter was added for SerializationDebugger. - -  -* Besides the changes mentioned above, countless smaller improvements including numerous bug fixes, performance improvements, API enhancements or Javadoc specifications were added across the whole library. - * Some functions were slightly renamed but it is usually documented but deprecated functions were removed! -# - -# SerialX 1.3.9+ - -Release date: UNKNOWN - -### Roadmap of potential changes: -* Separating From/Into API from Scope and Serializer into the standalone classes making it more flexible and customizable. -* ? Implementing Register in such a way that it will be possible to specify the underlying data structure. -* Optimizing deserialization process in JussSerializer (unification of "those 2 methods" and getting rid of that stinky legacy spaghetti code they have). -* ? Optimizations - Introducing char/class-based direct dispatch hashing algorithm for selecting the best fitting data converter for the string/object. (This is likely not going to be possible to fully implement due to internal dependencies between parsers and other legacy reasons...) -* Update CLRFs to be compatible with multiple systems. -* ? Formating options - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index a10452e..0000000 --- a/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Based on MIT License - -Copyright (c) USP 2019-2024 | Peto - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated files, to deal -in the Software without restriction, including without limitation the rights -to use, copy or modify copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -Permission to re-publish, re-distribute, sublicense or sell any code contained in this repository (for example as a direct part of your game or application) under your own trademark is PROHIBITED unless the following conditions are met: -- Indication/pointing to the original source (https://github.com/PetoPetko/Java-SerialX/). -The above does not apply if, and only if your project (game/application/etc.) is depended on the "jar file" form of this library. -Any other situation MUST follow the conditions stated above! - -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. diff --git a/README.md b/README.md index 2459869..69624bc 100644 --- a/README.md +++ b/README.md @@ -1,155 +1 @@ -# Java-SerialX -## Quick links -* If you want to download/import the library, add this to your pom.xml. Or take a look at [Packages](https://github.com/SimplyProgrammer?tab=packages&repo_name=Java-SerialX). -``` - - - org.ugp.serialx - serialx-json - 1.3.8 - - - - - - github - https://maven.pkg.github.com/SimplyProgrammer/Java-SerialX - - -``` - -* If you want to add or see issues just click on [Issues section](https://github.com/PetoPetko/Java-SerialX/issues) in up. -* If you want to comment or suggest a feature use [Discussions section](https://github.com/PetoPetko/Java-SerialX/discussions). -* If you want to see or learn some things about library, take a look at [examples](https://github.com/SimplyProgrammer/Java-SerialX/tree/tests-and-experimental-features/src/examples). -* And if you want to see the changelog, open [changelog file](Changelog.md) or use [Releases section](https://github.com/PetoPetko/Java-SerialX/releases) too. -
- - -SerialX is powerful and lightweighted utility library to serialize objects in Java. Serialization means storing Java objects and values into some media (for example text file).
-SerialX is improving regular Java Base64 serialization and adding serialization protocols that you can create for objects that cant be serialized using regular way. For example final non-serializable objects, 3rd party objects and others. SerialX API is storing objects into JSON like "programming" language (data format) called JUSS (Java universal serial script) which shares common functionality with JSON and provides more customizability and extended functionality! This allows you to serialize multiple objects into one string or also into file. But unlike to JSON, JUSS general conception is based on determinate order of arguments or values we can say. The latest versions also provides variable system (keys, values) similar to JSON. But in JUSS these variables can be overided and can interact with each other and can be used multiple times. Nowadays SerialX provides recursive descent parser that can be modified so you can create your own data structures! In other words SerialX allows you to serialize **anything**, it's pretty simple to use and practically limitless! -## Brief overview of working concept and advantages compared to regular serialization: -**Regular java serialization** is strongly based on some kind of "magic" or we can say "godly reflection" which will reflectivly read all fields of object including private and final ones and then interprets it as Base64 string. And during deserialization it will create an empty instance of object absolutely ignoring its constructors by using some "magic" compilator process to create it instad, and then it will violently write all serialized fields again including private and final ones which is realy not the best approach! Also, this allows you to serialize only instances of java.io.Serializable and all fields must be instances of Serializable as well which is also not the most useful thing!
-Compared to this, **SerialX API** is doing everything programmatically. SerialX API uses ``SerializationProtocol``s that are registered in ``ProtocolRegistry``, each working for certain class! ``SerializationProtocol`` contains 2 methods, ``serialize(T object)`` and ``unserialize(Object[] args)``. ``serialize(T object)`` method obtains certain object to serialize and its job is to turn this object into an array of objects that we can then reconstruct this exact object from, such as constructor arguments! These arguments are then paste into ``Serializer`` and ``Serializer`` serialize them into mentioned SerialX API data storage format. During deserialization, ``Serializer`` first takes given data serialized in SerialX, unserializes them into array of objects and this array is then paste into ``unserialize(Object[] args)`` method of certain ``SerializationProtocol`` as argument. The job of ``unserialize(Object[] args)`` method is to create an new instance of serialized object ``T`` from given arguments! Everything in this function is controlled by you and you can write them by yourself which gives you an absolute control!
-Note: Since 1.3.0, protocols are operated by DataParsers and are mainly used for more complex objects. Also Object to String conversion is now done by DataConverter and String - Object is done by DataParsers and further by protocols! -**Advantages and goals:** -* Overcoming most of regular serialization problems such as bypassing constructor! -* Powerful and highly costomizable/opinionated, you have control over stuff via protocols and recursive descent parser! -* Programmaticall, meaning you can decide how objects will be serialized and deserialized! -* Fast, SerialX solution is almost always far more faster than regular serialization! -* Readable, It depends but SerialX formats are supposed to be pretty readable for humans and should be also pretty intuitive for learning and writing! -* Data types recognition, SerialX defaultly supports all primitive datatypes from Java and also objects (done with protocols) compare to Json for instance! -* Small storage requirements, as you can see belove SerialX is often times far smaller than Json not even mentioning XML! -* Quantity, SerialX can serialize multiple objects into one file or string! -* Fully compatible and interoperable with JSON! -* Very easy to use, at the beginning all what you need to know is ``JsonSerializer#SerializeTo(file, objects)`` for serializing and ``JsonSerializer#LoadFrom(file)`` for deserializing! -* Recursive descent parser that is fully customizable and can be used to parse and convert potentially anything from JSON to CSS! -* Lightweight, all modules combined under 150KB! - -## Comparison: XML (.xml) vs Json (.json) vs YAML (.yml) vs JUSS (.juss or .srlx) -Sample object: -``` -public class Foo -{ - double val1 = 55, val2 = 455.45; - float val3 = 236.12F; - boolean flag = true; - - public double getVal1() - { - return val1; - } - public void setVal1(double val1) - { - this.val1 = val1; - } - public double getVal2() - { - return val2; - } - public void setVal2(double val2) - { - this.val2 = val2; - } - public float getVal3() - { - return val3; - } - public void setVal3(float val3) - { - this.val3 = val3; - } - public boolean isFlag() - { - return flag; - } - public void setFlag(boolean flag) - { - this.flag = flag; - } -} -``` -## -Serialized via **XMLDecoder for XML:** -``` - - - - - 55 - - - 455.45 - - - 236.12 - - - true - - - -``` -
Serialized via **JACKSONE (hypothetical) for Json:** -``` -... -{ - "val1" : 55.0, - "val2" : 455.45, - "val3" : 236.12, - "flag" : true -} -``` -
Serialized via **(hypothetical) YAML:** -``` -val1: 55.0 -val2: 455.45 -val3: 236.12 -flag: true -``` -
Serialized via **SerialX for JUSS (protocol):** -``` -some.package.Foo 55D 455.45 236.12F T; -``` -## After introduction of variables in 1.1.5 and scope in 1.2.0:
-Serialized via **SerialX for JUSS (protocol + scope):** -``` -some.package.Foo { - val1 = 55D, - val2 = 455.45, - val3 = 236.12F, - flag = T -} -``` -
Serialized via **SerialX for JUSS (scope only):** -``` -{ - val1 = 55D, - val2 = 455.45, - val3 = 236.12F, - flag = T -} -``` -
Maybe it is a question of formatting but JUSS with protocol will be the shortest one anyway. Because, in this case, instead of having some sort of key to the value you simply have its order (index)! -And value's data type is specified by suffix if it is a primitive data type or simply by package name as the first argument in case of an object! Other arguments (count, order, type) are then specified by a SerializationProtocol! Generally, one line means one object, one value (separated by spaces) means one argument!

-Note: Since there is variable system in 1.1.5, the order of values is now not the only option to obtain an object or value!
-
+This branch is for purely development purposes such as testing, prototyping or benchmarking and should not be used otherwise... diff --git a/SECURITY.md b/SECURITY.md deleted file mode 100644 index d24b2cb..0000000 --- a/SECURITY.md +++ /dev/null @@ -1,18 +0,0 @@ -# Security Policy - -## Versioning schema -This project uses incremental X.Y.Z version numbers (XYZ are numbers from 0 to 9) where: -* X = "Uber version", this is likely to stay 1 forever (and therefore is kind of useless). It is also quiet possible that numbers are going to be shifted 1 space towards the left for this exact reason. -* Y = Major version. When this number is incremented it usually means something "revolutionary" was added, something that moved the library forward significantly. Moderate migration is likely to be required... -* Z = Majnor version. Although it is called "minor", it can oftentimes be quiet big. The bigger the number difference between the last minor version, the bigger the update. But the library is usually compatible between minor version with minimal migration needed (deprecateds or changes are usually documented in the code...). - -## Supported Versions -There are no LTS versions, except the current version. It is recommended to always use the latest version if possible as the old versions were slow, riddled with bugs and sometimes quite significant security vulnerabilities. -Also is highly discouraged to use any "alpha", or "beta" versions. -Using versions with _SNAPSHOT at the end is only recommended when it is the latest version available. Keep it mind that the correct functionality in these versions is not guaranteed and they should be updated to the latest (non _SNAPSHOT) version/release as soon as it becomes possible. - -## Reporting a Vulnerability - -Currently, there are no known vulnerabilities present in the library but still be wise with your code, mainly with creating protocols and parsers, if your work is security-focused! -After all, and also unfortunately, this library has its history of security missteps so reporting potential vulnerability of any kind is encouraged (preferably without "spreading the word" too much). -You can do so by using [Issues section](https://github.com/SimplyProgrammer/Java-SerialX/issues). diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..c9fd16a --- /dev/null +++ b/pom.xml @@ -0,0 +1,60 @@ + + 4.0.0 + + SerialXTest + SerialXTest + 0.0.1-SNAPSHOT + SerualX-test + Used for testing + + + + org.ugp.serialx + serialx-json + 1.3.8 + + + org.ugp.serialx + serialx-devtools + 1.3.8 + + + org.ugp.serialx + serialx-operators + 1.3.8 + + + + junit + junit + 4.13.2 + provided + + + org.openjdk.jmh + jmh-core + 1.37 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + + + + + src + + + + + src + + **/*.java + + + + + \ No newline at end of file diff --git a/src/examples/Bar.java b/src/examples/Bar.java new file mode 100644 index 0000000..c50dfa6 --- /dev/null +++ b/src/examples/Bar.java @@ -0,0 +1,99 @@ +package examples; + +import java.util.List; +import java.util.Objects; + +public final class Bar extends Foo //Sample object that inheres +{ + byte by0 = (byte) 142; + short s0 = 515; + double d2 = 5; + Object sampleParent; + + @Override + public String toString() + { + return "Bar[" + a + " " + b + " " + c + " " + d + " " + f + " " + ch + " " + s + " " + nah + " " + l + " " + by0 + " " + s0 + " " + sampleParent+"]"; + } + + public Bar(Object parent) + { + this.sampleParent = parent; + } + + @Override + public boolean equals(Object obj) + { + Bar other = (Bar) obj; + return super.equals(obj) && by0 == other.by0 && Double.doubleToLongBits(d2) == Double.doubleToLongBits(other.d2) && s0 == other.s0 + && Objects.equals(sampleParent, other.sampleParent); + } + + public static class BarProtocol extends FooProtocol //Protocol to serialize Bar (and Foo) + { + @Override + public Object[] serialize(Foo object) + { + return new Object[] {object.a, object.b, object.c, object.d, object.f, object.ch, object.s, object.nah, object.l, ((Bar) object).by0, ((Bar) object).s0, ((Bar) object).sampleParent}; + } + + @SuppressWarnings("unchecked") + @Override + public Foo unserialize(Class objectClass, Object... args) + { + Bar f = new Bar(null); + f.a = (int) args[0]; + f.b = (int) args[1]; + f.c = (int) args[2]; + f.d = (double) args[3]; + f.f = (float) args[4]; + f.ch = (char) args[5]; + f.s = (String) args[6]; + f.nah = (boolean) args[7]; + f.l = (List) args[8]; + f.by0 = (byte) args[9]; + f.s0 = (short) args[10]; + f.sampleParent = args[11]; + + return f; + } + + @Override + public Class applicableFor() + { + return Bar.class; + } + } + + public byte getBy0() { + return by0; + } + + public void setBy0(byte by0) { + this.by0 = by0; + } + + public short getS0() { + return s0; + } + + public void setS0(short s0) { + this.s0 = s0; + } + + public double getD2() { + return d2; + } + + public void setD2(double d2) { + this.d2 = d2; + } + + public Object getSampleParent() { + return sampleParent; + } + + public void setSampleParent(Object sampleParent) { + this.sampleParent = sampleParent; + } +} diff --git a/src/examples/Foo.java b/src/examples/Foo.java new file mode 100644 index 0000000..9efd077 --- /dev/null +++ b/src/examples/Foo.java @@ -0,0 +1,153 @@ +package examples; + +import java.nio.file.AccessMode; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +import org.ugp.serialx.protocols.SerializationProtocol; + +public class Foo //Sample object to be serialized using its protocol! +{ + int a = 8, b = 1, c = 456; + double d = 5; + float f = 1453.364564564132454654511324f; + char ch = 'l'; + String s = "a"; + boolean nah = false; + List l = new CopyOnWriteArrayList(); + + public Foo() + { + l.add(6); + l.add(9); + l.add(13); + l.add(new HashMap<>()); + l.add(new ArrayList<>(Arrays.asList(4, 5, 6d, new ArrayList<>(), AccessMode.READ, "hi"))); + } + + @Override + public String toString() + { + return "Foo[" + a + " " + b + " " + c + " " + d + " " + f + " " + ch + " " + s + " " + nah + " " + l + "]"; + } + + + @Override + public boolean equals(Object obj) { + Foo other = (Foo) obj; + return a == other.a && b == other.b && c == other.c && ch == other.ch + && Double.doubleToLongBits(d) == Double.doubleToLongBits(other.d) + && Float.floatToIntBits(f) == Float.floatToIntBits(other.f) && l.equals(other.l) + && nah == other.nah && s.equals(other.s); + } + + public static class FooProtocol extends SerializationProtocol //Protocol to serialize Foo + { + @Override + public Object[] serialize(Foo object) + { + return new Object[] {object.a, object.b, object.c, object.d, object.f, object.ch, object.s, object.nah, object.l}; + } + + @SuppressWarnings("unchecked") + @Override + public Foo unserialize(Class objectClass, Object... args) + { + Foo f = new Foo(); + f.a = (int) args[0]; + f.b = (int) args[1]; + f.c = (int) args[2]; + f.d = (double) args[3]; + f.f = (float) args[4]; + f.ch = (char) args[5]; + f.s = (String) args[6]; + f.nah = (boolean) args[7]; + f.l = (List) args[8]; + + return f; + } + + @Override + public Class applicableFor() + { + return Foo.class; + } + } + + public int getA() { + return a; + } + + public void setA(int a) { + this.a = a; + } + + public int getB() { + return b; + } + + public void setB(int b) { + this.b = b; + } + + public int getC() { + return c; + } + + public void setC(int c) { + this.c = c; + } + + public double getD() { + return d; + } + + public void setD(double d) { + this.d = d; + } + + public float getF() { + return f; + } + + public void setF(float f) { + this.f = f; + } + + public char getCh() { + return ch; + } + + public void setCh(char ch) { + this.ch = ch; + } + + public String getS() { + return s; + } + + public void setS(String s) { + this.s = s; + } + + public boolean isNah() { + return nah; + } + + public void setNah(boolean nah) { + this.nah = nah; + } + + public List getL() { + return l; + } + + public void setL(List l) { + this.l = l; + }; + + public static void a() {}; +} diff --git a/src/examples/MemberInvokeOperator.java b/src/examples/MemberInvokeOperator.java new file mode 100644 index 0000000..35788b9 --- /dev/null +++ b/src/examples/MemberInvokeOperator.java @@ -0,0 +1,48 @@ +package examples; + +import static org.ugp.serialx.Utils.InvokeFunc; +import static org.ugp.serialx.Utils.indexOfNotInObj; +import static org.ugp.serialx.Utils.splitValues; + +import java.lang.reflect.InvocationTargetException; + +import org.ugp.serialx.converters.DataParser; +import org.ugp.serialx.converters.ProtocolConverter; +import org.ugp.serialx.juss.JussSerializer; + +/** + * This is example of more advanced parser! It can be used for calling non-static methods from objects via "->" operator!
+ * For example with this parser registered with {@link JussSerializer#JUSS_PARSERS} you can print out hello world in JUSS like System::out->println "Hello world"
+ * Note: This is only for demonstration purposes and not a real feature so its not fully compatible with JUSS syntax so you will have to use () quiet often depending on where you put this parser! + * + * @author PETO + * + * @serial 1.3.5 + */ +public class MemberInvokeOperator implements DataParser +{ + @Override + public Object parse(ParserRegistry myHomeRegistry, String str, Object... args) + { + int index; + if ((index = indexOfNotInObj(str, 0, str.length(), -1, false, "->")) > 0) + { + Object obj = myHomeRegistry.parse(str.substring(0, index).trim(), args); + String[] funcArgs = splitValues(str.substring(index+2).trim(), ' '); + + try + { + return InvokeFunc(obj, funcArgs[0], ProtocolConverter.parseAll(myHomeRegistry, funcArgs, 1, true, args)); + } + catch (InvocationTargetException e) + { + throw new RuntimeException(e); + } + catch (Exception e2) + { + return null; + } + } + return CONTINUE; + } +} diff --git a/src/examples/Message.java b/src/examples/Message.java new file mode 100644 index 0000000..0dca7ab --- /dev/null +++ b/src/examples/Message.java @@ -0,0 +1,107 @@ +package examples; + +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.Random; + +import org.ugp.serialx.juss.protocols.SelfSerializable; + +/** + * Example of self-serializable object! + * {@link SelfSerializable} objects can be serialized directly without necessity of having any {@link org.ugp.serialx.devtools.SerializationDebugger}, all you need to do is implement {@link SelfSerializable} interface and override {@link SelfSerializable#serialize()} method accordingly! + * + * @author PETO + * + * @see SelfSerializable + * + * @since 1.3.2 + */ +public class Message implements SelfSerializable +{ + protected String str; + protected long date; + + protected List replies; + protected HashMap mappedReplies; + + protected transient Object rand = new Random(); + + public Message(String str, int date) + { + this(str, date, (List) null); + } + + public Message(String str, int date, List replies) + { + setStr(str); + setDate(date); + setReplies(replies); + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + return true; + if (obj == null || getClass() != obj.getClass()) + return false; + Message other = (Message) obj; + return date == other.date && + Objects.equals(str, other.str) && + mappedReplies == null ? Objects.deepEquals(replies, other.replies) : + Objects.deepEquals(mappedReplies, other.mappedReplies); + } + + @Override + public String toString() + { + return "Message["+str+", "+date+", "+(mappedReplies == null ? replies : mappedReplies)+"]"; + } + + @Override + public Object[] serialize() + { + return new Object[] {str, date, replies}; + } + + public String getStr() { + return str; + } + + public void setStr(String str) { + this.str = str; + } + + public long getDate() { + return date; + } + + public void setDate(long date) { + this.date = date; + } + + public List getReplies() { + return replies; + } + + public void setReplies(List replies) { + this.replies = replies; + } + + public HashMap getMappedReplies() { + return mappedReplies; + } + + public void setMappedReplies(HashMap mappedReplies) { + this.mappedReplies = mappedReplies; + } + + public Object getRand() { + return rand; + } + + public void setRand(Object rand) { + this.rand = rand; + } +} diff --git a/src/examples/TryParser.java b/src/examples/TryParser.java new file mode 100644 index 0000000..64b94c7 --- /dev/null +++ b/src/examples/TryParser.java @@ -0,0 +1,35 @@ +package examples; + +import static org.ugp.serialx.Utils.indexOfNotInObj; + +import org.ugp.serialx.converters.DataParser; + +/** + * This is another example of more "advanced" parser. This one allow you to use "try" keyword and catching exceptions! + * Note: This is only for demonstration purposes and not a real feature so its not fully compatible with JUSS syntax so you will have to use () quiet often depending on where you put this parser! + * + * @author PETO + * + * @since 1.3.5 + * + * @see MemberInvokeOperator + */ +public class TryParser implements DataParser +{ + @Override + public Object parse(ParserRegistry myHomeRegistry, String str, Object... args) + { + if (indexOfNotInObj(str = str.trim(), "try") == 0) + { + try + { + return myHomeRegistry.parse(str.substring(3).trim(), false, getClass(), args); + } + catch (Exception e) + { + return e; + } + } + return CONTINUE; + } +} diff --git a/src/examples/implementations/AdvancedParsersExample.java b/src/examples/implementations/AdvancedParsersExample.java new file mode 100644 index 0000000..6564bf4 --- /dev/null +++ b/src/examples/implementations/AdvancedParsersExample.java @@ -0,0 +1,51 @@ +package examples.implementations; + +import java.io.File; + +import org.ugp.serialx.LogProvider; +import org.ugp.serialx.devtools.SerializationDebugger; +import org.ugp.serialx.juss.JussSerializer; +import org.ugp.serialx.juss.converters.ObjectConverter; +import org.ugp.serialx.juss.converters.VariableConverter; +import org.ugp.serialx.juss.protocols.UniversalObjectInstantiationProtocol; +import org.ugp.serialx.protocols.SerializationProtocol; + +import examples.MemberInvokeOperator; +import examples.TryParser; + +/** + * In this example we will create our very own simple scripting language by using {@link MemberInvokeOperator} and {@link TryParser} + * together with {@link JussSerializer#JUSS_PARSERS_AND_OPERATORS}! + * As you can see with SerialX capable of far more than parsing some JSON... + * Note: This is primarily for demonstrational purposes and might not be suitable for production... + * + * @author PETO + * + * @see TryParser + * @see MemberInvokeOperator + * + * @since 1.3.5 + */ +public class AdvancedParsersExample +{ + public static void main(String[] args) throws Exception + { + JussSerializer.JUSS_PARSERS.get(ObjectConverter.class).getInvokableClasses().add(System.class); //This is necessary since 1.3.8 + SerializationProtocol.REGISTRY.add(new UniversalObjectInstantiationProtocol<>(Object.class)); + + //In this case JussSerializer acts as an interpreter for our custom scripting language. + JussSerializer interpreter = new JussSerializer(); + + interpreter.setParsers(JussSerializer.JUSS_PARSERS_AND_OPERATORS.clone()); //Allowing usage of operators in our script! + interpreter.getParsers().addAllAfter(VariableConverter.class, new TryParser(), new MemberInvokeOperator()); //Allowing method calls and try expressions in our script! + + interpreter = SerializationDebugger.debug(interpreter); + + LogProvider.instance.setReThrowException(true); //This allows us to implement custom exception handling! + + interpreter.LoadFrom(new File("src/examples/implementations/simpleScript.juss")); //Running our script from simpleScript.juss file! + + //Printing the results of our script... + System.out.println(interpreter); //This is not necessary in this case! + } +} diff --git a/src/examples/implementations/GeneralExample.java b/src/examples/implementations/GeneralExample.java new file mode 100644 index 0000000..d3e671c --- /dev/null +++ b/src/examples/implementations/GeneralExample.java @@ -0,0 +1,196 @@ +package examples.implementations; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import java.util.concurrent.atomic.AtomicLong; + +import org.junit.Test; +import org.ugp.serialx.GenericScope; +import org.ugp.serialx.LogProvider; +import org.ugp.serialx.Scope; +import org.ugp.serialx.Utils; +import org.ugp.serialx.converters.DataParser; +import org.ugp.serialx.converters.Operators; +import org.ugp.serialx.converters.StringConverter; +import org.ugp.serialx.devtools.SerializationDebugger; +import org.ugp.serialx.juss.JussSerializer; +import org.ugp.serialx.juss.converters.ObjectConverter; +import org.ugp.serialx.protocols.SerializationProtocol; + +import examples.Bar; +import examples.Foo; + +/** + * This example is overview of general SerialX API functionalities! + * We will look at how to serialize and deserialize objects using file. We will also create protocols for our objects as well as for already existing ones! + * This example is also for testing and benchmarking! + * + * @author PETO + * + * @since 1.0.0 + */ +public class GeneralExample +{ + //Test constants... + public static final String TEST_1 = "father"; + public static final String TEST_2 = "has an event horizon... //lol"; + public static final String TEST_3 = "some string"; + + public static final double TEST_4 = 5; + public static final int TEST_4I = 6; + public static final Scope TEST_5 = new Scope(); + public static final String TEST_6 = "HELLO_WORLD"; + + @Test + public void test() throws Exception + { + GeneralExample.main(new String[0]); + } + + public static void main(String[] args) throws Exception + { + LogProvider.instance.setReThrowException(true); // This is for testing purposes, so no error are allowed in this case, comment temporary when necessary... + + //------------------------------------------- Custom protocol registration ------------------------------------------- + + SerializationProtocol.REGISTRY.addAll(new Bar.BarProtocol(), new Foo.FooProtocol(), new SerializationProtocol() //Sample custom protocol to serialized Random. + { //Random will be serialized also without protocol via classic Java Base64 because it implements java.io.Serializable! + @Override + public Object[] serialize(Random object) + { + try + { + Field f = Random.class.getDeclaredField("seed"); + f.setAccessible(true); + return new Object[] {((AtomicLong) f.get(object)).get()}; + } + catch (Exception e) + { + e.printStackTrace(); + return new Object[] {-1}; + } + } + + @Override + public Random unserialize(Class objectClass, Object... args) + { + return new Random(((Number) args[0]).longValue()); + } + + @Override + public Class applicableFor() + { + return Random.class; + } + }); + + File f = new File("src/examples/implementations/test.juss"); //File to write and read from! + + //------------------------------------------- Generating mock data ------------------------------------------- + + Random r = new Random(123); + List list = new ArrayList<>(); + for (int i = 0; i < 10; i++) + list.add(r.nextBoolean() ? r.nextInt(i+1) : r.nextBoolean()); + list.add(new LinkedList<>(list)); + + HashMap vars = new HashMap<>(); //Variables to serialize + vars.put("yourMom", TEST_2); + vars.put("num", TEST_4I); + + int[][] ints = {{1, 2, 3}, {4, 5, 4}, {3, 2, 1}}; + + String complexExpression = "$undef??0 ?12 : 11??{} ? ($_boolTst1 = 1 2 <= {1, 2, 3} - 2 - 3 + 5)&& ($_boolTst2: !!T instanceof java.lang.Boolean) && !!!5.0 > 5 && ($_boolTst3 = T) || ($_boolTst4= 'i'- 5 == 'd' ^ 240/4*2 != 'x') ? (+1 --+-6l /- 2*(2l+--(T || F))%- 10**2 + 1 ) * \"a\""; + Scope someScope = new Scope(111, 222, new Scope(new ArrayList<>(Arrays.asList("some{", "}elements{", "...", new Scope('c', TEST_5))))); + Scope neastedScope1 = new Scope(), neastedScope2 = new Scope(); + neastedScope2.put("tst4", TEST_4); + neastedScope2.add(StringConverter.DirectCode("$num")); + neastedScope1.put("neastedTest", neastedScope2); + someScope.put("test", neastedScope1); + + //------------------------------------------- Serializing ------------------------------------------- + + JussSerializer.JUSS_PARSERS.get(ObjectConverter.class).getInvokableClasses().add(GeneralExample.class); //This is necessary since 1.3.8 + + JussSerializer serializer = new JussSerializer(vars); //Creating an instance of Serializer that will serialize objects using Juss! Serializer is instance of scope so it behaves like so! + //Adding independent values Invokation of static members of this class (calling method "println" and obtaining "hello" field as argument! + serializer.addAll(TEST_3, r, list, ints, someScope, serializer.Comment("Size of array"), serializer.Var("arrSize", list.size()), new Bar(serializer.Code("$parent")), 1, 2.2, 3, 'A', true, false, null, serializer.Code("-$num::new"), serializer.Code(complexExpression), serializer.StaticMember(GeneralExample.class, "println", serializer.StaticMember(GeneralExample.class, "hello"))); + //This will insert an comment Another way to add variable except put method $ is used to obtain value from variable, ::new will attempt to clone the value + serializer.setGenerateComments(true); //Enabling comment generation + + serializer.getParsers().resetCache(); //Enabling cache, this can improve performance when serializing a lot of data (not case of this example)! + + double t0 = System.nanoTime(); + serializer.SerializeTo(f); //Saving content of serializer to file (serializing) + double t = System.nanoTime(); + System.out.println("Write: " + (t-t0)/1000000 + " ms"); //Write benchmark + + //------------------------------------------- Deserializing ------------------------------------------- + SerializationProtocol.REGISTRY.setActivityForAll(true); //Enabling all protocols, just in case... + + JussSerializer deserializer = new JussSerializer(); //Creating instance of Serializer that will deserialize objects serialized in Juss (same class is responsible for serializing and deserializing)! + deserializer.setParsers(JussSerializer.JUSS_PARSERS_AND_OPERATORS); //Doing this will allow us to use operators from org.ugp.serialx.converters.operators while deserializing! + deserializer.put("parent", TEST_1); //Setting global variables + + deserializer = SerializationDebugger.debug(deserializer); //Enabling debugging for deserialization! Do this before applying caching! + + deserializer.getParsers().resetCache(); //Enabling cache, this can improve performance when serializing a lot of data (not the case of this example)! + for (DataParser opr : Operators.BINARY) //We have to pre-cache the operator parser to prevent parser cache from breaking precedence! + deserializer.getParsers().preCache(opr.getClass()); + deserializer.getParsers().preCache(SerializationDebugger.class); + + t0 = System.nanoTime(); + deserializer.LoadFrom(f); //Loading content of file in to deserializer! + t = System.nanoTime(); + System.out.println("Read: " + (t-t0)/1000000 + " ms"); //Read benchmark + + deserializer = (JussSerializer) deserializer.filter(obj -> obj != null); //This will filter away every null value and variable! + + //Printing values and variables of scope! + System.out.println(deserializer.variables()); + System.out.println(deserializer.values()); + + //Performing test + assertEquals(TEST_1, deserializer.getString("parent")); + assertEquals(TEST_2, deserializer.getString("yourMom")); + assertEquals(deserializer.getString("yourMom").charAt(0), deserializer.getChar("yourMom")); + assertEquals(list.size(), deserializer.getInt("arrSize")); + + assertEquals(TEST_4, deserializer.getScope(4).getScope("neastedTest").getDouble("tst4"), 0); + assertEquals(deserializer.getScope(4).getScope(Utils.splitValues("test neastedTest", ' ')).getParent(2), deserializer.getScope(4)); + assertEquals(((Scope) deserializer.getScope(4).getSubScope(0).>get(0).get(3)).getSubScope(0).>toObject(List.class).size(), TEST_5.>into(Collection.class).size()); + assertTrue(deserializer.clone() instanceof JussSerializer); + assertTrue(deserializer.filter(obj -> obj.equals(new Scope("true").getBool(0))).get(0)); + + assertEquals(TEST_3, deserializer.get(0)); + assertEquals(list, deserializer.get(2)); + assertEquals(new Bar(TEST_1), deserializer.get(5)); + assertArrayEquals(ints, Scope.from(deserializer.get(3)).toArray()); + assertEquals(-TEST_4I, deserializer.getByte(-3)); + + assertTrue(deserializer.get("_boolTst1") && deserializer.cloneOf("_boolTst2") && deserializer.getBool("_boolTst4") && !deserializer.containsVariable("_boolTst3")); + assertEquals(Utils.multilpy(GenericScope.intoBidirectional(Scope.from(new Scope()) , null, Arrays.asList(97)).getChar(0), +1 +-6 / -2*(2+1)%- 100 + 1).toString(), deserializer.get(-2)); + + assertEquals(TEST_6, new Scope(deserializer).getString(-1)); + } + + //We can invoke static members in JUSS! + public static String hello = "Hello world!"; + + public static String println(String str) + { + System.out.println(str); + return TEST_6; + } +} \ No newline at end of file diff --git a/src/examples/implementations/ReadingJsonFromInternet.java b/src/examples/implementations/ReadingJsonFromInternet.java new file mode 100644 index 0000000..3ddd2b6 --- /dev/null +++ b/src/examples/implementations/ReadingJsonFromInternet.java @@ -0,0 +1,34 @@ +package examples.implementations; + +import java.io.IOException; + +import org.ugp.serialx.json.JsonSerializer; + +/** + * In this example we can see how to perform json reading from remote web url! + * Note: Internet connection is required for this example to work! + * + * @author PETO + * + * @since 1.3.2 + */ +public class ReadingJsonFromInternet +{ + public static void main(String[] args) throws IOException, Exception + { + /* + //---------------------- Before SerialX 1.3.5 ---------------------- + //Creating JsonSerializer that can parse json! + JsonSerializer reader = new JsonSerializer(); + + InputStream urlInput = new URL("https://jsonplaceholder.typicode.com/users").openStream(); //Establishing connection with https://jsonplaceholder.typicode.com/users and getting stream of received data! + reader.LoadFrom(urlInput); //Parsing url stream content into json! + */ + + JsonSerializer reader = JsonSerializer.from("https://jsonplaceholder.typicode.com/users"); //Getting and deserializing data from remote web address! + + String user = "Glenna Reichert"; //User we want to get (Glenna Reichert)! + String glennasCompany = reader.getScopesWith("name", user).getScope(0).getScope("company").getString("name"); //Obtaining first scope that contains variable with users name and getting name of his company as string from it! + System.out.println(user + " is working for " + glennasCompany); //Printing results! + } +} diff --git a/src/examples/implementations/SerializingWithJson.java b/src/examples/implementations/SerializingWithJson.java new file mode 100644 index 0000000..b9e79f5 --- /dev/null +++ b/src/examples/implementations/SerializingWithJson.java @@ -0,0 +1,152 @@ +package examples.implementations; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; + +import org.junit.Test; +import org.ugp.serialx.LogProvider; +import org.ugp.serialx.Scope; +import org.ugp.serialx.Serializer; +import org.ugp.serialx.json.JsonSerializer; +import org.ugp.serialx.juss.protocols.AutoProtocol; +import org.ugp.serialx.juss.protocols.SelfSerializableProtocol; +import org.ugp.serialx.protocols.SerializationProtocol; + +import examples.Message; + +/** + * This example demonstrating SerialX Json capabilities... + * + * @author PETO + * + * @since 1.3.8 + */ +public class SerializingWithJson +{ + public static final String[] NO_SCOPE = new String[] {"str", "date", "replies"}; + + @Test + public void test() throws Exception // SelfSerializable + { + SerializingWithJson.main(null); + } + + @Test + public void test1() throws Exception // AutoProtocol + { + SerializingWithJson.main(NO_SCOPE); + } + + @Test + public void test2() throws Exception // AutoProtocol + { + SerializingWithJson.main(new String[] {"str", "date"}); + } + + @Test + public void test3() throws Exception // AutoProtocol + { + SerializingWithJson.main(new String[] {"str", "date", "replies"}); + } + + @Test + public void test4() throws Exception // AutoProtocol + { + SerializingWithJson.main(new String[] {"str", "date", "mappedReplies"}); + } + + public static void main(String[] args) throws Exception + { + LogProvider.instance.setReThrowException(true); // This is for testing purposes, so no error are allowed in this case, comment temporary when necessary... + + SerializationProtocol.REGISTRY.add( + SerializationProtocol.REGISTRY.removeIf(prot -> prot.applicableFor() == Message.class) ? // Change this accordingly while experimenting (add negation in front)... + + /* + * Registering AutoProtocol for Message class and setting it to serialize it as Scope, but feel free to experiment (except when args are NO_SCOPE in case you are running this as test)! + */ + new AutoProtocol(Message.class, args != NO_SCOPE /*true*/, args) + { + /* + * This is not really necessary to do but in this case we are doing it to achieve a bit better efficiency/performance... + */ + public Message createBlankInstance(Class objectClass) throws Exception + { + if (objectClass == Message.class) + return new Message(null, 0, null); // Faster + return super.createBlankInstance(objectClass); // Slower... + } + } : + + /* + * Note that Message is also SelfSerializable which makes it eligible to be serialized with SelfSerializableProtocol as well! + * You can try this by changing the condition above, notice how data format will change slightly due to different serialization technique that SelfSerializable uses! + */ + new SelfSerializableProtocol<>(Message.class) + ); + + File medium = new File("src/examples/implementations/messages.json"); // Json file to use... + + // Content to serialize (list of Messages) + List messages = new ArrayList<>(); + messages.add(new Message("Hi!", 1)); + messages.add(new Message("My name is Json.", 2)); + messages.add(new Message("And I am data format!", 3)); + if (Objects.deepEquals(args, new String[] {"str", "date", "mappedReplies"})) + messages.get(2).setMappedReplies(Scope.mapKvArray(new HashMap<>(), "entry1", new Message("Hello to you as well from map!", 12))); + else + { + messages.get(0).setReplies(new ArrayList<>()); + messages.get(1).setReplies(new ArrayList<>(Arrays.asList(new Message("Hello to you as well!", 11)))); + } + + /* + * Creating new JsonSerializer object and putting out Messages into it. + */ + Serializer serializer = new JsonSerializer(null, messages); + serializer.SerializeTo(medium); // Serializing to given file. + + System.out.println("-------- Serialization complete! --------"); + + /* + * Deserializing our Messages from given file. + */ + Serializer deserializer = JsonSerializer.from(medium); + + // Mapping deserialized Scopes, or "json objects" in this case, back into our original messages! + List deserializedMessages = deserializer.map(jsonObj -> { + try + { + return ((Scope) jsonObj).toObject(Message.class); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + }); + + System.out.println("-------- Deserialization complete! --------"); + System.out.println(deserializedMessages + "\n"); + + /* Test if original content was successfully serialized as well as deserialized! */ + if (Objects.deepEquals(args, new String[] {"str", "date"})) + { + for (int i = 0; i < messages.size(); i++) + { + assertTrue(deserializedMessages.get(i).getDate() == messages.get(i).getDate()); + assertTrue(Objects.equals(deserializedMessages.get(i).getStr(), messages.get(i).getStr())); + } + + return; + } + + assertEquals(messages, deserializedMessages); + } +} diff --git a/src/examples/implementations/SimpleCalculator.java b/src/examples/implementations/SimpleCalculator.java new file mode 100644 index 0000000..d2ab26f --- /dev/null +++ b/src/examples/implementations/SimpleCalculator.java @@ -0,0 +1,66 @@ +package examples.implementations; + +import java.util.Scanner; + +import org.ugp.serialx.converters.DataParser; +import org.ugp.serialx.converters.DataParser.ParserRegistry; +import org.ugp.serialx.converters.NumberConverter; +import org.ugp.serialx.converters.operators.ArithmeticOperators; +import org.ugp.serialx.juss.converters.OperationGroups; + +/** + * This example will show you simple implementation of SerialX latest feature the recursive data parser! + * In this example we will be creating simple evaluator of mathematical expressions! + * + * @author PETO + * + * @since 1.3.0 + */ +public class SimpleCalculator +{ + static Scanner scIn = new Scanner(System.in); + + public static void main(String[] args) + { + /* + * We could easily just use DataParser.REGISTRY but there is tone of stuff we do not need and it will just slow it down! + */ + ParserRegistry parsersRequiredToEvaluateMath = new ParserRegistry(new OperationGroups(), new ArithmeticOperators(), new NumberConverter());; + + /* + * This is an example of simple custom parser this one will allow us to reuse answers of out previous evaluations! + * We will access this old answer using 'ans' word! + * Old ans must be provided as first one of args! + */ + DataParser ansParser = new DataParser() + { + @Override + public Object parse(ParserRegistry myHomeRegistry, String str, Object... args) + { + if (str.equalsIgnoreCase("ans")) + { + if (args.length > 0) + return args[0]; //First arg is old answer! + return null; + } + return CONTINUE; + } + }; + parsersRequiredToEvaluateMath.add(ansParser); + + Object oldAns = null; + while (true) + { + System.out.print("Please insert your math problem: "); //Ask for input! + String input = scIn.nextLine() ;//Read console input + if (!(input = input.trim()).isEmpty()) //Avoiding empty input! + { + double t0 = System.nanoTime(); //Performing simple benchmark + oldAns = parsersRequiredToEvaluateMath.parse(input, oldAns); //Notice that we are inserting oldAns as compiler arguments for parseObj which are then picked up by our ansParser as well as every other registered DataParser. + double t = System.nanoTime(); + + System.out.println(input + " = " + oldAns +"\n" + (t-t0)/1000000 + "ms \n"); //Parsing input! + } + } + } +} diff --git a/src/examples/implementations/SimpleQuerying.java b/src/examples/implementations/SimpleQuerying.java new file mode 100644 index 0000000..35d17f1 --- /dev/null +++ b/src/examples/implementations/SimpleQuerying.java @@ -0,0 +1,237 @@ +package examples.implementations; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; + +import org.junit.Test; +import org.ugp.serialx.GenericScope; +import org.ugp.serialx.LogProvider; +import org.ugp.serialx.Scope; +import org.ugp.serialx.Serializer; +import org.ugp.serialx.Utils; +import org.ugp.serialx.converters.DataParser; +import org.ugp.serialx.json.JsonSerializer; +import org.ugp.serialx.json.converters.JsonCharacterConverter; +import org.ugp.serialx.juss.JussSerializer; +import org.ugp.serialx.juss.converters.ObjectConverter; + +/** + * This example contains brief example of querying and obtaining real data from deserialized content! + * + * @author PETO + * + * @since 1.3.5 + */ +public class SimpleQuerying +{ + public static final String TEST_1 = "Is the best!"; + public static final String TEST_2 = "app"; + public static final long TEST_3 = 58; + public static final String TEST_JSON = "Hello world I am Javascript object notation!"; + + @Test + public void test() throws Exception + { + SimpleQuerying.main(new String[0]); + } + + public static void main(String[] args) throws Exception + { + LogProvider.instance.setReThrowException(true); // This is for testing purposes, so no error are allowed in this case, comment temporary when necessary... + + JussSerializer.JUSS_PARSERS.get(ObjectConverter.class).getInvokableClasses().addAll(Arrays.asList(JsonSerializer.class, Integer.class)); //This is necessary since 1.3.8 + + //Preparing to load complex juss file "commentedExample.juss"! + + JussSerializer content = new JussSerializer(); // Creating JussSerializer for deserialization... + + Scope testScope = new Scope(), testScope2 = new Scope(); + testScope2.put("1", TEST_1); + testScope.put("", testScope2); + content.putAllKv( // Putting initial variables into it before actual deserialization, these variables will then be accessible inside "commentedExample.juss"! + "TEST", testScope, + "TEST_2", TEST_2, + "", TEST_JSON + ); + + content = (JussSerializer) Serializer.from(content, "src/examples/implementations/commentedExample.juss", new String[0]); //Since 1.3.5 we can use "from/into API" to load content of scope by just typing its path into "from" method! + + //Printing loaded data! + System.out.println("Used content:\n" + content + "\n"); + + /* + * Scope#getScope method is capable of getting scopes that are direct sub-scopes of scope but also it will automatically search for required scope + * through every sub-scope in content! Thats why we can get sub-scope stored by "serialx" variable even though it is neasted in 3 parent scopes, Scope#getScope method will + * search for it automatically without necessity of chaining multiple of them. In case of there being more than one "serialx" we can specify the specific path like + * content.getScope("dependencies", "something", "serialx")! But in case of there being only one, like we have, this is not really necessary. + */ + String serialx = content.getScope("serialx").getString(0); //Getting first independent value of scope stored by variable "serialx"! + System.out.println("SerialX " + serialx.toLowerCase()); //Printing result! + + /** + * We often times have scopes where there are data with repetitive structure. In this case in scope stored by "ppl" there are always sub-scopes that have name, age and residence! + * We can use Scope#getAllStoredBy to get values of all variables from this sub-scopes. + * In this example we will take all age of all people, sum it up and than print average age of them! + */ + List ages = content.getScope("ppl").getAllStoredBy("age"); //Getting all age variables of sub-scopes from "ppl" scope! \ + //Suming them and printing avg age! + double sum = 0; + for (Number number : ages) + sum += number.doubleValue(); + System.out.println("Avarage age of people is: " + (sum / ages.size())); + + /** + * Sometimes we do not need to get only values of variables inside of a scope, sometimes we need actual scopes with variables meeting certain criterias, + * this is case where method Scope#getScopesWith comes in handy! This method will return sub-scope containing all sub-scopes found that contains variable that meats + * a certain condition! + * With this we can for example get all people that live in a certain country! + */ + String residence = "germany"; //Country of residence! + Scope residents = content.getScope("ppl").getScopesWith("residence", residanceValue -> ((String) residanceValue).equalsIgnoreCase(residence)); //Getting all people sub-scopes that whose have "residence" variable equal to required residence! + System.out.println("People liveing in " + residence + " are: " + residents.getAllStoredBy("name")); //Printing names of those who live in Germany! + + /** + * Perhaps the most powerful querying method is GenericScope#filter that allow you to filter away both independent values as well as variables with values that + * does not meet your condition! + * In this particular example we are writing pretty simple condition that will filter away everything that is not a scope and has no independent values inside! + */ + Scope filtered = (Scope) content.getScope("dataStorage").filter(obj -> ((Scope) obj).valuesCount() > 0); //Filtering + System.out.println(filtered.variables()); //Printing variables of filtered sub-scope! + + /** + * One also very powerful method is GenericScope#map that will remap independent values of the scope based on rule you write! + * In this case we are taking all values of sub-scope stored by "arr" variable and multiplying them by 2 if they are bigger than 3! + * Notice that by returning DataParser#VOID we can filter away the certain values! + * + * Honorable mention is also GenericScope#transform that will transform entire scope including values of variables not only independent values like map! + */ + List remappedValues = content.getScope("arr").map(obj -> ((Number) obj).doubleValue() > 3 ? ((Number) obj).doubleValue() * 2 : DataParser.VOID); //Remapping independent values of scope stored by "arr" by multiplying them by 2 if they are bigger than 3! + System.out.println("Mapped number values: " + remappedValues); //Printing remapped independent values of "arr"! + + /** + * We can use GenericScope#map in combination with Scope#toObject and Scope#into methods to remap scopes into real java objects! + * For instance we can remap all all scopes representing residents of Germany into real Java sample Person objects! + */ + List realResidents = residents.map(obj -> { + try + { + return ((Scope) obj).into(Person.class); //Turning scopes into real Java objects! + } + catch (Exception e) + { + return DataParser.VOID; //We already know that this will filter away the object! + } + }); + System.out.println("Real \"Java\" residents of " + residence + " are: " + realResidents); //Printing results + + //Performing tests, note that correctness of these tests depends on src/examples/implementations/commentedExample.juss + assertEquals(TEST_1, serialx); + assertEquals(content.getScope("ppl").valuesCount(), ages.size()); + assertEquals(filtered.getScope("serialx"), content.getScope("serialx")); + + assertTrue(residents.>toObject(List.class).size() > 0); //Should not be 0 + assertTrue(remappedValues.size() > 0); + + JsonSerializer test = new JsonSerializer(); + assertEquals(new Scope(residents).clone().clone(JussSerializer.class).into(test).valuesCount(), realResidents.size()); + assertFalse(realResidents.contains(DataParser.VOID) || realResidents.contains(null)); + assertEquals(residents, test); + + GenericScope sc = content.getScope("devDependencies", "ppl", "ludvig"); + assertEquals(TEST_2, content.get(-1)); + assertEquals(((Scope) sc).getString("residence"), "null"); + assertEquals(TEST_3, ((Scope) sc).getLong("age")); + assertEquals(((Scope) content.transformToScope()).getScope("alienFruit").toObjectOf("variants", List.class), new GenericScope<>(1, 2, 3).values()); + + assertNotEquals(TEST_2, (sc = content.getScope("devDependencies")).get("name")); + assertNull(sc.get(-1)); + assertNull(sc.get("nope")); + + sc = sc.getGenericScope("something"); + assertNotEquals(sc.get(0), sc.get(1)); + assertFalse(sc.containsVariable("version")); + + assertNotNull(content.get("srlxVer1")); + assertEquals(content.get("srlxVer1"), content.getString("srlxVer1")); + + sc = content.getScope("jsonCrossover"); + assertTrue(sc instanceof JsonSerializer); + assertTrue(Scope.from(sc).castTo(Scope.class) instanceof Scope); + assertEquals(TEST_JSON, sc.get("he" + Utils.multilpy("l", 2) + "o")); + assertFalse(sc.getGenericScope("jsonArray").isEmpty()); + assertEquals(sc.getClass(), content.get("jsonArrayCla" + Utils.multilpy('s', 2))); + + + assertEquals(content.getGenericScope("genericScope").get(Arrays.asList((Object[]) content.getParsers().parse("(1_0_0e-2 (0b10 ) 3d)"))), new JsonCharacterConverter(false).toString(null, '{') /* DO NOT DO IN PROD ("123") */); + assertEquals(content.getGenericScope("genericScope").get(Arrays.asList(-+-+04, -+-5.000, 0x6)).get(0), 456d); + assertEquals(content.getGenericScope("genericScope").get(Arrays.asList(.7, 8f, (byte) +-+-9)).get("test"), 789l); + + assertNotNull(sc = content.getScope("arr")); + for (Object obj : content.getScope("superArr")) + assertTrue(sc.equals(obj)); + } + + /** + * Dummy class, part of SerialX {@link SimpleQuerying} example!
+ * Note: In order for {@link Scope#toObject} and {@link Scope#into} and methods to work, object must have valid getters and setters! + * + * @author PETO + * + * @since 1.3.5 + */ + public static class Person + { + protected String name, residance; + protected double age; + + public Person(String name, String residance, double age) + { + this.name = name; + this.residance = residance; + this.age = age; + } + + public String getName() + { + return name; + } + + public void setName(String name) + { + this.name = name; + } + + public String getResidance() + { + return residance; + } + + public void setResidance(String residance) + { + this.residance = residance; + } + + public double getAge() + { + return age; + } + + public void setAge(double age) + { + this.age = age; + } + + @Override + public String toString() + { + return "Person[name=" + name + ", residance=" + residance + ", age=" + age + "]"; + } + } +} diff --git a/src/examples/implementations/commentedExample.juss b/src/examples/implementations/commentedExample.juss new file mode 100644 index 0000000..63c2245 --- /dev/null +++ b/src/examples/implementations/commentedExample.juss @@ -0,0 +1,175 @@ +/* THIS IS HOW RESULT OF SERIALX (Juss) REAL LIFE IMPLEMENTATION MIGHT LOOK LIKE */ +/* See also SimpleQuerying.java. !! This file is used for unit tests, do not modify! */ + +import org.ugp.serialx.json.JsonSerializer => Json; //Importing JsonSerializer and aliasing it as Json! +import org.ugp.serialx.GenericScope; //Importing without aliasing! + +name = $TEST_2; //"TEST_XY" variables are not declared in here as you can see, they are expected to be provided by the deserializer! + +dependencies = +{ + //This is scope, the Juss representation of ugp.org.SerialX.Scope! + //Each scope can have its own variables with values and independant values! + + //Every scope can read and write parent scopes variables however by changing them, it will only affect local one and not parents one! + $name; //"app" ($ obtains value from variable, in this case "app") + $name = "no longer app lol!"; + + composition-api = "1.0.0 (beta)", //This is one of the variables of this scope... + bootstrap = "4.5.3", + version = "2.3.4", + something = + { + dataStorage { + //This is "dataStorage" (stored by variable "dataStorage") sub-scope aka nested skope of its parent scope "something" which is subscope of "dependencies", + xml = + { + version = "2.8.0" + }, + yaml = + { + version = "1.10.5" + }, + josn = + { + version = "4.0.0" + }, + serialx = + { + version = "The best version!"; + $TEST..1 // this one is also provided by deserializer, also this one is a bit tricky... + } + totalVersion = "9.9.9" + }, + ppl = + { + //This is "ppl" (stored by variable "ppl") sub-scope aka nested skope of its parent scope "something" which is subscope of "dependencies". + //All of these scopes are sub-scopes of "ppl", there can be infinite number of variables and independent values together in one Scope! + { + name: "Vladimir"; + age = 37; + residence = "russia"; + }, + { + name: "Ivan"; + age = 19; + residence = "russia"; + }, + { + name: "Firippu"; + age = 103; + residence = "japan"; + }, + { + name: "Peter"; + age = 17; + residence = "slovak"; + }, + { + name: "Lukas"; + age = 23; + residence = "usa"; + }, + { + name: "Hans"; + age = 51; + residence = "germany"; + }, + { + name: "Yeager"; + age = 17; + residence = "germany"; + }, + { + name: "Pierre"; + age = 44; + residence = "france"; + } + } + }, + "lololoolollool"; //This is independent value of this scope. +}, +$srlxVer1 = srlxVer2 = $dependencies.something.dataStorage.serialx.version; //Obtaining value of "serialx" variable in "dependencies" sub-scopes! + +something = +[ + test = "NOPE" +} //Well yea... [} or {] is possible. In 99% cases the interpreter sees these 2 chars as the same one... but it does not mean that you should adopt this convention... + +devDependencies = +{ + //Variables in this scope have nothing to do with variables from "dependencies" because they are in diffrent scope! + $name = "absolutely not app!"; + + composition-api = "1.0.0 (alpha)", + bootstrap = "2.2.3", + version = "1.2.3", + something = + { + $version, + version = "9.9.9", + $version, + version = void, //We can use void in order to remove variable entirely + + dataStorage = {}, + ppl = {} + } + + nope = $something.test, + + $something.dataStorage.xml.version +}; +//Setting variable of scope from outer world (possible since 1.3.2) +devDependencies.something.ppl.ludvig = +{ + String::valueOf "_SCOPE"; + age = Math::max {int::valueOf "50"} {Math::pow {Double::valueOf {String::valueOf Math::PI}} 3.55}; + residence = String::valueOf "russia"; +}; + +//Since 1.2.5 Serializer fully supports Json and JavaScript object! +jsonCrossover = Json { + /* Yes... $ are not valid values in Json. But in SerialX, Json is the superset of Juss so it is possible. In real usecase you probably want to avoid this! */ + "hello" : $, // As we know, $ is for getting value of the variable however there is no variable name right...? Well actually it is "", the name-less variable. Yea... thats also a thing... + "jsObject": { + name: "John", + age: 31, + city: "New York" + }, + "jsonArray": [ + 1, + 2, + 3, + 4 + ] +}, +jsonArrayClass = $jsonCrossover.jsonArray::class; + +//Since 1.3.5, generic scopes are supported. They allow ussage of anything as a key not only strings! +genericScope = GenericScope { + ArrayList 1_0_0e-2 0b10 3d: String 49y 50s 51, + ArrayList -+-+04 -+-5.000 0x6: {456.000d}, + ArrayList .7 8f +-+-9y: {test: 789L} +} +//But there is no way to read them if they are not string... + +//Since SerialX 1.3.5 we can use "from/into API" to load files from external locations! +alienFruit = Json::from "src/examples/implementations/test.json"; //Loading content of external file by using JsonSerializer! +alienPost = Json::from "https://jsonplaceholder.typicode.com/posts/1"; //We can even load files from remote urls (internet connection is required for this)! + +//$bullshit <-- No this is not possible, variable "bullshit" cannot be accessed here because it was not initialized yet! +bullshit = +{ + //This scope cant access variable that is stored by (bullshit), because variable is always created after its value (Scope in this case) is constructed! + server = "service server", + build = "service build", + sql = "service sql"; + + devDependencies.something.ppl.ludvig.residence = ; //Same as = null +}, +$bullshit; //Now we can access variable "bullshit" + +$name; //"name" is still "app" in this scope! + +arr = {1, 2, 3, 4, 5}; //This is scope with only values! So lets call it... array I guess! +superArr = {$arr, $arr, $arr, $arr::new /*creates clone of arr*/, {1, 2, 3, 4, 5}}; //Yes... this is completely normal and possible in Juss but keep in mind that first, second and third element will refere to same instance in this case! diff --git a/src/examples/implementations/messages.json b/src/examples/implementations/messages.json new file mode 100644 index 0000000..87f4f80 --- /dev/null +++ b/src/examples/implementations/messages.json @@ -0,0 +1,23 @@ +[ + { + "str" : "Hi!", + "date" : 1, + "mappedReplies" : null + }, + { + "str" : "My name is Json.", + "date" : 2, + "mappedReplies" : null + }, + { + "str" : "And I am data format!", + "date" : 3, + "mappedReplies" : { + "entry1" : { + "str" : "Hello to you as well from map!", + "date" : 12, + "mappedReplies" : null + } + } + } +] \ No newline at end of file diff --git a/src/examples/implementations/simpleScript.juss b/src/examples/implementations/simpleScript.juss new file mode 100644 index 0000000..cf8cd1d --- /dev/null +++ b/src/examples/implementations/simpleScript.juss @@ -0,0 +1,21 @@ +/* THIS EXAMPLE IS DEMONSTRATING CAPABILITIES OF SERIALX AS A DOMAIN SPECIFIC LANGUAGE TOOLKIT BY CREATING A SIMPLE SCRIPT */ +/* In this case, we are writing a simple script that will print "Hello world!" and then analyze your age category from the age given! */ + +System::out->println "Hello world!"; //Saying the famous "Hello world" in our custom script by calling java methods! + +//Handling possible errors! +result = try { //Convenient usage of JUSS scope as a code block... + System::out->print "Enter your age: "; //Asking for input! + + input = java.util.Scanner System::in; //Declaring input scanner object! + age = double ($input->nextLine); //Reading input from console as number! + + //Printing age message + System::out->println ($age >= 18 ? "You are an adult!" : $age <= 0 ? "Well, you are not yet..." : "You are sill a child!"); +} + +//Printing adequate error message... +$result instanceof java.lang.RuntimeException ? (System::err->println (Math::random > 0.5 ? "Age must be a number you dummy..." : "Age must be numeric, dum-dum...")); + +//Voidification of used variables that are not needed! This is not really a necessity but it nice to know about it... +result = void; //Voidification will remove the variable from this scope releasing some memory! diff --git a/src/examples/implementations/test.json b/src/examples/implementations/test.json new file mode 100644 index 0000000..4a4419c --- /dev/null +++ b/src/examples/implementations/test.json @@ -0,0 +1,10 @@ +{ + "fruit": "Apple", + "size": "Large", + "color": "Red", + "variants": [ + 1, + 2, + 3 + ] +} \ No newline at end of file diff --git a/src/examples/implementations/test.juss b/src/examples/implementations/test.juss new file mode 100644 index 0000000..3b9515b --- /dev/null +++ b/src/examples/implementations/test.juss @@ -0,0 +1,60 @@ +//Date created: 09-08-2024 at 23:04:27 CEST + +//Scope serialization summary: +//2 variables! +//18 values! + +num = 6; //Primitive data type: "6" the integer value! Stored by "num" variable! +yourMom = "has an event horizon... //lol"; //Object of java.lang.String: "has an event horizon... //lol"! Stored by "yourMom" variable! +"some string"; //Object of java.lang.String: "some string"! +java.util.Random 68284896517770L; //Object of java.util.Random: "java.util.Random@46cdf8bd" serialized using examples.implementations.GeneralExample$1[java.util.Random]! +ArrayList 0 0 T 1 3 0 5 T 5 6 {java.util.LinkedList 0 0 T 1 3 0 5 T 5 6}; //Object of java.util.ArrayList: "[0, 0, true, 1, 3, 0, 5, true, 5, 6, [0, 0, true, 1, 3, 0, 5, true, 5, 6]]" serialized using org.ugp.serialx.protocols.ListProtocol[java.util.Collection]! +(1 2 3) (4 5 4) (3 2 1); //Primitive array [[I@f0c8a99 converted by org.ugp.serialx.juss.converters.ArrayConverter +{ + //Scope serialization summary: + //1 variables! + //3 values! + + test = + { + //Scope serialization summary: + //1 variables! + + neastedTest = + { + //Scope serialization summary: + //1 variables! + //1 values! + + tst4 = 5.0; //Primitive data type: "5.0" the double value! Stored by "tst4" variable! + $num; //Manually inserted code! + } + }; + 111; //Primitive data type: "111" the integer value! + 222; //Primitive data type: "222" the integer value! + { + //Scope serialization summary: + //1 values! + + ArrayList "some{" "}elements{" "..." { + //Scope serialization summary: + //2 values! + + '99'; //Primitive data type: "c" the character value! + {} //Empty scope! + }; //Object of java.util.ArrayList: "[some{, }elements{, ..., Scope[c, Scope[]]]" serialized using org.ugp.serialx.protocols.ListProtocol[java.util.Collection]! + } +}; +//Size of array +arrSize = 11; //Manually inserted code! +examples.Bar 8 1 456 5.0 1453.3646F '108' "a" F {java.util.concurrent.CopyOnWriteArrayList 6 9 13 java.util.HashMap {ArrayList 4 5 6.0 ArrayList {java.nio.file.AccessMode "READ"} "hi"}} -114Y 515S $parent; //Object of examples.Bar: "Bar[8 1 456 5.0 1453.3646 l a false [6, 9, 13, {}, [4, 5, 6.0, [], READ, hi]] -114 515 ${$parent}]" serialized using examples.Bar$BarProtocol[examples.Bar]! +1; //Primitive data type: "1" the integer value! +2.2; //Primitive data type: "2.2" the double value! +3; //Primitive data type: "3" the integer value! +'65'; //Primitive data type: "A" the character value! +T; //Primitive data type: "true" the boolean value! +F; //Primitive data type: "false" the boolean value! +null; //Null, the nothing! +-$num::new; //Manually inserted code! +$undef??0 ?12 : 11??{} ? ($_boolTst1 = 1 2 <= {1, 2, 3} - 2 - 3 + 5)&& ($_boolTst2: !!T instanceof java.lang.Boolean) && !!!5.0 > 5 && ($_boolTst3 = T) || ($_boolTst4= 'i'- 5 == 'd' ^ 240/4*2 != 'x') ? (+1 --+-6l /- 2*(2l+--(T || F))%- 10**2 + 1 ) * "a"; //Manually inserted code! +{examples.implementations.GeneralExample::println examples.implementations.GeneralExample::hello}; //Manually inserted code! \ No newline at end of file diff --git a/src/tests/n/benchmarks/Benchmarks.java b/src/tests/n/benchmarks/Benchmarks.java new file mode 100644 index 0000000..7265e5b --- /dev/null +++ b/src/tests/n/benchmarks/Benchmarks.java @@ -0,0 +1,208 @@ +package tests.n.benchmarks; + +import static org.openjdk.jmh.annotations.Scope.Benchmark; +import static org.ugp.serialx.Utils.fastReplace; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.results.RunResult; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.openjdk.jmh.runner.options.TimeValue; +import org.ugp.serialx.GenericScope; +import org.ugp.serialx.LogProvider; +import org.ugp.serialx.Utils; +import org.ugp.serialx.converters.DataConverter; +import org.ugp.serialx.converters.NumberConverter; + +@State(Benchmark) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations = 0) +@Measurement(iterations = 100) +@BenchmarkMode( + Mode.SingleShotTime +// Mode.Throughput +) +@Fork(1) // 1 or 2 +public class Benchmarks { + + @Param({"0", "0b11l", "12345", "-14445", "1 1", "0xff", "0b11111111", "011", "15.222", "16.88e2", "1234_5678_91011"}) + String nvalue; + +// @Param({"java.util.ArrayList 5 5 5", "java.util.concurrent.TimeUnit 1 2 3", "5hjdhjsakhdjsakhdjsahdjhdjak {} 59", "{hjdhjsakhdjsakhdjsahdjhdjak T T T"}) +// String str; + +// @Param({"a"}) +// char ch; +// +// @Param({"4", "16", "250", "500"}) +// int count; +// +// @Param({"true", "f", "TRue", "FaLse", "tru0", "asdasdzxc", "falsr"}) +// String bvalue; + +// @Param({"adsadas {adsa {asdasd adasdsa asdas} adasdsdas } adsad adas", "{a{b{c}}aaaaaa}"}) +// String objs; + + GenericScope scope; + + static final Function trans = val -> ((Number)val).doubleValue()+5; + + DataConverter benchSubject = new NumberConverter(); + + DataConverter benchSubjectOld = new NumberConverter() { + public Object parse(ParserRegistry myHomeRegistry, String arg, Object... args ) + { + if (arg.length() > 0) + { + char ch = arg.charAt(0); + if (ch == '+' || ch == '-' || ch == '.' || (ch >= '0' && ch <= '9')) + { + arg = normFormatNum(arg.toLowerCase()); + ch = arg.charAt(arg.length()-1); //ch = last char + + if (ch == '.') + return CONTINUE; + if (Utils.contains(arg, '.') || (!arg.startsWith("0x") && ch == 'f' || ch == 'd')) + { + if (ch == 'f') + return new Float(fastReplace(arg, "f", "")); + return new Double(fastReplace(arg, "d", "")); + } + + try + { + if (ch == 'l') + return new Long(Long.parseLong(fastReplace(fastReplace(fastReplace(arg, "l", ""), "0b", ""), "0x", ""), arg.startsWith("0b") ? 2 : arg.startsWith("0x") ? 16 : 10)); + if (ch == 's') + return new Short(Short.parseShort(fastReplace(fastReplace(fastReplace(arg, "s", ""), "0b", ""), "0x", ""), arg.startsWith("0b") ? 2 : arg.startsWith("0x") ? 16 : 10)); + if (ch == 'y') + return new Byte(Byte.parseByte(fastReplace(fastReplace(arg, "y", ""), "0b", ""), arg.startsWith("0b") ? 2 : 10)); + return new Integer(Integer.parseInt(fastReplace(fastReplace(arg, "0b", ""), "0x", ""), arg.startsWith("0b") ? 2 : arg.startsWith("0x") ? 16 : 10)); + } + catch (NumberFormatException e) + { + if (arg.matches("[0-9.]+")) + try + { + return new Long(Long.parseLong(fastReplace(fastReplace(fastReplace(arg, "l", ""), "0b", ""), "0x", ""), arg.startsWith("0b") ? 2 : arg.startsWith("0x") ? 16 : 10)); + } + catch (NumberFormatException e2) + { + LogProvider.instance.logErr("Number " + arg + " is too big for its datatype! Try to change its datatype to double (suffix D)!", e2); + return null; + } + } + } + } + return CONTINUE; + } + }; +// +// BooleanConverter boolConv = new BooleanConverter(); +// +// BooleanConverter boolConvOld = new BooleanConverter() { +// public Object parse(ParserRegistry myHomeRegistry, String arg, Object... args) { +// if (arg.equalsIgnoreCase("T") || arg.equalsIgnoreCase("true")) +// return new Boolean(true); +// if (arg.equalsIgnoreCase("F") || arg.equalsIgnoreCase("false")) +// return new Boolean(false); +// return CONTINUE; +// }; +// }; + +// @Setup() +// public void setup() { +// scope = new GenericScope(null, nums(1000_000)); +// } + + @Benchmark + public void bench(Blackhole hole) + { + hole.consume(benchSubject.parse(null, nvalue)); + } + + @Benchmark + public void benchOld(Blackhole hole) + { +// hole.consume(Integer.valueOf(value)); +// hole.consume(Double.valueOf(value)); + hole.consume(benchSubjectOld.parse(null, nvalue)); + } + +// @Benchmark +// public void bench(Blackhole hole) +// { +// hole.consume(scope.map(trans)); +//// hole.consume(boolConv.parse(null, bvalue)); +// } + +// @Benchmark +// public void benchOld(Blackhole hole) +// { +//// hole.consume(Integer.valueOf(value)); +//// hole.consume(Double.valueOf(value)); +//// hole.consume(boolConvOld.parse(null, bvalue)); +// } + + public static void main(String[] args) throws Exception { + OptionsBuilder ob = new OptionsBuilder(); + ob.measurementTime(TimeValue.milliseconds(100)); + ob.include(Benchmarks.class.getSimpleName()); + +// ParserRegistry reg = Operators.install(new ParserRegistry(new OperationGroups(), new VariableConverter(), new StringConverter(), new ObjectConverter(), new ArrayConverter(), new NumberConverter(), new BooleanConverter(), new CharacterConverter(), new NullConverter(), new SerializableBase64Converter())); +// +// JussSerializer srl = new JussSerializer(); +// srl.setParsers(reg); +// System.out.println(reg.parse("-1 + 1")); +// System.out.println(reg.parse("10 * 2 + 5")); +// System.out.println(reg.parse("2 ** 4 - 6")); +// System.out.println(reg.parse("18 ++ 20 -+ 8")); +// System.out.println(reg.parse("--5 --9")); +// +// ob.verbosity(VerboseMode.SILENT); + Collection runResults = new Runner(ob).run(); + +// Scope s = new Scope(); +// s.add(new Scope("hi".equalsIgnoreCase(null), 123)); +// Scope i = s.get(0, Scope.class); +// System.out.println(i); +// +// String str = "0xff"; +// Object num = numberOf(str, 10, 0); +// System.out.println(num + " | " + num.getClass().getSimpleName()); + +// for (char i = 0; i < 128; i++) +// System.out.println((int)i + " " + i + " | " + (i | ' ') + " " + (char)(i | ' ')); + System.out.println(NumberConverter.numberOf("0b11l", '0', 4, 10, 0) + " " + 0b11l); + System.out.println(NumberConverter.numberOf("1_0_0", '1', 4, 10, 0) + " " + 1_0_0); + System.out.println(NumberConverter.numberOf(".1e2", '1', 3, 10, 0) + " " + .1e2); + System.out.println(NumberConverter.numberOf("10e2", '1', 3, 10, 0) + " " + 10e2); + +// for (String bval : Arrays.asList("true", "f", "TRue", "FaLse", "tru0", "asdasdzxc", "falsr")) { +// System.out.println(new BooleanConverter().parse(null, bval)); +// } + } + + public static List nums(int size) + { + ArrayList nums = new ArrayList<>(); + for (int i = 0; i < size; i++) + nums.add(i); + return nums; + } +} diff --git a/src/tests/n/benchmarks/StandardBenchmark.java b/src/tests/n/benchmarks/StandardBenchmark.java new file mode 100644 index 0000000..d787c18 --- /dev/null +++ b/src/tests/n/benchmarks/StandardBenchmark.java @@ -0,0 +1,263 @@ +package tests.n.benchmarks; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Reader; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.infra.BenchmarkParams; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.OptionsBuilder; +import org.ugp.serialx.Serializer; +import org.ugp.serialx.juss.JussSerializer; + +/** + * StandardBenchmark for SerialX, single shot no warmup... + * + * @version 1.1.0 + * + * @since 1.3.8 + * + * @author PETO + */ +@State(Scope.Benchmark) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Warmup(iterations = 0) // 2 +@Measurement(iterations = 1) // 1 +@BenchmarkMode( + Mode.SingleShotTime +) +@Fork(3) // 1 +public class StandardBenchmark +{ + static final int seed = 123; // DO NOT CHANGE + + public static class DataState + { + protected final M medium; + protected final Collection data; + + public DataState(M medium, int count) // DO NOT CHANGE + { + this.medium = medium; + + if (count > 0) + { + Object[] dataArr = new Object[count]; + Random rand = new Random(seed); + for (int i = 0, rng = rand.nextInt(count/2)+2, bool = rng % 2; i < count; i++) + switch (i % 4) + { + case 0: + dataArr[i] = (++bool % 2 == 0 || bool % 11 == 0); break; + case 1: + dataArr[i] = (0.25 + rng + i); break; + case 2: + dataArr[i] = (rng + i); break; + case 3: + dataArr[i] = ("bench" + i); break; + } + data = Arrays.asList(dataArr); + } + else + data = null; + + setupMedium(); + +// double t0 = System.nanoTime(); +// long i = 4500000000l; +// while (i-- > 1); +// double t = System.nanoTime(); +// System.out.println(i + " | " + (t-t0)/1000000); + } + + public void setupMedium() {} + } + + public Serializer newSerializer(Map vars, Collection data) + { + JussSerializer srl = new JussSerializer(vars, data); + srl.getParsers().resetCache(); // Cached + return srl; + } + + @Param({"8000000", "4000000"}) + protected int dataCount; + + protected DataState state; + + @Setup + public void setupState(BenchmarkParams params) + { + state = new DataState(new File("src/tests/n/benchmarks/_" + dataCount + "_bench.juss"), params.getBenchmark().endsWith("write") ? dataCount : 0); + } + + @Benchmark + public void _0_write(Blackhole hole) throws IOException + { + JussSerializer serializer = (JussSerializer) newSerializer(null, state.data); +// serializer.setGenerateComments(true); + + serializer.SerializeTo((File) state.medium); + + hole.consume(serializer); + } + + @Benchmark + public Object _1_read() throws FileNotFoundException + { + JussSerializer deserializer = (JussSerializer) newSerializer(null, null); + + return deserializer.LoadFrom((File) state.medium); + } + +// @Benchmark +// public void readAndFormat(LargeFileData data, Blackhole hole) throws FileNotFoundException +// { +// hole.consume(new JussSerializer().readAndFormat(new FileReader(data.file), false)); +// } + + /* IO */ + +// @Benchmark +// public StringBuilder readChars(LargeFileData data) throws IOException +// { +// try (Reader reader = new FileReader(data.file)) +// { +// return readChars(reader); +// } +// } +// +// @Benchmark +// public StringBuilder readLinesAndChars(LargeFileData data) throws IOException { +// try (Reader reader = new FileReader(data.file)) +// { +// return readLinesAndChars(reader); +// } +// } +// +// +// @Benchmark +// public StringBuilder readCharsArrayed(LargeFileData data) throws IOException { +// try (Reader reader = new FileReader(data.file)) +// { +// return readCharsArrayed(reader); +// } +// } + +////StringBuilder sb = new StringBuilder(); +////char[] arr = new char[256*4]; +////try (Reader reader = new FileReader(fileLarge)) { +//// for (; reader.read(arr) != -1; ) { +//// sb.append(arr); +//// } +////} +////strLarge = sb.toString(); + +// @Benchmark +// public int str_readChars(Blackhole hole) throws IOException +// { +// try (Reader reader = new StringReader(strLarge)) +// { +// return readChars(reader); +// } +// } +// +// @Benchmark +// public int str_readLinesAndChars() throws IOException, InterruptedException { +// try (Reader reader = new StringReader(strLarge)) +// { +// return readLinesAndChars(reader); +// } +// } +// +// +// @Benchmark +// public int str_readCharsArrayed() throws IOException, InterruptedException { +// try (Reader reader = new StringReader(strLarge)) +// { +// return readCharsArrayed(reader); +// } +// } + + public static StringBuilder readChars(Reader r) throws IOException + { + StringBuilder sb = new StringBuilder(); + for (int ch; (ch = r.read()) != -1; ) { + if (ch > 31) + sb.append((char) ch); + } + + return sb; + } + + public static StringBuilder readLinesAndChars(Reader r) throws IOException + { + StringBuilder sb = new StringBuilder(); + BufferedReader reader = new BufferedReader(r); + + for (String line; (line = reader.readLine()) != null; ) { + for (int i = 0, len = line.length(); i < len; i++) + { + char ch = line.charAt(i); + if (ch > 31) + sb.append(ch); + } + } + + reader.close(); + return sb; + } + + public static StringBuilder readCharsArrayed(Reader r) throws IOException + { + StringBuilder sb = new StringBuilder(); + char[] arr = new char[256]; + + for (int charsRead; (charsRead = r.read(arr)) != -1; ) { + for (int i = 0; i < charsRead; i++) { + if (arr[i] > 31) + sb.append(arr[i]); + } + } + + return sb; + } + + public static void main(String[] args) throws Exception + { +// org.openjdk.jmh.Main.main(args); + + OptionsBuilder ob = new OptionsBuilder(); + ob.include(StandardBenchmark.class.getSimpleName()); +// ob.jvm(System.getProperty("user.home") + "\\.sdkman\\candidates\\java\\17.0.12-graal\\bin\\java.exe"); + +// ob.addProfiler(org.openjdk.jmh.profile.StackProfiler.class); +// ob.addProfiler(org.openjdk.jmh.profile.JavaFlightRecorderProfiler.class, "dir=./jfr_out"); + +// ob.result("src/tests/n/benchmarks/bench.scsv"); +// ob.resultFormat(ResultFormatType.SCSV); + + new Runner(ob).run(); + + System.out.println("Cached - 1.3.8"); + } +} \ No newline at end of file diff --git a/src/tests/n/benchmarks/Testing.java b/src/tests/n/benchmarks/Testing.java new file mode 100644 index 0000000..2b8d531 --- /dev/null +++ b/src/tests/n/benchmarks/Testing.java @@ -0,0 +1,59 @@ +package tests.n.benchmarks; + +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; + +import org.ugp.serialx.GenericScope; +import org.ugp.serialx.Utils; +import org.ugp.serialx.json.JsonSerializer; +import org.ugp.serialx.juss.converters.OperationGroups; +import org.ugp.serialx.juss.converters.VariableConverter; + +import examples.implementations.GeneralExample; + +/** + * Testing random algorithms... + */ +public class Testing { + + public static void main(String[] args) throws Exception { + + System.out.println(Arrays.asList(Utils.splitValues("123=123 == 55 =2=", "123=123 == 55 =2=".indexOf('='), 0, 1, new char[0], '='))); + System.out.println(Arrays.asList(Utils.splitValues("==123=123 == \"55\" = 4", 0, 0, 1, new char[0], '='))); + System.out.println(Arrays.asList(Utils.splitValues("=9", 0, 0, 0, new char[0], '='))); + System.out.println(Arrays.asList(Utils.splitValues("===98==9", 0, 0, 1, new char[0], '='))); + System.out.println(Arrays.asList(Utils.splitValues("10 98", 0, 0, 2, new char[0], ' '))); + + String str = "srlxVer1 = srlxVer2 = $dependencies.something.dataStorage.serialx.version"; + System.out.println(Arrays.asList(Utils.splitValues(str, VariableConverter.isVarAssignment(str), 0, 1, new char[0], '='))); + System.out.println(Utils.showPosInString("abc", 1)); + + System.out.println(1 +-6 / -2*(2+1)%- 100 + 1); + + char mark = (char) new OperationGroups().hashCode(); + System.out.println(OperationGroups.isGroupMark(new StringBuilder().append(mark--).append(21).append(mark), ++mark)); + + str = "jjiij {ha -> asd } \"hchaha\" a->b\" aaa bbb ha {}"; + System.err.println(Utils.showPosInString(str, Utils.indexOfNotInObj(str, 0, str.length(), -1, true, "->"))); + +// new JsonSerializer(new Object[] {1,2,3}, new HashMap<>(), GenericScope.mapKvArray(new HashMap<>(), "hi", 123), null, new ArrayList<>()).SerializeTo(new File("src/tests/n/benchmarks/test.json")); + +// JussSerializer.JUSS_PARSERS.get(ObjectConverter.class).setAllowStaticMemberInvocation(true); +// +// File file = new File("src/examples/implementations/test.juss"); +// +// JussSerializer deserializer = new JussSerializer(); +// deserializer.LoadFrom(file); +// +// System.out.println(deserializer); +// System.out.println(deserializer.get(new String[] { "kkt", "a" })); +// +// for (int i = 0; i < 12; i++) { +// +// System.out.println(deserializer.getParent(i)); +// } + + } +}