diff --git a/CMakeLists.txt b/CMakeLists.txt index fc4ed65b3..6dc32fc74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,8 +82,6 @@ set(AVX_FLAG "${AVX_FLAG}" CACHE INTERNAL "For the CPU flag selection.") target_compile_options( "${PROJECT_NAME}" INTERFACE - "$<$:$<$:/fsanitize=address>>" - "$<$:/MP${THREAD_COUNT}>" "${AVX_FLAG}" ) diff --git a/DiscordData.json b/DiscordData.json new file mode 100644 index 000000000..79c361f3f --- /dev/null +++ b/DiscordData.json @@ -0,0 +1,9879 @@ +{ + "t": "GUILD_CREATE", + "s": 6, + "op": 0, + "d": { + "joined_at": "2023-09-04T03:58:10.388000+00:00", + "afk_timeout": 3600, + "voice_states": [], + "afk_channel_id": null, + "latest_onboarding_question_id": "1131853763506880522", + "max_video_channel_users": 25, + "incidents_data": null, + "owner_id": "419757783068704790", + "explicit_content_filter": 2, + "safety_alerts_channel_id": null, + "nsfw_level": 0, + "system_channel_id": "1169442658683453470", + "id": "1131853763506880522", + "default_message_notifications": 1, + "lazy": true, + "home_header": null, + "soundboard_sounds": [ + { + "volume": 1.0, + "user_id": "787115161021972521", + "sound_id": "1147626231681007676", + "name": "hodr", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1146955740007911565", + "available": true + }, + { + "volume": 1.0, + "user_id": "787115161021972521", + "sound_id": "1153525919328247838", + "name": "coderbiggie", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1146955737436782632", + "available": true + }, + { + "volume": 1.0, + "user_id": "787115161021972521", + "sound_id": "1153932000818888774", + "name": "coder n", + "guild_id": "1131853763506880522", + "emoji_name": "≡ƒÑ╕", + "emoji_id": null, + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1154254137295388763", + "name": "Totalus-Kanye", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1150063091061641246", + "available": true + }, + { + "volume": 0.9029520750045776, + "user_id": "787115161021972521", + "sound_id": "1154256612714876989", + "name": "45", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1146955732084850748", + "available": true + }, + { + "volume": 1.0, + "user_id": "787115161021972521", + "sound_id": "1154268811030171709", + "name": "holo", + "guild_id": "1131853763506880522", + "emoji_name": "≡ƒÿà", + "emoji_id": null, + "available": true + }, + { + "volume": 0.8108900785446167, + "user_id": "787115161021972521", + "sound_id": "1155673147593474058", + "name": "packnabowl", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1151562622852935860", + "available": true + }, + { + "volume": 1.0, + "user_id": "787115161021972521", + "sound_id": "1155695858889801791", + "name": "slavery", + "guild_id": "1131853763506880522", + "emoji_name": "≡ƒ½ú", + "emoji_id": null, + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1155940875260665868", + "name": "Johnny-Somalia-Embassy6", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1132146663729926275", + "available": true + }, + { + "volume": 1.0, + "user_id": "787115161021972521", + "sound_id": "1157756897953329253", + "name": "coder kiss", + "guild_id": "1131853763506880522", + "emoji_name": "≡ƒÿì", + "emoji_id": null, + "available": true + }, + { + "volume": 0.5324891209602356, + "user_id": "424756951680024576", + "sound_id": "1161836205487439904", + "name": "superfly-sinatra3", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1146955732084850748", + "available": true + }, + { + "volume": 0.42700743675231934, + "user_id": "424756951680024576", + "sound_id": "1161851653956313169", + "name": "superfly-sinatra4", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1146955732084850748", + "available": true + }, + { + "volume": 0.42857545614242554, + "user_id": "424756951680024576", + "sound_id": "1161853056120541277", + "name": "superfly-sinatra5", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1146955732084850748", + "available": true + }, + { + "volume": 0.6595484614372253, + "user_id": "424756951680024576", + "sound_id": "1166564443036074015", + "name": "superfly-sinatra8", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1146955732084850748", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1180661413178515556", + "name": "hodor-bad-thing2", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1180673911193620531", + "name": "hodor-bad-thing3", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1180696295783026759", + "name": "Desk-Wild", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1180696698650120232", + "name": "Desk-Wild-Time", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1180699260791033887", + "name": "Belushi-Gold-Medal", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1180702568205258843", + "name": "Belushi-Kanye", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1182148407981244536", + "name": "Totalus-Wonderpets", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1182500595727347732", + "name": "Hodor-Hit-Em-Up", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1182501276668407989", + "name": "Hodor-Hit-Em-Up2", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + }, + { + "volume": 1.0, + "user_id": "424756951680024576", + "sound_id": "1182501749806878750", + "name": "Hodor-Hit-Em-Up3", + "guild_id": "1131853763506880522", + "emoji_name": null, + "emoji_id": "1155577203409572001", + "available": true + } + ], + "stage_instances": [], + "name": "The Ole Boys of Wallstreet", + "guild_scheduled_events": [], + "region": "deprecated", + "threads": [ + { + "type": 11, + "total_message_sent": 2, + "thread_metadata": { + "locked": false, + "invitable": true, + "create_timestamp": "2023-11-13T07:09:51.338000+00:00", + "auto_archive_duration": 10080, + "archived": false, + "archive_timestamp": "2023-11-13T07:09:51.338000+00:00" + }, + "rate_limit_per_user": 0, + "parent_id": "1169439664881541160", + "owner_id": "995763976656924733", + "name": "REAL?", + "message_count": 2, + "member_count": 2, + "last_message_id": "1173939398480506900", + "id": "1173506561293946941", + "guild_id": "1131853763506880522", + "flags": 0 + }, + { + "type": 11, + "total_message_sent": 4, + "thread_metadata": { + "locked": false, + "invitable": true, + "create_timestamp": "2023-11-14T21:08:35.482000+00:00", + "auto_archive_duration": 4320, + "archived": false, + "archive_timestamp": "2023-11-14T21:08:35.482000+00:00" + }, + "rate_limit_per_user": 0, + "parent_id": "1169440648273875054", + "owner_id": "995763976656924733", + "name": "Hey sexy", + "message_count": 4, + "member_count": 2, + "last_message_id": "1174253960052342786", + "id": "1173793174142079006", + "guild_id": "1131853763506880522", + "flags": 0 + } + ], + "channels": [ + { + "version": 1701741227829, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 16, + "permission_overwrites": [], + "parent_id": "1171888463751172228", + "nsfw": false, + "name": "suepaphly", + "last_message_id": "1182558996708720742", + "id": "1181411109551485018", + "icon_emoji": { + "name": "≡ƒîÉ", + "id": null + }, + "flags": 0 + }, + { + "version": 1701741227867, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 18, + "permission_overwrites": [ + { + "type": 0, + "id": "1150819267453931622", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "1024", + "allow": "0" + } + ], + "parent_id": "1171507375119814677", + "nsfw": false, + "name": "weeb", + "last_message_id": "1182463593204166666", + "id": "1169841302884585533", + "icon_emoji": { + "name": "≡ƒî╕", + "id": null + }, + "flags": 0 + }, + { + "version": 1699498219720, + "type": 0, + "topic": null, + "rate_limit_per_user": 0, + "position": 15, + "permission_overwrites": [], + "parent_id": "1171888463751172228", + "name": "totalus", + "last_message_id": "1182177030230528030", + "id": "1171888499067211816", + "icon_emoji": { + "name": "≡ƒç╣≡ƒç┤", + "id": null + }, + "flags": 0 + }, + { + "version": 1701191181439, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 9, + "permission_overwrites": [], + "parent_id": "1169429347069870232", + "nsfw": false, + "name": "crypto", + "last_pin_timestamp": "2023-11-02T07:52:57+00:00", + "last_message_id": "1182086505452281937", + "id": "1169544290364563496", + "icon_emoji": { + "name": "≡ƒÆ░", + "id": null + }, + "flags": 0 + }, + { + "version": 1701739139020, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 5, + "permission_overwrites": [], + "parent_id": "1169429347069870232", + "nsfw": false, + "name": "fine-dining", + "last_message_id": "1182086615213015170", + "id": "1169440127395836054", + "icon_emoji": { + "name": "≡ƒì╜∩╕Å", + "id": null + }, + "flags": 0 + }, + { + "version": 1700909264808, + "user_limit": 0, + "type": 2, + "topic": null, + "theme_color": null, + "status": null, + "rtc_region": null, + "rate_limit_per_user": 0, + "position": 2, + "permission_overwrites": [], + "parent_id": "1169409823041925260", + "nsfw": false, + "name": "Zoomers On Top", + "last_message_id": null, + "id": "1171996582376382474", + "icon_emoji": { + "name": "≡ƒææ", + "id": null + }, + "flags": 0, + "bitrate": 64000 + }, + { + "version": 1701741227887, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 19, + "permission_overwrites": [ + { + "type": 0, + "id": "1132495232991244298", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1136839878127128668", + "deny": "0", + "allow": "3072" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "1024", + "allow": "0" + } + ], + "parent_id": "1171507375119814677", + "nsfw": false, + "name": "totaluses-approval", + "last_pin_timestamp": "2023-11-19T07:42:38+00:00", + "last_message_id": "1182718332936405134", + "id": "1168677148245110824", + "icon_emoji": { + "name": "≡ƒôê", + "id": null + }, + "flags": 0 + }, + { + "version": 1701751874606, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 13, + "permission_overwrites": [], + "parent_id": "1169409823041925260", + "nsfw": false, + "name": "vc-chat", + "last_pin_timestamp": "2023-12-10T16:39:09+00:00", + "last_message_id": "1183518964995854408", + "id": "1169429230233342012", + "icon_emoji": { + "name": "≡ƒÄÖ∩╕Å", + "id": null + }, + "flags": 0 + }, + { + "version": 1698890466674, + "type": 4, + "position": 0, + "permission_overwrites": [], + "name": "Text Channels", + "id": "1169429347069870232", + "flags": 0 + }, + { + "version": 1701739758388, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 11, + "permission_overwrites": [ + { + "type": 0, + "id": "1165360991710752979", + "deny": "0", + "allow": "2048" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "2048", + "allow": "0" + } + ], + "parent_id": "1169429347069870232", + "nsfw": false, + "name": "zomboid", + "last_message_id": "1182086447352787127", + "id": "1169830775751970836", + "icon_emoji": { + "name": "≡ƒºƒ", + "id": null + }, + "flags": 0 + }, + { + "version": 1701191181416, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 8, + "permission_overwrites": [], + "parent_id": "1169429347069870232", + "nsfw": false, + "name": "memes", + "last_message_id": "1183221533360001114", + "id": "1169503128656293910", + "icon_emoji": { + "name": "≡ƒñú", + "id": null + }, + "flags": 0 + }, + { + "version": 1699719005193, + "user_limit": 0, + "type": 2, + "topic": null, + "status": null, + "rtc_region": null, + "rate_limit_per_user": 0, + "position": 5, + "permission_overwrites": [], + "parent_id": "1169409823041925260", + "name": "AFK", + "last_message_id": null, + "id": "1169434569930444872", + "icon_emoji": { + "name": "≡ƒÄ¡", + "id": null + }, + "flags": 0, + "bitrate": 64000 + }, + { + "version": 1698979700439, + "type": 0, + "topic": null, + "rate_limit_per_user": 0, + "position": 4, + "permission_overwrites": [], + "parent_id": "1169429347069870232", + "name": "main", + "last_message_id": "1182551163866976366", + "id": "1169440648273875054", + "icon_emoji": { + "name": "≡ƒîÉ", + "id": null + }, + "flags": 0 + }, + { + "version": 1701741227854, + "type": 0, + "topic": null, + "theme_color": 15158332, + "rate_limit_per_user": 0, + "position": 17, + "permission_overwrites": [ + { + "type": 0, + "id": "1131853763506880522", + "deny": "0", + "allow": "0" + } + ], + "parent_id": "1171507375119814677", + "nsfw": false, + "name": "learn-and-speak-english", + "last_message_id": "1182086737686695997", + "id": "1171262043375009842", + "icon_emoji": { + "name": "≡ƒç║≡ƒç╕", + "id": null + }, + "flags": 0 + }, + { + "version": 1701573217400, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 2, + "permission_overwrites": [ + { + "type": 0, + "id": "1145791399162294334", + "deny": "0", + "allow": "0" + }, + { + "type": 0, + "id": "1131855863930425394", + "deny": "0", + "allow": "0" + } + ], + "parent_id": null, + "nsfw": false, + "name": "song-of-the-day", + "last_message_id": "1183420867724709888", + "id": "1169439698314342470", + "icon_emoji": { + "name": "≡ƒÄ╡", + "id": null + }, + "flags": 0 + }, + { + "version": 1701191187941, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 1, + "permission_overwrites": [ + { + "type": 0, + "id": "1136839878127128668", + "deny": "0", + "allow": "2048" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "71453223614464", + "allow": "262208" + } + ], + "parent_id": null, + "nsfw": false, + "name": "announcements", + "last_message_id": "1169740026167443498", + "id": "1169430670230163496", + "icon_emoji": { + "name": "≡ƒôú", + "id": null + }, + "flags": 0 + }, + { + "version": 1701103396709, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 7, + "permission_overwrites": [ + { + "type": 0, + "id": "1169450276873314374", + "deny": "0", + "allow": "70506451881041" + } + ], + "parent_id": "1169429347069870232", + "nsfw": false, + "name": "trading", + "last_message_id": "1182087111751512074", + "id": "1169440416886706226", + "icon_emoji": { + "name": "≡ƒÆ╣", + "id": null + }, + "flags": 0 + }, + { + "version": 1700909264778, + "user_limit": 0, + "type": 2, + "topic": null, + "theme_color": null, + "status": null, + "rtc_region": null, + "rate_limit_per_user": 0, + "position": 1, + "permission_overwrites": [ + { + "type": 0, + "id": "1144017607444402276", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1136839878127128668", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "1024", + "allow": "0" + }, + { + "type": 0, + "id": "1136878100718829589", + "deny": "0", + "allow": "1024" + } + ], + "parent_id": "1169409823041925260", + "nsfw": false, + "name": "Extra Room", + "last_message_id": null, + "id": "1169387170579095592", + "icon_emoji": { + "name": "≡ƒæì", + "id": null + }, + "flags": 0, + "bitrate": 64000 + }, + { + "version": 1699539649751, + "type": 0, + "topic": null, + "rate_limit_per_user": 0, + "position": 10, + "permission_overwrites": [], + "parent_id": "1169429347069870232", + "name": "ai-art", + "last_message_id": "1183485358910996552", + "id": "1169466057203916800", + "icon_emoji": { + "name": "≡ƒÄ¿", + "id": null + }, + "flags": 0 + }, + { + "version": 1699223433249, + "type": 4, + "position": 1, + "permission_overwrites": [], + "name": "VC", + "id": "1169409823041925260", + "flags": 0 + }, + { + "version": 1701742493407, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 12, + "permission_overwrites": [], + "parent_id": "1169409823041925260", + "nsfw": true, + "name": "nsfw", + "last_message_id": "1183156701982113802", + "id": "1169439664881541160", + "icon_emoji": { + "name": "≡ƒö₧", + "id": null + }, + "flags": 0, + "default_auto_archive_duration": 10080 + }, + { + "version": 1700909266800, + "user_limit": 0, + "type": 2, + "topic": null, + "theme_color": null, + "status": null, + "rtc_region": null, + "rate_limit_per_user": 0, + "position": 4, + "permission_overwrites": [ + { + "type": 0, + "id": "1131855863930425394", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "1049600", + "allow": "0" + }, + { + "type": 0, + "id": "1132495232991244298", + "deny": "0", + "allow": "1049600" + } + ], + "parent_id": "1169409823041925260", + "nsfw": false, + "name": "≡ƒªÖAlpacas Trading Family", + "last_message_id": "1175654785563758592", + "id": "1169833450094743573", + "icon_emoji": { + "name": "≡ƒªÖ", + "id": null + }, + "flags": 0, + "bitrate": 64000 + }, + { + "version": 1701739139036, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 6, + "permission_overwrites": [], + "parent_id": "1169429347069870232", + "nsfw": false, + "name": "ai-prompts", + "last_message_id": "1182086588012953630", + "id": "1169830997609697380", + "icon_emoji": { + "name": "≡ƒñû", + "id": null + }, + "flags": 0 + }, + { + "version": 1700741124671, + "user_limit": 0, + "type": 2, + "topic": null, + "theme_color": null, + "status": null, + "rtc_region": null, + "rate_limit_per_user": 0, + "position": 0, + "permission_overwrites": [], + "parent_id": "1169409823041925260", + "nsfw": false, + "name": "The Free Market", + "last_message_id": "1183448457936109668", + "id": "1169831582157258904", + "icon_emoji": { + "name": "≡ƒÅ¬", + "id": null + }, + "flags": 0, + "bitrate": 64000 + }, + { + "version": 1701573217416, + "type": 15, + "topic": null, + "theme_color": null, + "template": "", + "rate_limit_per_user": 0, + "position": 3, + "permission_overwrites": [ + { + "type": 0, + "id": "1132495232991244298", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1132022472737292329", + "deny": "0", + "allow": "11264" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "3072", + "allow": "0" + }, + { + "type": 0, + "id": "1144017607444402276", + "deny": "0", + "allow": "3072" + } + ], + "parent_id": null, + "nsfw": false, + "name": "advanced-ai-assets", + "last_message_id": "1165121861663867001", + "id": "1153899109225345094", + "icon_emoji": { + "name": "≡ƒö¼", + "id": null + }, + "flags": 0, + "default_sort_order": null, + "default_reaction_emoji": null, + "default_forum_layout": 0, + "available_tags": [] + }, + { + "version": 1699470386858, + "type": 4, + "position": 3, + "permission_overwrites": [], + "name": "The Learning Server", + "id": "1171507375119814677", + "flags": 0 + }, + { + "version": 1701393640230, + "user_limit": 0, + "type": 2, + "topic": null, + "theme_color": null, + "status": null, + "rtc_region": null, + "rate_limit_per_user": 0, + "position": 3, + "permission_overwrites": [], + "parent_id": "1169409823041925260", + "nsfw": false, + "name": "poor vc", + "last_message_id": "1180060265279127582", + "id": "1172257938983891065", + "icon_emoji": { + "name": "≡ƒÄÖ∩╕Å", + "id": null + }, + "flags": 0, + "bitrate": 21125 + }, + { + "version": 1699470386876, + "type": 4, + "position": 4, + "permission_overwrites": [ + { + "type": 0, + "id": "1131853763506880522", + "deny": "1024", + "allow": "0" + } + ], + "name": "server-shit", + "id": "1151564736069115965", + "flags": 0 + }, + { + "version": 1701191187927, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 0, + "permission_overwrites": [ + { + "type": 0, + "id": "1131853763506880522", + "deny": "2048", + "allow": "0" + } + ], + "parent_id": null, + "nsfw": false, + "name": "start-here", + "last_message_id": "1181736023949058199", + "id": "1169830384868012103", + "icon_emoji": { + "name": "≡ƒÜÇ", + "id": null + }, + "flags": 0 + }, + { + "version": 1701751874618, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 14, + "permission_overwrites": [], + "parent_id": "1169409823041925260", + "nsfw": true, + "name": "bot-spam", + "last_message_id": "1183495037632393387", + "id": "1169456058989805669", + "icon_emoji": { + "name": "≡ƒñû", + "id": null + }, + "flags": 0 + }, + { + "version": 1701741227908, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 20, + "permission_overwrites": [ + { + "type": 0, + "id": "1144017607444402276", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1136839878127128668", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "1024", + "allow": "0" + }, + { + "type": 0, + "id": "1154965536464179290", + "deny": "0", + "allow": "1024" + } + ], + "parent_id": "1151564736069115965", + "nsfw": false, + "name": "invite-tackling", + "last_message_id": "1183228457509986314", + "id": "1169442658683453470", + "icon_emoji": { + "name": "≡ƒÅê", + "id": null + }, + "flags": 0 + }, + { + "version": 1699719005276, + "user_limit": 0, + "type": 2, + "topic": null, + "status": null, + "rtc_region": null, + "rate_limit_per_user": 0, + "position": 6, + "permission_overwrites": [ + { + "type": 0, + "id": "1132495232991244298", + "deny": "339202321560337", + "allow": "137440382016" + }, + { + "type": 0, + "id": "1171877369666076722", + "deny": "0", + "allow": "2097152" + } + ], + "parent_id": "1171507375119814677", + "name": "Totalus's Approval", + "last_message_id": "1175253486720536686", + "id": "1171877661790973992", + "icon_emoji": { + "name": "≡ƒæì", + "id": null + }, + "flags": 0, + "bitrate": 64000 + }, + { + "version": 1699470386838, + "type": 4, + "position": 2, + "permission_overwrites": [], + "name": "User Portraits", + "id": "1171888463751172228", + "flags": 0 + }, + { + "version": 1701741227919, + "type": 0, + "topic": null, + "theme_color": null, + "rate_limit_per_user": 0, + "position": 21, + "permission_overwrites": [ + { + "type": 0, + "id": "1136839878127128668", + "deny": "0", + "allow": "1024" + }, + { + "type": 0, + "id": "1131853763506880522", + "deny": "1024", + "allow": "0" + }, + { + "type": 0, + "id": "1154965536464179290", + "deny": "0", + "allow": "1024" + } + ], + "parent_id": "1151564736069115965", + "nsfw": false, + "name": "mod-chat", + "last_message_id": "1179623227601993758", + "id": "1169441906917376020", + "icon_emoji": { + "name": "≡ƒ¢í∩╕Å", + "id": null + }, + "flags": 0 + } + ], + "mfa_level": 0, + "preferred_locale": "en-US", + "embedded_activities": [], + "application_command_counts": { + "3": 11, + "2": 7, + "1": 391 + }, + "description": null, + "vanity_url_code": null, + "premium_progress_bar_enabled": false, + "rules_channel_id": null, + "inventory_settings": null, + "premium_subscription_count": 3, + "presences": [ + { + "user": { "id": "1179873808795049990" }, + "status": "dnd", + "client_status": { "web": "dnd" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "193017815232413697" }, + "status": "idle", + "client_status": { + "mobile": "idle", + "desktop": "idle" + }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "247121074393841664" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "341659789828423709" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "FAITH = the difference", + "name": "Custom Status", + "id": "custom", + "emoji": { + "name": "AU_twinklysparkles", + "id": "960199508283756555", + "animated": true + }, + "created_at": 1702108882261 + } + ] + }, + { + "user": { "id": "480225105616568331" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "621531622235308033" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "431013987375906816" }, + "status": "online", + "client_status": { + "mobile": "online", + "desktop": "online" + }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "Leaving Dec 26th", + "name": "Custom Status", + "id": "custom", + "created_at": 1702246305094 + } + ] + }, + { + "user": { "id": "692952507990933514" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "836385897372581910" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 3, + "name": "475.06 Γ¼ê 1.95%", + "id": "ec0b28a579ecb4bd", + "created_at": 1702249417029 + } + ] + }, + { + "user": { "id": "419757783068704790" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "This user has been profiled as sharing anti-government memes and other content.", + "name": "Custom Status", + "id": "custom", + "emoji": { "name": "ΓÜá∩╕Å" }, + "created_at": 1702248371695 + } + ] + }, + { + "user": { "id": "223984406581346304" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1142732033978814564" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "209157594575536129" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1025376302351523930" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "Judge everyday by the seeds you plant, not by the fruits you reap.", + "name": "Custom Status", + "id": "custom", + "created_at": 1702234136084 + } + ] + }, + { + "user": { "id": "881233615801974856" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1160506752316489758" }, + "status": "online", + "client_status": { + "mobile": "idle", + "desktop": "online" + }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "451379187031343104" }, + "status": "idle", + "client_status": { "web": "idle" }, + "broadcast": null, + "activities": [ + { + "type": 2, + "name": "!help | /help", + "id": "ec0b28a579ecb4bd", + "created_at": 1702249361318 + } + ] + }, + { + "user": { "id": "308150161966891009" }, + "status": "dnd", + "client_status": { + "mobile": "dnd", + "desktop": "dnd" + }, + "broadcast": null, + "activities": [ + { + "type": 0, + "timestamps": { "start": 1702248203463 }, + "name": "World of Warcraft Classic", + "id": "c59c0d49a0b79785", + "created_at": 1702248202843, + "application_id": "615752773690064908" + } + ] + }, + { + "user": { "id": "1059302859088347189" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "740746194829180958" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "805235025871241226" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1174224660968263692" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1121015033472745534" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1048074759918858281" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "timestamps": { "start": 1702231700710 }, + "name": "Counter-Strike 2", + "id": "fe9261765423ddd9", + "created_at": 1702231699429, + "application_id": "1158877933042143272" + } + ] + }, + { + "user": { "id": "321178412012011523" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1030016136735100928" }, + "status": "dnd", + "client_status": { "desktop": "dnd" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "806569145184550922" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 3, + "name": "195.71 Γ¼ê 0.74%", + "id": "ec0b28a579ecb4bd", + "created_at": 1702249421928 + } + ] + }, + { + "user": { "id": "1056030770814263326" }, + "status": "online", + "client_status": { "mobile": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "207533376314277888" }, + "status": "dnd", + "client_status": { "desktop": "dnd" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "Hyv├ñ├ñ Itsen├ñisyysp├ñiv├ñ├ñ!", + "name": "Custom Status", + "id": "custom", + "emoji": { "name": "≡ƒç½≡ƒç«" }, + "created_at": 1702245142297 + } + ] + }, + { + "user": { "id": "412347257233604609" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 2, + "name": "m!help", + "id": "ec0b28a579ecb4bd", + "created_at": 1702232444275 + } + ] + }, + { + "user": { "id": "1161728107477205073" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1085588193438617630" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1137467117336268870" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "949479338275913799" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "Reply @Mention | Generated 9,828,155 images", + "name": "~", + "id": "ec0b28a579ecb4bd", + "created_at": 1701495470809 + } + ] + }, + { + "user": { "id": "365567541432811520" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "timestamps": { "start": 1702236242274 }, + "name": "Age of Empires IV", + "id": "3d756a1650597081", + "created_at": 1702236242913, + "application_id": "1129504181414273136" + } + ] + }, + { + "user": { "id": "811418568846737500" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 3, + "name": "460.20 Γ¼ê 0.43%", + "id": "ec0b28a579ecb4bd", + "created_at": 1702249417002 + } + ] + }, + { + "user": { "id": "1142160480195059712" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "605700934693289985" }, + "status": "dnd", + "client_status": { + "web": "dnd", + "desktop": "dnd" + }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1132282579702263811" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "150826437899714561" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "The Old Goat", + "name": "Custom Status", + "id": "custom", + "created_at": 1702240420627 + } + ] + }, + { + "user": { "id": "890259418636255232" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "92834990248722432" }, + "status": "dnd", + "client_status": { + "mobile": "dnd", + "desktop": "dnd" + }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "155149108183695360" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "name": "dyno.gg | ?help", + "id": "ec0b28a579ecb4bd", + "created_at": 1701964900731 + } + ] + }, + { + "user": { "id": "424368845621428234" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "Baja Blast my Brains Out", + "name": "Custom Status", + "id": "custom", + "created_at": 1702246387716 + } + ] + }, + { + "user": { "id": "1142166864437452801" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "enter /help for a list of my commands!", + "name": "enter /help for a list of my commands!", + "id": "ec0b28a579ecb4bd", + "created_at": 1702246048480 + } + ] + }, + { + "user": { "id": "117672888089313284" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "timestamps": { "start": 1702228841000 }, + "state": "In Menu", + "name": "RuneLite", + "id": "875ff14d93fff58", + "created_at": 1702249366356, + "assets": { + "large_text": "RuneLite v1.10.17.1", + "large_image": "409453539270590464" + }, + "application_id": "409416265891971072" + } + ] + }, + { + "user": { "id": "1119845619771650049" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "Searching for Dino...", + "name": "Custom Status", + "id": "custom", + "created_at": 1702232354771 + } + ] + }, + { + "user": { "id": "497321666372960268" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "411916947773587456" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 2, + "name": "m!help", + "id": "ec0b28a579ecb4bd", + "created_at": 1702232424503 + } + ] + }, + { + "user": { "id": "671176256313622548" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 2, + "name": "/help", + "id": "ec0b28a579ecb4bd", + "created_at": 1702230398829 + } + ] + }, + { + "user": { "id": "1152368395354918922" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "401328409499664394" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 3, + "name": "www.alpha.bot", + "id": "ec0b28a579ecb4bd", + "created_at": 1702206286530 + } + ] + }, + { + "user": { "id": "269688928804667394" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "98587545511669760" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "\"Royal Jester\"", + "name": "Custom Status", + "id": "custom", + "created_at": 1702002755109 + } + ] + }, + { + "user": { "id": "342945406914789376" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "407971046277382144" }, + "status": "idle", + "client_status": { "mobile": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "228537642583588864" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "vexera.io | +help", + "name": "Custom Status", + "id": "ec0b28a579ecb4bd", + "created_at": 1699473714741 + } + ] + }, + { + "user": { "id": "310140268307283978" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "700411523264282685" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "943308401411260436" }, + "status": "dnd", + "client_status": { "mobile": "dnd" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "748389195344773211" }, + "status": "online", + "client_status": { "mobile": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "1142167563858616410" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "enter /help for a list of my commands!", + "name": "enter /help for a list of my commands!", + "id": "ec0b28a579ecb4bd", + "created_at": 1702243423178 + } + ] + }, + { + "user": { "id": "523319660112773122" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "Skinhead Jungle Hours", + "name": "Custom Status", + "id": "custom", + "emoji": { + "name": "sssymbol", + "id": "1152244084497465374", + "animated": false + }, + "created_at": 1702214054908 + }, + { + "type": 2, + "timestamps": { + "start": 1702249181208, + "end": 1702249478634 + }, + "sync_id": "1pcBtixsF2z5AzvLKx7INI", + "state": "UGK", + "session_id": "b35aa65796de39ad389e33088c4a2164", + "party": { "id": "spotify:523319660112773122" }, + "name": "Spotify", + "id": "spotify:1", + "flags": 48, + "details": "Gravy", + "created_at": 1702249189563, + "assets": { + "large_text": "UGK (Underground Kingz)", + "large_image": "spotify:ab67616d0000b2730ecd0dec7edf87dab40d19b7" + } + } + ] + }, + { + "user": { "id": "321832087407689729" }, + "status": "dnd", + "client_status": { "desktop": "dnd" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "407337052099706891" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "808723743069306882" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 3, + "name": "243.84 Γ¼ê 0.49%", + "id": "ec0b28a579ecb4bd", + "created_at": 1702249421907 + } + ] + }, + { + "user": { "id": "285219649921220608" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "235148962103951360" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "name": "/help | carl.gg", + "id": "ec0b28a579ecb4bd", + "created_at": 1702231413310 + } + ] + }, + { + "user": { "id": "335094779207483392" }, + "status": "online", + "client_status": { "mobile": "online" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "timestamps": { "start": 1702247660173 }, + "platform": "ps5", + "name": "Terraria", + "id": "9f026074cd56a8ed", + "flags": 0, + "created_at": 1702247660173, + "assets": { "small_image": "mp:external/ypJGjEkDrgg-cZEzaSaH4biibHXObUuFboJg9_Z_7HU/https/image.api.playstation.com/gs2-sec/appkgo/prod/CUSA00737_00/7/i_db5a9a0c22390a8d68b215b244fb5ddf2332f2dfed152092533fc4a30c09452b/i/icon0.png" } + } + ] + }, + { + "user": { "id": "405189268399587339" }, + "status": "online", + "client_status": { + "mobile": "online", + "desktop": "idle" + }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "567463925801811969" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "timestamps": { "start": 1702249346361 }, + "name": "SteamVR", + "id": "2f6b02a624c08f40", + "created_at": 1702249346204 + } + ] + }, + { + "user": { "id": "173294645730607115" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "868296331234521099" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 0, + "name": "your sound files", + "id": "ec0b28a579ecb4bd", + "created_at": 1702248655025 + } + ] + }, + { + "user": { "id": "159985870458322944" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "279722369260453888" }, + "status": "idle", + "client_status": { "web": "idle" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "995763976656924733" }, + "status": "online", + "client_status": { "desktop": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "822367483679473675" }, + "status": "idle", + "client_status": { "desktop": "idle" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "SO DONT ASK ME NO QUESTIONS AND I WONT TELL YOU NO LIES", + "name": "Custom Status", + "id": "custom", + "created_at": 1702207648504 + } + ] + }, + { + "user": { "id": "1142733646600614004" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [ + { + "type": 4, + "state": "enter /help for a list of my commands!", + "name": "enter /help for a list of my commands!", + "id": "ec0b28a579ecb4bd", + "created_at": 1702249436069 + } + ] + }, + { + "user": { "id": "936929561302675456" }, + "status": "online", + "client_status": { "web": "online" }, + "broadcast": null, + "activities": [] + }, + { + "user": { "id": "439205512425504771" }, + "status": "online", + "client_status": { "mobile": "online" }, + "broadcast": null, + "activities": [ + { + "type": 3, + "name": "for .", + "id": "ec0b28a579ecb4bd", + "created_at": 1701757988628 + } + ] + } + ], + "verification_level": 1, + "system_channel_flags": 4, + "hub_type": null, + "application_id": null, + "icon": "221fe14b9840d9bed6a8844a5d2608c3", + "splash": null, + "banner": null, + "roles": [ + { + "version": 1701238513698, + "unicode_emoji": null, + "tags": {}, + "position": 18, + "permissions": "0", + "name": "Dumbass Bird Beak Lookin' Bitch", + "mentionable": false, + "managed": false, + "id": "1157914001255178250", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513758, + "unicode_emoji": null, + "tags": {}, + "position": 27, + "permissions": "0", + "name": "Tranny at heart", + "mentionable": false, + "managed": false, + "id": "1154848174251458580", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514063, + "unicode_emoji": null, + "tags": {}, + "position": 98, + "permissions": "0", + "name": "loki's bbc", + "mentionable": false, + "managed": false, + "id": "1152013710374748240", + "icon": null, + "hoist": false, + "flags": 0, + "color": 460294 + }, + { + "version": 1701238513574, + "unicode_emoji": null, + "tags": { "bot_id": "949479338275913799" }, + "position": 5, + "permissions": "274878024704", + "name": "Make it a Quote", + "mentionable": false, + "managed": true, + "id": "1172323415919693868", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513922, + "unicode_emoji": null, + "tags": {}, + "position": 64, + "permissions": "0", + "name": "8 Ball", + "mentionable": false, + "managed": false, + "id": "1150637606183379024", + "icon": null, + "hoist": false, + "flags": 0, + "color": 918789 + }, + { + "version": 1701238514164, + "unicode_emoji": null, + "tags": {}, + "position": 112, + "permissions": "0", + "name": "Real American Hero", + "mentionable": false, + "managed": false, + "id": "1132320097734770748", + "icon": null, + "hoist": false, + "flags": 0, + "color": 2632903 + }, + { + "version": 1701238514000, + "unicode_emoji": null, + "tags": {}, + "position": 86, + "permissions": "0", + "name": "1 Check", + "mentionable": false, + "managed": false, + "id": "1138271856009416804", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513619, + "unicode_emoji": null, + "tags": { "bot_id": "412347257233604609" }, + "position": 11, + "permissions": "8", + "name": "Jockie Music (1)", + "mentionable": false, + "managed": true, + "id": "1167665445801840722", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513706, + "unicode_emoji": null, + "tags": {}, + "position": 19, + "permissions": "0", + "name": "Squirt Instead of Hurt", + "mentionable": false, + "managed": false, + "id": "1157158716785823855", + "icon": null, + "hoist": false, + "flags": 0, + "color": 10181046 + }, + { + "version": 1701238513601, + "unicode_emoji": null, + "tags": { "bot_id": "1148952559562793122" }, + "position": 8, + "permissions": "4331670016", + "name": "dupe", + "mentionable": false, + "managed": true, + "id": "1171262927739818076", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513749, + "unicode_emoji": null, + "tags": {}, + "position": 24, + "permissions": "0", + "name": "50 Suns Worshipper", + "mentionable": false, + "managed": false, + "id": "1154972272294109194", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15524696 + }, + { + "version": 1701238513979, + "unicode_emoji": null, + "tags": {}, + "position": 81, + "permissions": "0", + "name": "6 Checks", + "mentionable": false, + "managed": false, + "id": "1138272100256329788", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514017, + "unicode_emoji": null, + "tags": { "bot_id": "671176256313622548" }, + "position": 90, + "permissions": "519232", + "name": "Tattle", + "mentionable": false, + "managed": true, + "id": "1135769664237088841", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513827, + "unicode_emoji": null, + "tags": {}, + "position": 42, + "permissions": "0", + "name": "English Student", + "mentionable": false, + "managed": false, + "id": "1150604748303646744", + "icon": null, + "hoist": false, + "flags": 0, + "color": 2828933 + }, + { + "version": 1701238513768, + "unicode_emoji": null, + "tags": {}, + "position": 30, + "permissions": "0", + "name": "Omegle", + "mentionable": false, + "managed": false, + "id": "1154509955290894427", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15158332 + }, + { + "version": 1701238514092, + "unicode_emoji": null, + "tags": {}, + "position": 102, + "permissions": "0", + "name": "Verified Euro", + "mentionable": false, + "managed": false, + "id": "1154851589857742898", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15277667 + }, + { + "version": 1701238513799, + "unicode_emoji": null, + "tags": {}, + "position": 37, + "permissions": "0", + "name": "Mountain Climber", + "mentionable": false, + "managed": false, + "id": "1151641053603057664", + "icon": null, + "hoist": false, + "flags": 0, + "color": 1122304 + }, + { + "version": 1701238514229, + "unicode_emoji": null, + "tags": {}, + "position": 126, + "permissions": "418514216611521", + "name": "Server Assistant", + "mentionable": false, + "managed": false, + "id": "1144017607444402276", + "icon": null, + "hoist": false, + "flags": 0, + "color": 1752220 + }, + { + "version": 1701238513867, + "unicode_emoji": null, + "tags": {}, + "position": 51, + "permissions": "0", + "name": "≡ƒìä", + "mentionable": false, + "managed": false, + "id": "1165352625173180516", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514129, + "unicode_emoji": null, + "tags": {}, + "position": 107, + "permissions": "75454089579008", + "name": "Oleboy Guest", + "mentionable": false, + "managed": false, + "id": "1145791399162294334", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15105570 + }, + { + "version": 1701238513970, + "unicode_emoji": null, + "tags": {}, + "position": 78, + "permissions": "0", + "name": "9 Checks", + "mentionable": false, + "managed": false, + "id": "1138272210734284901", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514138, + "unicode_emoji": null, + "tags": {}, + "position": 109, + "permissions": "119814659366593", + "name": "Ole Girl", + "mentionable": false, + "managed": false, + "id": "1133448992827641906", + "icon": null, + "hoist": false, + "flags": 0, + "color": 16712187 + }, + { + "version": 1701238513644, + "unicode_emoji": null, + "tags": {}, + "position": 14, + "permissions": "0", + "name": "Door Dash Thief", + "mentionable": false, + "managed": false, + "id": "1162968001683927121", + "icon": null, + "hoist": false, + "flags": 0, + "color": 3066993 + }, + { + "version": 1701238513812, + "unicode_emoji": null, + "tags": {}, + "position": 39, + "permissions": "0", + "name": "Weeb", + "mentionable": false, + "managed": false, + "id": "1150819267453931622", + "icon": null, + "hoist": false, + "flags": 0, + "color": 7154570 + }, + { + "version": 1701238513902, + "unicode_emoji": null, + "tags": {}, + "position": 58, + "permissions": "0", + "name": "Green Card", + "mentionable": false, + "managed": false, + "id": "1139727644712251534", + "icon": null, + "hoist": false, + "flags": 0, + "color": 177692 + }, + { + "version": 1701238514022, + "unicode_emoji": null, + "tags": {}, + "position": 91, + "permissions": "8", + "name": "Tickers", + "mentionable": false, + "managed": false, + "id": "1132514826179072091", + "icon": null, + "hoist": true, + "flags": 0, + "color": 15105570 + }, + { + "version": 1701238513881, + "unicode_emoji": null, + "tags": {}, + "position": 54, + "permissions": "0", + "name": "Sun Maximalist", + "mentionable": false, + "managed": false, + "id": "1147382626315935826", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15844367 + }, + { + "version": 1701238514189, + "unicode_emoji": null, + "tags": {}, + "position": 117, + "permissions": "0", + "name": "bot", + "mentionable": false, + "managed": false, + "id": "1158137449407598682", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513973, + "unicode_emoji": null, + "tags": {}, + "position": 79, + "permissions": "0", + "name": "8 Checks", + "mentionable": false, + "managed": false, + "id": "1138272169177141329", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513893, + "unicode_emoji": null, + "tags": {}, + "position": 56, + "permissions": "0", + "name": "new role", + "mentionable": false, + "managed": false, + "id": "1147245455256850505", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514218, + "unicode_emoji": null, + "tags": {}, + "position": 122, + "permissions": "256", + "name": "The Engineer", + "mentionable": false, + "managed": false, + "id": "1154591298477625364", + "icon": null, + "hoist": false, + "flags": 0, + "color": 131586 + }, + { + "version": 1701238513626, + "unicode_emoji": null, + "tags": {}, + "position": 13, + "permissions": "0", + "name": "Zomboid", + "mentionable": false, + "managed": false, + "id": "1165360991710752979", + "icon": null, + "hoist": false, + "flags": 0, + "color": 520332 + }, + { + "version": 1701238514153, + "unicode_emoji": null, + "tags": {}, + "position": 111, + "permissions": "119815733104321", + "name": "Ole Boy", + "mentionable": false, + "managed": false, + "id": "1131855863930425394", + "icon": null, + "hoist": true, + "flags": 0, + "color": 15844367 + }, + { + "version": 1701238514220, + "unicode_emoji": null, + "tags": {}, + "position": 123, + "permissions": "0", + "name": "Hall Monitor", + "mentionable": false, + "managed": false, + "id": "1163353762816086016", + "icon": null, + "hoist": false, + "flags": 0, + "color": 33279 + }, + { + "version": 1701238514193, + "unicode_emoji": null, + "tags": { "bot_id": "159985870458322944" }, + "position": 118, + "permissions": "364870364383", + "name": "MEE6", + "mentionable": false, + "managed": true, + "id": "1132513757491372055", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514125, + "unicode_emoji": null, + "tags": {}, + "position": 106, + "permissions": "0", + "name": "The True King Chad", + "mentionable": false, + "managed": false, + "id": "1133964361317240942", + "icon": null, + "hoist": false, + "flags": 0, + "color": 3066993 + }, + { + "version": 1701238513864, + "unicode_emoji": null, + "tags": {}, + "position": 50, + "permissions": "0", + "name": "Air Maximalist", + "mentionable": false, + "managed": false, + "id": "1147401491779424346", + "icon": null, + "hoist": false, + "flags": 0, + "color": 16185078 + }, + { + "version": 1701238513905, + "unicode_emoji": null, + "tags": {}, + "position": 59, + "permissions": "0", + "name": "QDDV", + "mentionable": false, + "managed": false, + "id": "1143056741261656065", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15277667 + }, + { + "version": 1701238513569, + "unicode_emoji": null, + "tags": {}, + "position": 4, + "permissions": "0", + "name": "Penis Tucker", + "mentionable": false, + "managed": false, + "id": "1173489923450470453", + "icon": null, + "hoist": false, + "flags": 0, + "color": 10181046 + }, + { + "version": 1701238513778, + "unicode_emoji": null, + "tags": {}, + "position": 32, + "permissions": "0", + "name": "45", + "mentionable": false, + "managed": false, + "id": "1152426486368845895", + "icon": null, + "hoist": false, + "flags": 0, + "color": 2865452 + }, + { + "version": 1701238513796, + "unicode_emoji": null, + "tags": {}, + "position": 36, + "permissions": "0", + "name": "≡ƒªæ", + "mentionable": false, + "managed": false, + "id": "1165355605033230336", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513871, + "unicode_emoji": null, + "tags": {}, + "position": 52, + "permissions": "0", + "name": "Agent Nori", + "mentionable": false, + "managed": false, + "id": "1150637930436636752", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15277667 + }, + { + "version": 1701238514069, + "unicode_emoji": null, + "tags": {}, + "position": 99, + "permissions": "0", + "name": "≡ƒôó", + "mentionable": false, + "managed": false, + "id": "1132547843064872980", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15844367 + }, + { + "version": 1701238513752, + "unicode_emoji": null, + "tags": {}, + "position": 25, + "permissions": "0", + "name": "Transitioning to a womam", + "mentionable": false, + "managed": false, + "id": "1154862022111010816", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514059, + "unicode_emoji": null, + "tags": {}, + "position": 97, + "permissions": "0", + "name": "Verified American", + "mentionable": false, + "managed": false, + "id": "1139361736886059058", + "icon": null, + "hoist": false, + "flags": 0, + "color": 524392 + }, + { + "version": 1701238513976, + "unicode_emoji": null, + "tags": {}, + "position": 80, + "permissions": "0", + "name": "7 Checks", + "mentionable": false, + "managed": false, + "id": "1138272133508771922", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514232, + "unicode_emoji": null, + "tags": {}, + "position": 127, + "permissions": "420009146314487", + "name": "≡ƒª₧Lobster≡ƒª₧", + "mentionable": false, + "managed": false, + "id": "1136839878127128668", + "icon": null, + "hoist": false, + "flags": 0, + "color": 16711680 + }, + { + "version": 1701238513615, + "unicode_emoji": null, + "tags": { "bot_id": "401328409499664394" }, + "position": 10, + "permissions": "275482074112", + "name": "Alpha", + "mentionable": false, + "managed": true, + "id": "1167941528841359363", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513856, + "unicode_emoji": null, + "tags": { "bot_id": "936929561302675456" }, + "position": 48, + "permissions": "2147601472", + "name": "Midjourney Bot", + "mentionable": false, + "managed": true, + "id": "1149199931584806974", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513533, + "unicode_emoji": null, + "tags": { "bot_id": "611635946735140874" }, + "position": 2, + "permissions": "70536256", + "name": "SoundBot", + "mentionable": false, + "managed": true, + "id": "1177893477829324852", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514132, + "unicode_emoji": null, + "tags": {}, + "position": 108, + "permissions": "0", + "name": "ai-trusted", + "mentionable": false, + "managed": false, + "id": "1142127501506777229", + "icon": null, + "hoist": false, + "flags": 0, + "color": 2123412 + }, + { + "version": 1701238514015, + "unicode_emoji": null, + "tags": { "bot_id": "451379187031343104" }, + "position": 89, + "permissions": "37088600", + "name": "LunaBot ≡ƒîÖ", + "mentionable": false, + "managed": true, + "id": "1132142645775446046", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513761, + "unicode_emoji": null, + "tags": {}, + "position": 28, + "permissions": "0", + "name": "Fits in with trannies", + "mentionable": false, + "managed": false, + "id": "1154848133143089312", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514113, + "unicode_emoji": null, + "tags": {}, + "position": 104, + "permissions": "40544595398337", + "name": "Military", + "mentionable": false, + "managed": false, + "id": "1137194209586196530", + "icon": null, + "hoist": false, + "flags": 0, + "color": 2067276 + }, + { + "version": 1701238513817, + "unicode_emoji": null, + "tags": {}, + "position": 40, + "permissions": "0", + "name": "On Fat Street", + "mentionable": false, + "managed": false, + "id": "1155586097708019762", + "icon": null, + "hoist": false, + "flags": 0, + "color": 10181046 + }, + { + "version": 1701238513965, + "unicode_emoji": null, + "tags": {}, + "position": 77, + "permissions": "0", + "name": "10 Checks", + "mentionable": false, + "managed": false, + "id": "1138272244515209357", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514055, + "unicode_emoji": null, + "tags": {}, + "position": 96, + "permissions": "71056043036225", + "name": "Ampersand Squad", + "mentionable": false, + "managed": false, + "id": "1146278985819500635", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15158332 + }, + { + "version": 1701238513731, + "unicode_emoji": null, + "tags": {}, + "position": 21, + "permissions": "0", + "name": "Crystal", + "mentionable": false, + "managed": false, + "id": "1156297495857614858", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514077, + "unicode_emoji": null, + "tags": {}, + "position": 100, + "permissions": "0", + "name": "Server Owner", + "mentionable": false, + "managed": false, + "id": "1132515740361179137", + "icon": null, + "hoist": true, + "flags": 0, + "color": 3066993 + }, + { + "version": 1701238514212, + "unicode_emoji": null, + "tags": { "bot_id": "155149108183695360" }, + "position": 120, + "permissions": "1513962695871", + "name": "Dyno", + "mentionable": false, + "managed": true, + "id": "1132495758340390994", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513675, + "unicode_emoji": null, + "tags": { "bot_id": "1142732033978814564" }, + "position": 17, + "permissions": "8", + "name": "MBot-Janny", + "mentionable": false, + "managed": true, + "id": "1158297926116847618", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513956, + "unicode_emoji": null, + "tags": {}, + "position": 74, + "permissions": "0", + "name": "13 Checks", + "mentionable": false, + "managed": false, + "id": "1138272323334586489", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514215, + "unicode_emoji": null, + "tags": { "premium_subscriber": null }, + "position": 121, + "permissions": "541651314790081", + "name": "Server Booster", + "mentionable": false, + "managed": true, + "id": "1136878100718829589", + "icon": null, + "hoist": false, + "flags": 0, + "color": 16023551 + }, + { + "version": 1701238513822, + "unicode_emoji": null, + "tags": {}, + "position": 41, + "permissions": "0", + "name": "Zoomers On Top", + "mentionable": false, + "managed": false, + "id": "1150634635815039138", + "icon": null, + "hoist": false, + "flags": 0, + "color": 7398426 + }, + { + "version": 1701238513805, + "unicode_emoji": null, + "tags": {}, + "position": 38, + "permissions": "0", + "name": "Wooderson Rescue Team", + "mentionable": false, + "managed": false, + "id": "1151564908278853652", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514117, + "unicode_emoji": null, + "tags": {}, + "position": 105, + "permissions": "0", + "name": "45th Platoon", + "mentionable": false, + "managed": false, + "id": "1150638639483723806", + "icon": null, + "hoist": false, + "flags": 0, + "color": 2067276 + }, + { + "version": 1701238513992, + "unicode_emoji": null, + "tags": {}, + "position": 84, + "permissions": "0", + "name": "3 Checks", + "mentionable": false, + "managed": false, + "id": "1138271935327916104", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513744, + "unicode_emoji": null, + "tags": { "bot_id": "1142167563858616410" }, + "position": 23, + "permissions": "8", + "name": "MBot-GameHouse", + "mentionable": false, + "managed": true, + "id": "1155296802241794091", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514169, + "unicode_emoji": null, + "tags": {}, + "position": 113, + "permissions": "29360128", + "name": "Parker the Mod", + "mentionable": false, + "managed": false, + "id": "1154509066882785332", + "icon": null, + "hoist": false, + "flags": 0, + "color": 1752220 + }, + { + "version": 1701238513910, + "unicode_emoji": null, + "tags": { "bot_id": "1142166864437452801" }, + "position": 60, + "permissions": "8", + "name": "MBot-MusicHouse", + "mentionable": false, + "managed": true, + "id": "1142732822847701012", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514046, + "unicode_emoji": null, + "tags": {}, + "position": 95, + "permissions": "0", + "name": "Music DJ", + "mentionable": false, + "managed": false, + "id": "1137195462189916262", + "icon": null, + "hoist": false, + "flags": 0, + "color": 10046026 + }, + { + "version": 1701238514039, + "unicode_emoji": null, + "tags": {}, + "position": 94, + "permissions": "0", + "name": "Certified Beaner", + "mentionable": false, + "managed": false, + "id": "1132071506801872987", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15277667 + }, + { + "version": 1701238513933, + "unicode_emoji": null, + "tags": {}, + "position": 67, + "permissions": "0", + "name": "20 Checks", + "mentionable": false, + "managed": false, + "id": "1138272521012138027", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701248720821, + "unicode_emoji": null, + "tags": { "bot_id": "868296331234521099" }, + "position": 88, + "permissions": "3197952", + "name": "Soundbort", + "mentionable": false, + "managed": true, + "id": "1132544481430868030", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513962, + "unicode_emoji": null, + "tags": {}, + "position": 76, + "permissions": "0", + "name": "11 Checks", + "mentionable": false, + "managed": false, + "id": "1138272266656952331", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514185, + "unicode_emoji": null, + "tags": {}, + "position": 116, + "permissions": "0", + "name": "Our Best Gal", + "mentionable": false, + "managed": false, + "id": "1163915273804460082", + "icon": null, + "hoist": false, + "flags": 0, + "color": 12845263 + }, + { + "version": 1701238513738, + "unicode_emoji": null, + "tags": {}, + "position": 22, + "permissions": "0", + "name": "new role", + "mentionable": false, + "managed": false, + "id": "1155697139809259550", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513664, + "unicode_emoji": null, + "tags": {}, + "position": 16, + "permissions": "0", + "name": "No S.W.A.T. List", + "mentionable": false, + "managed": false, + "id": "1159589181316661269", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15526969 + }, + { + "version": 1701238513834, + "unicode_emoji": null, + "tags": {}, + "position": 43, + "permissions": "0", + "name": "Speed Reader", + "mentionable": false, + "managed": false, + "id": "1150595696303550535", + "icon": null, + "hoist": false, + "flags": 0, + "color": 11342935 + }, + { + "version": 1701238514003, + "unicode_emoji": null, + "tags": {}, + "position": 87, + "permissions": "256", + "name": "PRIORITY SPEAKER", + "mentionable": false, + "managed": false, + "id": "1137988589792272554", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514035, + "unicode_emoji": null, + "tags": {}, + "position": 93, + "permissions": "0", + "name": "Along For The Ride", + "mentionable": false, + "managed": false, + "id": "1135643322132738170", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513937, + "unicode_emoji": null, + "tags": {}, + "position": 68, + "permissions": "0", + "name": "19 Checks", + "mentionable": false, + "managed": false, + "id": "1138272496701939823", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513928, + "unicode_emoji": null, + "tags": {}, + "position": 66, + "permissions": "0", + "name": "RumVerified", + "mentionable": false, + "managed": false, + "id": "1140025493027029171", + "icon": null, + "hoist": false, + "flags": 0, + "color": 14505301 + }, + { + "version": 1701238513588, + "unicode_emoji": null, + "tags": {}, + "position": 7, + "permissions": "0", + "name": "Totalus's Approval", + "mentionable": false, + "managed": false, + "id": "1171877369666076722", + "icon": null, + "hoist": false, + "flags": 0, + "color": 13949730 + }, + { + "version": 1701238513925, + "unicode_emoji": null, + "tags": {}, + "position": 65, + "permissions": "0", + "name": "Verified Canadian", + "mentionable": false, + "managed": false, + "id": "1139726540054216784", + "icon": null, + "hoist": false, + "flags": 0, + "color": 11027200 + }, + { + "version": 1701238514105, + "unicode_emoji": null, + "tags": {}, + "position": 103, + "permissions": "0", + "name": "Royalty", + "mentionable": false, + "managed": false, + "id": "1135771402880958514", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15158332 + }, + { + "version": 1701238513775, + "unicode_emoji": null, + "tags": {}, + "position": 31, + "permissions": "0", + "name": "Owes Window Money", + "mentionable": false, + "managed": false, + "id": "1154232442413121536", + "icon": null, + "hoist": false, + "flags": 0, + "color": 9936031 + }, + { + "version": 1701238513913, + "unicode_emoji": null, + "tags": {}, + "position": 61, + "permissions": "0", + "name": "GMI", + "mentionable": false, + "managed": false, + "id": "1141941481607790684", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513608, + "unicode_emoji": null, + "tags": {}, + "position": 9, + "permissions": "0", + "name": "Clown Role", + "mentionable": false, + "managed": false, + "id": "1169450276873314374", + "icon": null, + "hoist": false, + "flags": 0, + "color": 14340916 + }, + { + "version": 1701238514207, + "unicode_emoji": null, + "tags": { "bot_id": "235148962103951360" }, + "position": 119, + "permissions": "130111", + "name": "carl-bot", + "mentionable": false, + "managed": true, + "id": "1151669975375937638", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1694623924858, + "unicode_emoji": null, + "tags": {}, + "position": 0, + "permissions": "422903988670016", + "name": "@everyone", + "mentionable": false, + "managed": false, + "id": "1131853763506880522", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514176, + "unicode_emoji": null, + "tags": {}, + "position": 114, + "permissions": "137404710649665", + "name": "TNG", + "mentionable": true, + "managed": false, + "id": "1132022472737292329", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15844367 + }, + { + "version": 1701238513853, + "unicode_emoji": null, + "tags": {}, + "position": 47, + "permissions": "0", + "name": "In Coder's Memory", + "mentionable": false, + "managed": false, + "id": "1149867349994917948", + "icon": null, + "hoist": false, + "flags": 0, + "color": 3150921 + }, + { + "version": 1701238514149, + "unicode_emoji": null, + "tags": {}, + "position": 110, + "permissions": "0", + "name": "TERF", + "mentionable": false, + "managed": false, + "id": "1169788942971846818", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15277667 + }, + { + "version": 1701238513887, + "unicode_emoji": null, + "tags": {}, + "position": 55, + "permissions": "0", + "name": "Frame Enjoyer", + "mentionable": false, + "managed": false, + "id": "1147245576270913647", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513785, + "unicode_emoji": null, + "tags": {}, + "position": 34, + "permissions": "0", + "name": "Invited by Totalus", + "mentionable": false, + "managed": false, + "id": "1152371592911925289", + "icon": null, + "hoist": false, + "flags": 0, + "color": 16773376 + }, + { + "version": 1701238513941, + "unicode_emoji": null, + "tags": {}, + "position": 69, + "permissions": "0", + "name": "18 Checks", + "mentionable": false, + "managed": false, + "id": "1138272469870981163", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513959, + "unicode_emoji": null, + "tags": {}, + "position": 75, + "permissions": "0", + "name": "12 Checks", + "mentionable": false, + "managed": false, + "id": "1138272294343557182", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513847, + "unicode_emoji": null, + "tags": {}, + "position": 46, + "permissions": "281474976710656", + "name": "Account Verifier", + "mentionable": false, + "managed": false, + "id": "1144734109021769749", + "icon": null, + "hoist": false, + "flags": 0, + "color": 3484081 + }, + { + "version": 1701238514226, + "unicode_emoji": null, + "tags": {}, + "position": 125, + "permissions": "119455388004033", + "name": "Senior Moderator Tortie", + "mentionable": false, + "managed": false, + "id": "1154965536464179290", + "icon": null, + "hoist": false, + "flags": 0, + "color": 58596 + }, + { + "version": 1701238513876, + "unicode_emoji": null, + "tags": {}, + "position": 53, + "permissions": "0", + "name": "Food Maximalist", + "mentionable": false, + "managed": false, + "id": "1147401226187714590", + "icon": null, + "hoist": false, + "flags": 0, + "color": 11027200 + }, + { + "version": 1701238513945, + "unicode_emoji": null, + "tags": {}, + "position": 70, + "permissions": "0", + "name": "17 Checks", + "mentionable": false, + "managed": false, + "id": "1138272440754130965", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513859, + "unicode_emoji": null, + "tags": { "bot_id": "1142733646600614004" }, + "position": 49, + "permissions": "8", + "name": "MBot-MusicHouse-2", + "mentionable": false, + "managed": true, + "id": "1148104696171601934", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514181, + "unicode_emoji": null, + "tags": {}, + "position": 115, + "permissions": "0", + "name": "RPN Empire", + "mentionable": false, + "managed": false, + "id": "1142735361538269274", + "icon": null, + "hoist": false, + "flags": 0, + "color": 12058697 + }, + { + "version": 1701238514370, + "unicode_emoji": null, + "tags": {}, + "position": 1, + "permissions": "0", + "name": "Ugly Ve", + "mentionable": false, + "managed": false, + "id": "1179304344751984730", + "icon": null, + "hoist": false, + "flags": 0, + "color": 10950121 + }, + { + "version": 1701238513582, + "unicode_emoji": null, + "tags": { "bot_id": "439205512425504771" }, + "position": 6, + "permissions": "412320386112", + "name": "NotSoBot", + "mentionable": false, + "managed": true, + "id": "1171880651843182634", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514223, + "unicode_emoji": null, + "tags": {}, + "position": 124, + "permissions": "400913440632513", + "name": "Risk Management", + "mentionable": false, + "managed": false, + "id": "1153154189288030259", + "icon": null, + "hoist": false, + "flags": 0, + "color": 6724482 + }, + { + "version": 1701238513919, + "unicode_emoji": null, + "tags": {}, + "position": 63, + "permissions": "0", + "name": "Angry Mexican", + "mentionable": false, + "managed": false, + "id": "1139366614492532787", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15105570 + }, + { + "version": 1701238513711, + "unicode_emoji": null, + "tags": { "bot_id": "411916947773587456" }, + "position": 20, + "permissions": "8", + "name": "Jockie Music", + "mentionable": false, + "managed": true, + "id": "1156313429796192338", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513550, + "unicode_emoji": null, + "tags": {}, + "position": 3, + "permissions": "0", + "name": "≡ƒæ╜", + "mentionable": false, + "managed": false, + "id": "1173650979418279986", + "icon": null, + "hoist": false, + "flags": 0, + "color": 3066993 + }, + { + "version": 1701238513948, + "unicode_emoji": null, + "tags": {}, + "position": 71, + "permissions": "0", + "name": "16 Checks", + "mentionable": false, + "managed": false, + "id": "1138272413205930026", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513984, + "unicode_emoji": null, + "tags": {}, + "position": 82, + "permissions": "0", + "name": "5 Checks", + "mentionable": false, + "managed": false, + "id": "1138272038205792326", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513838, + "unicode_emoji": null, + "tags": {}, + "position": 44, + "permissions": "0", + "name": "≡ƒÆ⌐", + "mentionable": false, + "managed": false, + "id": "1139376515461677147", + "icon": null, + "hoist": false, + "flags": 0, + "color": 11027200 + }, + { + "version": 1701238513622, + "unicode_emoji": null, + "tags": {}, + "position": 12, + "permissions": "0", + "name": "Poor Gang", + "mentionable": false, + "managed": false, + "id": "1167576534178082997", + "icon": null, + "hoist": false, + "flags": 0, + "color": 12699515 + }, + { + "version": 1701238513755, + "unicode_emoji": null, + "tags": {}, + "position": 26, + "permissions": "0", + "name": "Tranny worshipper", + "mentionable": false, + "managed": false, + "id": "1154848241322565782", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513790, + "unicode_emoji": null, + "tags": {}, + "position": 35, + "permissions": "106102975991361", + "name": "≡ƒÆë", + "mentionable": false, + "managed": false, + "id": "1132495232991244298", + "icon": null, + "hoist": false, + "flags": 0, + "color": 6323595 + }, + { + "version": 1701238513843, + "unicode_emoji": null, + "tags": {}, + "position": 45, + "permissions": "256", + "name": "Priority Tweaker", + "mentionable": false, + "managed": false, + "id": "1151630267413434428", + "icon": null, + "hoist": false, + "flags": 0, + "color": 16777215 + }, + { + "version": 1701238513765, + "unicode_emoji": null, + "tags": {}, + "position": 29, + "permissions": "0", + "name": "Not an Oleboy", + "mentionable": false, + "managed": false, + "id": "1154848091380383814", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514086, + "unicode_emoji": null, + "tags": {}, + "position": 101, + "permissions": "0", + "name": "push2talk", + "mentionable": false, + "managed": false, + "id": "1151025333206794321", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238514031, + "unicode_emoji": null, + "tags": {}, + "position": 92, + "permissions": "4398049724480", + "name": "NGMI", + "mentionable": false, + "managed": false, + "id": "1132134966185181234", + "icon": null, + "hoist": false, + "flags": 0, + "color": 6323595 + }, + { + "version": 1701238513656, + "unicode_emoji": null, + "tags": {}, + "position": 15, + "permissions": "0", + "name": "Mod Abuser", + "mentionable": false, + "managed": false, + "id": "1162967312341663764", + "icon": null, + "hoist": false, + "flags": 0, + "color": 11342935 + }, + { + "version": 1701238513781, + "unicode_emoji": null, + "tags": {}, + "position": 33, + "permissions": "0", + "name": "TripleHomicideSuicideNoNote", + "mentionable": false, + "managed": false, + "id": "1152389946255093911", + "icon": null, + "hoist": false, + "flags": 0, + "color": 16711680 + }, + { + "version": 1701238513953, + "unicode_emoji": null, + "tags": {}, + "position": 73, + "permissions": "0", + "name": "14 Checks", + "mentionable": false, + "managed": false, + "id": "1138272358528974878", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513916, + "unicode_emoji": null, + "tags": {}, + "position": 62, + "permissions": "0", + "name": "FULL ADMIN PERMS", + "mentionable": false, + "managed": false, + "id": "1138881285482369084", + "icon": null, + "hoist": false, + "flags": 0, + "color": 15277667 + }, + { + "version": 1701238513951, + "unicode_emoji": null, + "tags": {}, + "position": 72, + "permissions": "0", + "name": "15 Checks", + "mentionable": false, + "managed": false, + "id": "1138272384546250763", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513987, + "unicode_emoji": null, + "tags": {}, + "position": 83, + "permissions": "0", + "name": "4 Checks", + "mentionable": false, + "managed": false, + "id": "1138271967913463850", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513898, + "unicode_emoji": null, + "tags": { "bot_id": "228537642583588864" }, + "position": 57, + "permissions": "8", + "name": "Vexera", + "mentionable": false, + "managed": true, + "id": "1146220716417622149", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + }, + { + "version": 1701238513995, + "unicode_emoji": null, + "tags": {}, + "position": 85, + "permissions": "0", + "name": "2 Checks", + "mentionable": false, + "managed": false, + "id": "1138271904193597480", + "icon": null, + "hoist": false, + "flags": 0, + "color": 0 + } + ], + "stickers": [ + { + "version": 1689995253914, + "type": 2, + "tags": "watermelon", + "name": "sleepy", + "id": "1132146894437617684", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1693264785886, + "type": 2, + "tags": "ok", + "name": "moon?", + "id": "1145860305470095463", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "GERT", + "available": true, + "asset": "" + }, + { + "version": 1693694973867, + "type": 2, + "tags": "upside_down", + "name": "wigazngz", + "id": "1147664644626989077", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1693855354635, + "type": 2, + "tags": "shushing_face", + "name": "coder", + "id": "1148337330315337788", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1694198578751, + "type": 2, + "tags": "brain", + "name": "wallstreetagent", + "id": "1149776916635725924", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455788, + "type": 2, + "tags": "chart_with_upwards_trend", + "name": "stonks", + "id": "1149778986025615513", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455796, + "type": 2, + "tags": "cry", + "name": "missingbucko", + "id": "1149781447159316480", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455804, + "type": 2, + "tags": "crossed_flags", + "name": "ngmi", + "id": "1151303871247945809", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455808, + "type": 2, + "tags": "≡ƒæú", + "name": "ram", + "id": "1155932203205799936", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455814, + "type": 2, + "tags": "1156425736140357743", + "name": "alp", + "id": "1157170292645433374", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455818, + "type": 2, + "tags": "1152963109166784552", + "name": "vclit", + "id": "1158134041351028899", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455822, + "type": 2, + "tags": "≡ƒÿÄ", + "name": "hardcore", + "id": "1158235654220677210", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "", + "available": true, + "asset": "" + }, + { + "version": 1701235455827, + "type": 2, + "tags": "≡ƒÉé", + "name": "bullishdave", + "id": "1169742478556004513", + "guild_id": "1131853763506880522", + "format_type": 1, + "description": "Bullish Wave for Bullish Dave. Invest $1000 today. ", + "available": true, + "asset": "" + } + ], + "unavailable": false, + "public_updates_channel_id": null, + "features": [ "THREE_DAY_THREAD_ARCHIVE", "AUTO_MODERATION", "ANIMATED_ICON", "CHANNEL_ICON_EMOJIS_GENERATED", "SOUNDBOARD", "INVITE_SPLASH" ], + "premium_tier": 1, + "members": [ + { + "user": { + "username": "NotSoBot", + "public_flags": 65536, + "id": "439205512425504771", + "global_name": null, + "display_name": null, + "discriminator": "9555", + "bot": true, + "avatar_decoration_data": null, + "avatar": "3c90a26e89ee800bb9d4f5b4bb25f0f3" + }, + "roles": [ "1171880651843182634" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-08T18:35:19.937000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Midjourney Bot", + "public_flags": 589824, + "id": "936929561302675456", + "global_name": null, + "display_name": null, + "discriminator": "9282", + "bot": true, + "avatar_decoration_data": null, + "avatar": "f6ce562a6b4979c4b1cbc5b436d3be76" + }, + "roles": [ "1132495232991244298", "1158137449407598682", "1149199931584806974" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-07T04:30:14.855000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "MBot-MusicHouse-2", + "public_flags": 0, + "id": "1142733646600614004", + "global_name": null, + "display_name": null, + "discriminator": "3055", + "bot": true, + "avatar_decoration_data": null, + "avatar": "88bd9ce7bf889c0d36fb4afd3725900b" + }, + "roles": [ "1132515740361179137", "1132495232991244298", "1158137449407598682", "1148104696171601934" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-04T03:58:10.388000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "shrimpdick003", + "public_flags": 0, + "id": "853416208212033546", + "global_name": "Shrimp Dick", + "display_name": "Shrimp Dick", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "71b4169afe8cd917feb0f17542d673ce" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-05T03:15:12.196000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "justliz.", + "public_flags": 256, + "id": "822367483679473675", + "global_name": "justliz.", + "display_name": "justliz.", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b1d0e0f3dc70a2e165b3941b6ef369bf" + }, + "roles": [ "1132495232991244298", "1153154189288030259", "1133448992827641906", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-23T06:03:59.076000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "rezzybeans", + "public_flags": 0, + "id": "217341623514824704", + "global_name": "RezzyBeans", + "display_name": "RezzyBeans", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a56458ab9a17bbe210ed557fe610945d" + }, + "roles": [ "1144017607444402276", "1132022472737292329", "1132495232991244298", "1131855863930425394", "1140025493027029171", "1132320097734770748" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T12:53:56.628000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "crispynick11", + "public_flags": 0, + "id": "704855912950530091", + "global_name": "crispynick11", + "display_name": "crispynick11", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "15e21cca697b193c7c3179fc7960cc74" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T02:32:22.058555+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "morelli", + "public_flags": 0, + "id": "428417059077095426", + "global_name": null, + "display_name": null, + "discriminator": "5226", + "bot": false, + "avatar_decoration_data": null, + "avatar": "737410284c2cab813b264cd41eeed7f5" + }, + "roles": [ "1132495232991244298", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T03:05:56.555000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "gertallah", + "public_flags": 0, + "id": "685745703003095052", + "global_name": "gert", + "display_name": "gert", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "3f54ffb302e18c1e9424f6eb1e9e1a4d" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-22T20:45:49.536000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "clipperfrog", + "public_flags": 128, + "id": "995763976656924733", + "global_name": "clipper", + "display_name": "clipper", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "085138c9e84a856d0269134c085b5a2f" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1140025493027029171", "1165360991710752979", "1173489923450470453", "1138881285482369084" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-05T13:43:45.310000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "pepelejoker", + "public_flags": 0, + "id": "824259062438428692", + "global_name": "en passant prenez l'argent", + "display_name": "en passant prenez l'argent", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d764339655dea624fd22301e91ff9256" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": ":Pepe-le:Joker: ALIAS", + "mute": false, + "joined_at": "2023-11-04T18:24:08.325000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "DiceParser", + "public_flags": 65536, + "id": "279722369260453888", + "global_name": null, + "display_name": null, + "discriminator": "0764", + "bot": true, + "avatar_decoration_data": null, + "avatar": "e6d297d605117684d26c6b3b07169b31" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-12-05T04:52:32.771384+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "MEE6", + "public_flags": 65536, + "id": "159985870458322944", + "global_name": null, + "display_name": null, + "discriminator": "4876", + "bot": true, + "avatar_decoration_data": null, + "avatar": "b50adff099924dd5e6b72d13f77eb9d7" + }, + "roles": [ "1132495232991244298", "1158137449407598682", "1132513757491372055" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-07-23T03:25:20.998000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "ageoldtitan", + "public_flags": 0, + "id": "284128221522296842", + "global_name": "AgeOldTitan", + "display_name": "AgeOldTitan", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "78df2878b9beb60c0b4fb0978f1d9601" + }, + "roles": [ "1131855863930425394", "1153154189288030259", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-20T02:06:12.504000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "kawaiikitten", + "public_flags": 0, + "id": "181596968550662144", + "global_name": "Kawaii Kitten", + "display_name": "Kawaii Kitten", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "92e3bed1e9c83f5b8fc49597a1c9d779" + }, + "roles": [ "1137195462189916262", "1132495232991244298", "1131855863930425394", "1153154189288030259", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "therapist", + "mute": false, + "joined_at": "2023-09-11T18:14:23.450000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Soundbort", + "public_flags": 65536, + "id": "868296331234521099", + "global_name": null, + "display_name": null, + "discriminator": "8790", + "bot": true, + "avatar_decoration_data": null, + "avatar": "244f2d20c498175dc30c83c580e3eea8" + }, + "roles": [ "1132495232991244298", "1139361736886059058", "1158137449407598682", "1132320097734770748", "1132544481430868030" ], + "premium_since": null, + "pending": false, + "nick": "Hodors Prolapsed Gook Chode", + "mute": false, + "joined_at": "2023-07-23T05:27:26.102000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "pudding6699", + "public_flags": 256, + "id": "408470059879759872", + "global_name": "pudding6699", + "display_name": "pudding6699", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "373da8a60d18f1e742b862f8dc3225a9" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-22T07:01:33.053000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "genocidalvirus", + "public_flags": 512, + "id": "173294645730607115", + "global_name": "GenocidalVirus", + "display_name": "GenocidalVirus", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "9f3e28eed531a06f09cfb74e7f0a746e" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T03:39:52.235000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "roth_trader", + "public_flags": 0, + "id": "449167945386557461", + "global_name": "Roth_Trader", + "display_name": "Roth_Trader", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "92154014b44b4f7694c876efc3b52e89" + }, + "roles": [ "1137195462189916262", "1132495232991244298", "1131855863930425394", "1140025493027029171", "1135643322132738170" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-20T20:32:11.720000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "therumbler_", + "public_flags": 0, + "id": "1065863268012404816", + "global_name": "Rumbler", + "display_name": "Rumbler", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a583b9d3767486c1c5d0d8f33df56863" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171", "1135643322132738170" ], + "premium_since": null, + "pending": false, + "nick": "RumStream", + "mute": false, + "joined_at": "2023-11-22T23:51:21.295000+00:00", + "flags": 0, + "deaf": true, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".joshfx", + "public_flags": 128, + "id": "567463925801811969", + "global_name": "JoshFX", + "display_name": "JoshFX", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "8edaaa3bb4049ec2bc73745c6998ddfd" + }, + "roles": [ "1132495232991244298", "1142127501506777229", "1131855863930425394", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T15:16:16.541000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "bloody.frog.kingdom", + "public_flags": 0, + "id": "227215432812199936", + "global_name": null, + "display_name": null, + "discriminator": "4362", + "bot": false, + "avatar_decoration_data": null, + "avatar": "37cba3c2165e50f9c2c8dfe43c4c344f" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T05:04:30.619000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "oldboywoody", + "public_flags": 0, + "id": "405189268399587339", + "global_name": "Indianapolis Jones", + "display_name": "Indianapolis Jones", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "c2e33b4f686ec3314f828ffd1f8f7ba8" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1138881285482369084", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T21:01:26.362000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": "2023-12-05T00:46:29.644000+00:00", + "avatar": null + }, + { + "user": { + "username": "ktravelmedia", + "public_flags": 0, + "id": "950668182786560041", + "global_name": "Ktravelmedia", + "display_name": "Ktravelmedia", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "bd20746a8dd67d29dac6dd89876ca7d8" + }, + "roles": [ "1132495232991244298", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-29T03:03:55.888000+00:00", + "flags": 1, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "_disposition_", + "public_flags": 0, + "id": "335094779207483392", + "global_name": "Disposition", + "display_name": "Disposition", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "bc7077bed3bb9637bc44e3e7dd6df4be" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T23:52:25.056000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "bigdicktendygang", + "public_flags": 0, + "id": "722120322676949063", + "global_name": "BigDickTendyGang", + "display_name": "BigDickTendyGang", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "9904cbd4017a02e8e913da51f6ab2d87" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171", "1135643322132738170" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T03:40:34.645000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Carl-bot", + "public_flags": 65536, + "id": "235148962103951360", + "global_name": null, + "display_name": null, + "discriminator": "1536", + "bot": true, + "avatar_decoration_data": null, + "avatar": "ed3dac3b6e7a851df781632a4295fcb9" + }, + "roles": [ "1158137449407598682", "1151669975375937638" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-14T00:05:19.154000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "banginparts", + "public_flags": 0, + "id": "826973557559918602", + "global_name": "Banginparts", + "display_name": "Banginparts", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "40fab19bdc197143c07c04b5c80302d8" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-08T21:53:44.537000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "ccrazycc", + "public_flags": 0, + "id": "1119110358007820318", + "global_name": "Crazy.CC", + "display_name": "Crazy.CC", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144058844004233369", + "asset": "a_fed43ab12698df65902ba06727e20c0e" + }, + "avatar": "03077ecf57eb3a61e2dbe2a901df87b8" + }, + "roles": [ "1132495232991244298", "1146278985819500635", "1133448992827641906", "1157158716785823855" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-23T21:39:20.330000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "lothrop", + "public_flags": 0, + "id": "285219649921220608", + "global_name": "Lothrop", + "display_name": "Lothrop", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "eb0e334170b3b7f501d535241a4552b6" + }, + "roles": [ "1131855863930425394", "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T12:17:05.232000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "TSLA", + "public_flags": 65536, + "id": "808723743069306882", + "global_name": null, + "display_name": null, + "discriminator": "3521", + "bot": true, + "avatar_decoration_data": null, + "avatar": "9003259db1636b883ed939632b9139cf" + }, + "roles": [ "1132495232991244298", "1132514826179072091", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-07-23T03:31:57.938000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "channygod", + "public_flags": 0, + "id": "384852088036786177", + "global_name": "channygod", + "display_name": "channygod", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "32c643b3bdf3f1b4e0d78f5f06e74e7e" + }, + "roles": [ "1154232442413121536", "1138271856009416804", "1132495232991244298", "1131855863930425394", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-12T16:16:35.766000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "sans7770", + "public_flags": 0, + "id": "733032208905797753", + "global_name": "janzschanz", + "display_name": "janzschanz", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f1531f2927b8fe1857a4ad6a07772fc0" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1140025493027029171", "1165360991710752979", "1138881285482369084" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-13T07:22:57.624000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "bortles", + "public_flags": 0, + "id": "966356960511397918", + "global_name": "Bortles", + "display_name": "Bortles", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "aee09be0675a95d458e212336170298d" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1153154189288030259", "1140025493027029171", "1165360991710752979" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-11T16:04:24.495000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "stinkhauzer", + "public_flags": 0, + "id": "1046851450422165595", + "global_name": "Stinkhauzer (ziggi)", + "display_name": "Stinkhauzer (ziggi)", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b1afc90b44aa03ee5d42d92f686eee62" + }, + "roles": [ "1132495232991244298", "1146278985819500635", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-23T22:42:48.758000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "TurboTrader", + "public_flags": 0, + "id": "527838872613421075", + "global_name": "Turbo", + "display_name": "Turbo", + "discriminator": "5379", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f004b0201bae928131e226d2b82601a6" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171", "1169450276873314374" ], + "premium_since": null, + "pending": false, + "nick": "Turbo", + "mute": false, + "joined_at": "2023-09-11T02:13:12.268000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "infowars_", + "public_flags": 0, + "id": "609922826153230356", + "global_name": "InfoWars", + "display_name": "InfoWars", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f0fb955a01d7115caa6af04f6d5d4a19" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-25T12:53:11.893000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "tortie6969", + "public_flags": 0, + "id": "298910884942577664", + "global_name": "Tortie", + "display_name": "Tortie", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "58fcb67fa0c948e16a1441fe184ce159" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171", "1154965536464179290" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-23T02:09:29.552000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "scoutking", + "public_flags": 0, + "id": "407337052099706891", + "global_name": "scoutking", + "display_name": "scoutking", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "af40aea3a23c03362287bd6339aca8ea" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-12T13:12:31.584000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "tuckferrorists", + "public_flags": 64, + "id": "766822971377188864", + "global_name": "tweakferrorists", + "display_name": "tweakferrorists", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "66ddfc6117e607c6a41fe4a220b1d831" + }, + "roles": [ "1132495232991244298", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T18:11:13.124000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "amademan", + "public_flags": 0, + "id": "137052617548365824", + "global_name": "a made man", + "display_name": "a made man", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "c934f4caec63941db0675107c3748371" + }, + "roles": [ "1165355605033230336", "1132495232991244298", "1140025493027029171", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-19T18:40:39.784000+00:00", + "flags": 1, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "tear_jerker", + "public_flags": 0, + "id": "321832087407689729", + "global_name": "TearJerker", + "display_name": "TearJerker", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "5eb717b59d42453c49d226f1dbd6ee45" + }, + "roles": [ "1137195462189916262", "1132495232991244298", "1131855863930425394", "1137194209586196530", "1139361736886059058", "1140025493027029171", "1154509955290894427", "1136839878127128668", "1150638639483723806" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-07-23T16:41:37.980000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "loki.1851", + "public_flags": 0, + "id": "476183649985757197", + "global_name": "Steel Balls.", + "display_name": "Steel Balls.", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "19ec54037d828513bde15af084bd3d36" + }, + "roles": [ "1132495232991244298", "1152013710374748240", "1133448992827641906", "1140025493027029171", "1131855863930425394", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T01:55:15.199000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "m_and_m55", + "public_flags": 0, + "id": "1113668949138227291", + "global_name": "M&M", + "display_name": "M&M", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b54eab29824f68f27c03ca5fd5b93881" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-14T09:14:20.201000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "johnnysomali", + "public_flags": 0, + "id": "270281452816564225", + "global_name": "Johnny Somali", + "display_name": "Johnny Somali", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "268adffa50c21f034522d200157b20ef" + }, + "roles": [ "1132495232991244298", "1133964361317240942", "1131855863930425394", "1140025493027029171", "1132320097734770748" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-12T08:31:33.700000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "thetopg02", + "public_flags": 64, + "id": "411597832508932097", + "global_name": "Γ£» Krueger Γ£»", + "display_name": "Γ£» Krueger Γ£»", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "5306f91a681d1a2329989936bb1040cf" + }, + "roles": [ "1152371592911925289", "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-18T13:58:54.853000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "chopper_cock", + "public_flags": 0, + "id": "745964914421530714", + "global_name": "&Chopper&", + "display_name": "&Chopper&", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "abae386b53a1d0c10c44d27926a734e2" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-27T07:34:48.859000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "itsyaboyy.", + "public_flags": 0, + "id": "566510460547891221", + "global_name": "itsyaboyy", + "display_name": "itsyaboyy", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "3b53c3a76dc201b967bcf8062241c618" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-21T04:45:08.580000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".marack", + "public_flags": 64, + "id": "523319660112773122", + "global_name": "Marack", + "display_name": "Marack", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144308439720394944", + "asset": "a_3c97a2d37f433a7913a1c7b7a735d000" + }, + "avatar": "1d3c5937b82bfceb536b09689366c548" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-18T08:44:11.274000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "MBot-GameHouse", + "public_flags": 0, + "id": "1142167563858616410", + "global_name": null, + "display_name": null, + "discriminator": "4710", + "bot": true, + "avatar_decoration_data": null, + "avatar": "dbd1ec9a73f5a12b76166dc521213846" + }, + "roles": [ "1158137449407598682", "1155296802241794091" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-24T00:17:02.067000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "megaboomer", + "public_flags": 0, + "id": "748389195344773211", + "global_name": "GrinningMan", + "display_name": "GrinningMan", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "53e52391dd18aa7799e25ff53ce2aa5e" + }, + "roles": [ "1132495232991244298", "1173650979418279986", "1153154189288030259", "1131855863930425394", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "GrinningMan 14/20", + "mute": false, + "joined_at": "2023-09-30T00:04:25.934000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "carnage5611", + "public_flags": 0, + "id": "256917990480674817", + "global_name": "Carnage", + "display_name": "Carnage", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "5d6c9d75c8d49dd386aac1a0a2a35136" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T06:47:00.363000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "ksdiscord", + "public_flags": 0, + "id": "722672687989784606", + "global_name": null, + "display_name": null, + "discriminator": "7350", + "bot": false, + "avatar_decoration_data": null, + "avatar": null + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171", "1157158716785823855" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-18T19:48:44.008000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "ratbread_0000", + "public_flags": 0, + "id": "943308401411260436", + "global_name": "rat bread", + "display_name": "rat bread", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "bfc07c8735cbaab74eeb9ccc4e225a0b" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-25T03:52:32.950000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "myspacetom", + "public_flags": 0, + "id": "215167096663965696", + "global_name": "Tom", + "display_name": "Tom", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b5ce35bd5333125f984597dc6c317345" + }, + "roles": [ "1131855863930425394", "1153154189288030259", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "Tom", + "mute": false, + "joined_at": "2023-09-11T18:08:40.249000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".ludmilla.", + "public_flags": 0, + "id": "700411523264282685", + "global_name": "LudMilla", + "display_name": "LudMilla", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b11e61651fe6f24a669c59c95588248d" + }, + "roles": [ "1132495232991244298", "1153154189288030259", "1133448992827641906", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T12:16:59.483000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "grumpybear", + "public_flags": 0, + "id": "310140268307283978", + "global_name": "Grumpy Bear", + "display_name": "Grumpy Bear", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "4e126c9df6b89a86d941d07434fdd464" + }, + "roles": [ "1131855863930425394", "1140025493027029171", "1144017607444402276", "1136878100718829589", "1150819267453931622", "1132495232991244298", "1154509955290894427" ], + "premium_since": "2023-11-29T05:24:07.110000+00:00", + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T06:05:21.917000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Vexera", + "public_flags": 65536, + "id": "228537642583588864", + "global_name": null, + "display_name": null, + "discriminator": "8487", + "bot": true, + "avatar_decoration_data": null, + "avatar": "855c102d556d5aa135716da398404980" + }, + "roles": [ "1132495232991244298", "1146220716417622149", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-08-29T23:11:54.581000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".ldd", + "public_flags": 0, + "id": "407971046277382144", + "global_name": "LDD", + "display_name": "LDD", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "32fe8548ea9ad675ab471c9786459870" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-13T01:09:56.590000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "austinwhk", + "public_flags": 128, + "id": "342945406914789376", + "global_name": "Austin", + "display_name": "Austin", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144059132517826601", + "asset": "a_10b9f886b513b77ccdd67c8784f1a496" + }, + "avatar": "9b25d024640b47035a5c775a41c7b7df" + }, + "roles": [ "1132495232991244298", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-19T22:56:26.147000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "1929tomorrow", + "public_flags": 0, + "id": "512639330586460177", + "global_name": "ToeKnee", + "display_name": "ToeKnee", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d8587983d5a5ec6ca0b1c698ef498b56" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T13:52:21.005000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "ExecutionerTV", + "public_flags": 0, + "id": "98587545511669760", + "global_name": null, + "display_name": null, + "discriminator": "3187", + "bot": false, + "avatar_decoration_data": null, + "avatar": "c9e1c0a7da6142ed49d140fe78567fdd" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-10T05:07:28.125000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "joedatti", + "public_flags": 256, + "id": "269688928804667394", + "global_name": "Josef", + "display_name": "Josef", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a_2ef83b469e8b07d5e763392aefdebec2" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "[BIGGERTHANYOU] Josef", + "mute": false, + "joined_at": "2023-09-10T03:51:12.488000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "≡ƒÆÄ Rainman ≡ƒÆÄ", + "public_flags": 0, + "id": "245721412881481728", + "global_name": "Rainstein", + "display_name": "Rainstein", + "discriminator": "3390", + "bot": false, + "avatar_decoration_data": null, + "avatar": "24fb4d6a0df80ffbfeb3e35b9c6f5ec8" + }, + "roles": [ "1135643322132738170", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T00:36:46.337000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Alpha", + "public_flags": 65536, + "id": "401328409499664394", + "global_name": null, + "display_name": null, + "discriminator": "9179", + "bot": true, + "avatar_decoration_data": null, + "avatar": "326e5bef971f8227de79c09d82031dda" + }, + "roles": [ "1167941528841359363" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-28T21:42:39.858000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "alpaca_v2.0", + "public_flags": 0, + "id": "1152368395354918922", + "global_name": "Alpaca V2.5", + "display_name": "Alpaca V2.5", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ece44991c2c07027379e3ecafe2f9c00" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1131855863930425394", "1135643322132738170" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-29T02:03:33.275000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "wavy", + "public_flags": 0, + "id": "797378719924617236", + "global_name": "wavy", + "display_name": "wavy", + "discriminator": "8455", + "bot": false, + "avatar_decoration_data": null, + "avatar": "bf7f57fa485e793ab53f69b906ca8b20" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "Speed Racer", + "mute": false, + "joined_at": "2023-09-11T13:29:36.176000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Tattle", + "public_flags": 65536, + "id": "671176256313622548", + "global_name": null, + "display_name": null, + "discriminator": "6330", + "bot": true, + "avatar_decoration_data": null, + "avatar": "c821c8380c754c5ed6e107a4909b96cd" + }, + "roles": [ "1135769664237088841", "1132495232991244298", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-08-01T03:03:09.590000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "vethorvendetta", + "public_flags": 0, + "id": "804557363054247977", + "global_name": "VeThorVendetta", + "display_name": "VeThorVendetta", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "70d8feb0296612d2e806b88351c7d239" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1153154189288030259", "1132547843064872980", "1140025493027029171", "1165360991710752979", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-12T16:01:35.972000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "etric", + "public_flags": 0, + "id": "101782535012384768", + "global_name": "{ i4ni } Lurker", + "display_name": "{ i4ni } Lurker", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f5c9041f24ba56b5329f75d42040dece" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T03:12:52.880000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "engineer3649", + "public_flags": 0, + "id": "1080482523760574566", + "global_name": "Engineer", + "display_name": "Engineer", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d067480e5b15cdeac088617b35732c74" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1153154189288030259", "1140025493027029171", "1154591298477625364", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T05:16:19.422000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "liltrippyrae", + "public_flags": 0, + "id": "1078174604897562624", + "global_name": "LilTrippyRae", + "display_name": "LilTrippyRae", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d2998152672f5b48c576b138dac5b1ed" + }, + "roles": [ "1131855863930425394", "1146278985819500635", "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-25T15:30:11.705000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Jockie Music", + "public_flags": 65536, + "id": "411916947773587456", + "global_name": null, + "display_name": null, + "discriminator": "8158", + "bot": true, + "avatar_decoration_data": null, + "avatar": "dbdfec1a92c466ce59a324a497735a6e" + }, + "roles": [ "1156313429796192338", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": "Dino Radio", + "mute": false, + "joined_at": "2023-09-26T19:36:44.976000+00:00", + "flags": 0, + "deaf": true, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "pres/charlie", + "public_flags": 256, + "id": "1118642969117999294", + "global_name": null, + "display_name": null, + "discriminator": "9005", + "bot": false, + "avatar_decoration_data": null, + "avatar": "fb10d4b68e4b723285856eec65e6c414" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T15:12:02.867363+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "dalghak", + "public_flags": 0, + "id": "1043344037672919151", + "global_name": "Dalghak", + "display_name": "Dalghak", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a612d38d25e97d6b27cb61a78fd9fdf2" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1138881285482369084", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": "Ghost of GazaΓäó", + "mute": false, + "joined_at": "2023-10-02T04:13:46.757000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "therion7", + "public_flags": 0, + "id": "305582583398400002", + "global_name": "Therion", + "display_name": "Therion", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b00ccb42969e42fec0adf3a94f790cd6" + }, + "roles": [ "1131855863930425394", "1153154189288030259", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-17T15:19:13.876000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "myname1", + "public_flags": 0, + "id": "269599326756536331", + "global_name": "My Name", + "display_name": "My Name", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "0fe170a75c7dd0210278c0c7d97daa57" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1153154189288030259", "1147382626315935826", "1140025493027029171", "1165360991710752979", "1171877369666076722" ], + "premium_since": null, + "pending": false, + "nick": "[420C 01/19 24] My Name", + "mute": false, + "joined_at": "2023-09-11T03:52:53.216000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "nvda_labrat_tcade", + "public_flags": 0, + "id": "424756951680024576", + "global_name": "Bullion Hambone Goldstein", + "display_name": "Bullion Hambone Goldstein", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "802a97a45c0952054ed0dc58e7bf9173" + }, + "roles": [ "1152426486368845895", "1132495232991244298", "1142127501506777229", "1131855863930425394", "1135771402880958514", "1132547843064872980", "1139361736886059058", "1140025493027029171", "1152389946255093911", "1154509955290894427", "1136839878127128668", "1150638639483723806" ], + "premium_since": null, + "pending": false, + "nick": "Alopecia Specialist", + "mute": false, + "joined_at": "2023-07-21T16:39:14.085000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "lilfreebase", + "public_flags": 0, + "id": "497321666372960268", + "global_name": "lilfreeba$e", + "display_name": "lilfreeba$e", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "127e71f750b6d890bc65933abb061408" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-03T00:45:26.782000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "deskiweski", + "public_flags": 0, + "id": "1119845619771650049", + "global_name": "╩₧╦ó╟¥ß╡û", + "display_name": "╩₧╦ó╟¥ß╡û", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "c255131c6023a4d0ec40df48ccc6eae8" + }, + "roles": [ "1152426486368845895", "1152371592911925289", "1132495232991244298", "1131855863930425394", "1165360991710752979", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-12-10T02:07:26.036000+00:00", + "flags": 1, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "senordomo", + "public_flags": 0, + "id": "301896412780691466", + "global_name": "senordomo|XxX|", + "display_name": "senordomo|XxX|", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f1169265e0c1505cbed1cb31ee677dfc" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1139361736886059058", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "Big Filthy", + "mute": false, + "joined_at": "2023-11-11T03:05:42.538000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "vaguelyfamiliar", + "public_flags": 0, + "id": "1002472778391371776", + "global_name": "cranberrycocaine", + "display_name": "cranberrycocaine", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "02c45d28c5e66a921b30e291d5d8a862" + }, + "roles": [ "1132495232991244298", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-16T21:53:15.042000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "plantman111", + "public_flags": 0, + "id": "899799912789737503", + "global_name": "i4ni plantman111", + "display_name": "i4ni plantman111", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "73e59656a830e6f6283c12eb29fd5c31" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-27T19:53:45.901000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".fleksnes", + "public_flags": 128, + "id": "275424641869152256", + "global_name": "Fleksnes", + "display_name": "Fleksnes", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a884b25d063aec87077c7d741f19a02e" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-15T19:14:11.280000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "missstacy_70079", + "public_flags": 0, + "id": "1141891864723738785", + "global_name": "Miss Stacy", + "display_name": "Miss Stacy", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "c5c85fe340890ff1e7f383afaaae7598" + }, + "roles": [ "1144017607444402276", "1132495232991244298", "1131855863930425394", "1132547843064872980", "1136839878127128668" ], + "premium_since": null, + "pending": false, + "nick": "Miss Stacy", + "mute": false, + "joined_at": "2023-08-23T21:14:30.732000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "solderotter", + "public_flags": 64, + "id": "252639378940231680", + "global_name": "SolderOtter", + "display_name": "SolderOtter", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144058844004233369", + "asset": "a_fed43ab12698df65902ba06727e20c0e" + }, + "avatar": "3cfbf4965552aad1a0d74cede69c5e6e" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-18T08:45:44.154000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "drderpenstein", + "public_flags": 0, + "id": "371825227459723264", + "global_name": "DrDerpenstein", + "display_name": "DrDerpenstein", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "3553df4c3cd9fc827c54c5c22f0b1a63" + }, + "roles": [ "1131855863930425394", "1153154189288030259", "1132495232991244298", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-17T22:58:40.663000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "theodoorklaproos", + "public_flags": 0, + "id": "117672888089313284", + "global_name": "Theodoor Klaproos", + "display_name": "Theodoor Klaproos", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "63a8ebac9b8d039a69c6611439355bfc" + }, + "roles": [ "1151641053603057664", "1132022472737292329", "1132495232991244298", "1131855863930425394", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "Theo the Chtitty guy", + "mute": false, + "joined_at": "2023-09-13T19:05:53.733000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Gatsu", + "public_flags": 0, + "id": "482285925695488000", + "global_name": "Sam Porter Bridges", + "display_name": "Sam Porter Bridges", + "discriminator": "2784", + "bot": false, + "avatar_decoration_data": null, + "avatar": "89e1ce9dd490769d38fe7edc7879cf24" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-13T02:36:11.428000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "MBot-MusicHouse", + "public_flags": 0, + "id": "1142166864437452801", + "global_name": null, + "display_name": null, + "discriminator": "9137", + "bot": true, + "avatar_decoration_data": null, + "avatar": "88bd9ce7bf889c0d36fb4afd3725900b" + }, + "roles": [ "1132515740361179137", "1132022472737292329", "1132495232991244298", "1142732822847701012", "1158137449407598682", "1136839878127128668" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-08-20T08:12:15.931000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "fastcarsandsunnydays", + "public_flags": 0, + "id": "811479300590796820", + "global_name": "Fast cars and sunny days", + "display_name": "Fast cars and sunny days", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "80b94b1da94602a3383681de1566509a" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1133448992827641906", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-15T20:43:17.585000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "shayan0907", + "public_flags": 0, + "id": "344210573086425100", + "global_name": "Shy", + "display_name": "Shy", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a_061f81efc2c7a86b0d6669a5170e53c9" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-25T23:26:07.097009+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".petrikov", + "public_flags": 128, + "id": "293058512932569088", + "global_name": "Petrikov", + "display_name": "Petrikov", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "efc1e3fd14dc17d96b7224ebc6a336d2" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-12T00:15:48.082000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "bitcoinmarty", + "public_flags": 0, + "id": "604950306391851029", + "global_name": "BitcoinMarty", + "display_name": "BitcoinMarty", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "73e00fe6bb4a84358e268facedc30d53" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-24T04:33:27.507000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "astrid0001", + "public_flags": 0, + "id": "1037130703990697994", + "global_name": "astrid", + "display_name": "astrid", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b676321f82a5bf7fcc90da2af8933862" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-09T23:50:44.896000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "mixxona", + "public_flags": 0, + "id": "424368845621428234", + "global_name": "Mixxona", + "display_name": "Mixxona", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a_49d579780354621631ff9c94a47b662b" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-09T06:02:31.274000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Dyno", + "public_flags": 589824, + "id": "155149108183695360", + "global_name": null, + "display_name": null, + "discriminator": "3861", + "bot": true, + "avatar_decoration_data": null, + "avatar": "19a5ee4114b47195fcecc6646f2380b1" + }, + "roles": [ "1132022472737292329", "1132495232991244298", "1132495758340390994", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": "Gypsyjew", + "mute": false, + "joined_at": "2023-07-23T02:13:49.619000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "un_luckyjoe", + "public_flags": 0, + "id": "965384231503147018", + "global_name": "Joe is mean", + "display_name": "Joe is mean", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "cea46a085df6eb08e11c7aeb1afbd566" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-12-02T01:01:21.670267+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "okamihoro", + "public_flags": 576, + "id": "92834990248722432", + "global_name": "MichaeLeo", + "display_name": "MichaeLeo", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "5d77f1eeff63b6238beb49590b24a999" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T04:53:57.644000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "slopeking", + "public_flags": 0, + "id": "401130340648747018", + "global_name": "blanco the grey", + "display_name": "blanco the grey", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "69dec75c108d39d74c583ba131ab11d4" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-17T07:07:29.556000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "shadowlogic", + "public_flags": 0, + "id": "248969305700433921", + "global_name": "ShadowLogic", + "display_name": "ShadowLogic", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "49a2ac39516177222f37475a29d61727" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-25T12:56:57.730000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "pureeboyz", + "public_flags": 64, + "id": "890259418636255232", + "global_name": "Pureeboyz", + "display_name": "Pureeboyz", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d3cb4935d5da89acb085afc6a0b69ed4" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1155586097708019762", "1135643322132738170" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-12T05:10:37.832000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "dupe", + "public_flags": 0, + "id": "1148952559562793122", + "global_name": null, + "display_name": null, + "discriminator": "5851", + "bot": true, + "avatar_decoration_data": null, + "avatar": "5f06a463c8e7339f9631677de92f9d20" + }, + "roles": [ "1171262927739818076" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-07T01:40:43.041000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "xxtheh3roxx", + "public_flags": 0, + "id": "398254658159902720", + "global_name": "xXTheH3roXx", + "display_name": "xXTheH3roXx", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "8107c9459c59dd632956085dac19806a" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T16:00:46.491000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "gankiskahn", + "public_flags": 0, + "id": "150826437899714561", + "global_name": "Gankiskahn", + "display_name": "Gankiskahn", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "9fd6150f4a026728a1fbdc4179afa655" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T05:10:20.504000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "kotallyr3kt", + "public_flags": 0, + "id": "573017385108242454", + "global_name": "Kotally87", + "display_name": "Kotally87", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d9ae034bf1b8d1e7b089570c16040e16" + }, + "roles": [ "1135643322132738170", "1132495232991244298", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T04:53:44.630000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "spacecowboy077", + "public_flags": 0, + "id": "1132282579702263811", + "global_name": "spacecowboy", + "display_name": "spacecowboy", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1154896005045694555", + "asset": "a_c7e1751e8122f1b475cb3006966fb28c" + }, + "avatar": "71ff0ff231401ca4cd7366b46245cff1" + }, + "roles": [ "1131855863930425394", "1140025493027029171", "1136878100718829589", "1132495232991244298", "1138881285482369084" ], + "premium_since": "2023-12-03T16:27:59.306000+00:00", + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T15:23:39.729000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "bortlesstream", + "public_flags": 0, + "id": "1061725614584893490", + "global_name": null, + "display_name": null, + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b25458a3b75a6e19c522373e887b5e7c" + }, + "roles": [ "1137195462189916262", "1132495232991244298", "1165360991710752979", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T01:30:19.449000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "mytastybits", + "public_flags": 256, + "id": "691186760230895686", + "global_name": "MyTastyBits", + "display_name": "MyTastyBits", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "207dc8c85b921c4ba0b40ab6e98994df" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-21T11:37:36.328000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "eristocratic", + "public_flags": 0, + "id": "605700934693289985", + "global_name": "Eris", + "display_name": "Eris", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144059132517826601", + "asset": "a_10b9f886b513b77ccdd67c8784f1a496" + }, + "avatar": "a_7b54b0aa821743cad2fe6f2cd46047db" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1133448992827641906", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": "Eristotle", + "mute": false, + "joined_at": "2023-09-12T04:28:32.161000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": "a_9c2c4f413cede34bd747d3c8caae95d2" + }, + { + "user": { + "username": "wobblychair", + "public_flags": 0, + "id": "292068759684775937", + "global_name": null, + "display_name": null, + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144058844004233369", + "asset": "a_fed43ab12698df65902ba06727e20c0e" + }, + "avatar": "c96f7f32b31e28540218cffcc9326f7f" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": "crab # 2", + "mute": false, + "joined_at": "2023-09-11T21:01:20.984000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "fakespacesteve", + "public_flags": 0, + "id": "1142160480195059712", + "global_name": null, + "display_name": null, + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "157e517cdbf371a47aaead44675714a3" + }, + "roles": [ "1131855863930425394", "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T22:47:28.583000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "loose69", + "public_flags": 0, + "id": "166293122303787008", + "global_name": "Loose", + "display_name": "Loose", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "6b4fb4c78272a1397c6c26eb2013ab4e" + }, + "roles": [ "1131855863930425394", "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-17T00:53:48.875000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "michaelstevens", + "public_flags": 128, + "id": "298562669303037953", + "global_name": "Michael Stevens", + "display_name": "Michael Stevens", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a_7f8718d5dd2bc64bd20dd934d61bcc88" + }, + "roles": [ "1132495232991244298", "1146278985819500635", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-19T22:18:54.673000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "unsmoothe_banana", + "public_flags": 0, + "id": "934881078324371457", + "global_name": null, + "display_name": null, + "discriminator": "2527", + "bot": false, + "avatar_decoration_data": null, + "avatar": "976216825168dedad0401867c343cffe" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T17:22:02.283000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "spy-usd", + "public_flags": 65536, + "id": "811418568846737500", + "global_name": null, + "display_name": null, + "discriminator": "2780", + "bot": true, + "avatar_decoration_data": null, + "avatar": "4b607585173fcb3665950020bb64f5a7" + }, + "roles": [ "1132495232991244298", "1132514826179072091", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": "SPY", + "mute": false, + "joined_at": "2023-07-23T03:27:44.218000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "stockdocta", + "public_flags": 0, + "id": "826569120110608406", + "global_name": "Stock Docta", + "display_name": "Stock Docta", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "3e2ae827c5b364d5993e4ea0c39500d7" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-04T06:50:06.148000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "nerai", + "public_flags": 0, + "id": "315215796446035968", + "global_name": null, + "display_name": null, + "discriminator": "1176", + "bot": false, + "avatar_decoration_data": null, + "avatar": "cd4642b228796bbda593c8803d2bc917" + }, + "roles": [ "1165355605033230336", "1150819267453931622", "1137195462189916262", "1132495232991244298", "1139727644712251534", "1140025493027029171", "1150604748303646744" ], + "premium_since": null, + "pending": false, + "nick": "neraiπÇéthe inflation skizo", + "mute": false, + "joined_at": "2023-09-10T06:57:10.474000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Nightreaperr", + "public_flags": 0, + "id": "365567541432811520", + "global_name": "WiDoWMaKeR", + "display_name": "WiDoWMaKeR", + "discriminator": "1553", + "bot": false, + "avatar_decoration_data": null, + "avatar": null + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-10T02:50:11.471000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "thetealady", + "public_flags": 0, + "id": "869601612140797993", + "global_name": "The Tea Lady", + "display_name": "The Tea Lady", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "43257c93aa73f5dabee9e875fc5cea6f" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-23T19:26:21.871000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Make it a Quote", + "public_flags": 65536, + "id": "949479338275913799", + "global_name": null, + "display_name": null, + "discriminator": "6660", + "bot": true, + "avatar_decoration_data": null, + "avatar": "5261029e1fd335ed1cc13f2e12cce415" + }, + "roles": [ "1172323415919693868" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-09T23:54:43.139000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "ellesdy", + "public_flags": 64, + "id": "1137467117336268870", + "global_name": ".ellesdy", + "display_name": ".ellesdy", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a_2f5811fca7186fd6ef30b2a0583c3002" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1145791399162294334", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T18:39:05.634000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "moneybrain", + "public_flags": 0, + "id": "1085588193438617630", + "global_name": "moneybrain", + "display_name": "moneybrain", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a_9b514a39a12f709d97494aa26ce14f71" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T14:43:24.285000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "eriakh", + "public_flags": 0, + "id": "1161728107477205073", + "global_name": "Rahma", + "display_name": "Rahma", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": null + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1133448992827641906", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-12T02:27:58.140000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Γè╣╦Ü∩╜íΓÖí be1a", + "public_flags": 256, + "id": "1074847041877975090", + "global_name": null, + "display_name": null, + "discriminator": "2733", + "bot": false, + "avatar_decoration_data": null, + "avatar": "59c92c22a9fd9fde0c0531ab6f59524d" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-21T23:11:16.355538+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Jockie Music (1)", + "public_flags": 65536, + "id": "412347257233604609", + "global_name": null, + "display_name": null, + "discriminator": "6951", + "bot": true, + "avatar_decoration_data": null, + "avatar": "5e8159b67a74d92153c8cd79cce4889c" + }, + "roles": [ "1167665445801840722" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-28T03:25:36.482000+00:00", + "flags": 0, + "deaf": true, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "little_droida", + "public_flags": 0, + "id": "207533376314277888", + "global_name": "little droida", + "display_name": "little droida", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "6950b0b4e615e41ae7eef655aff80d49" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T16:32:46.004000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "klaapps", + "public_flags": 0, + "id": "258446680783978497", + "global_name": "Klapps", + "display_name": "Klapps", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "23a28e0ae66a6dc219f0963bf62f3f69" + }, + "roles": [ "1144017607444402276", "1132495232991244298", "1131855863930425394", "1140025493027029171", "1137194209586196530" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-21T04:32:18.689000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "SoundBot", + "public_flags": 65536, + "id": "611635946735140874", + "global_name": null, + "display_name": null, + "discriminator": "1822", + "bot": true, + "avatar_decoration_data": null, + "avatar": "5daeb8010c26b282f66541c8bc98ce39" + }, + "roles": [ "1177893477829324852" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-25T08:48:09.350814+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "proteusoftheice", + "public_flags": 0, + "id": "1090976231375257610", + "global_name": "╞ñ╞ª╤│╧»╤öß╣╗┼ƒ, The One", + "display_name": "╞ñ╞ª╤│╧»╤öß╣╗┼ƒ, The One", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "7a06dd6f7b4594da00dd2a8e0878b50c" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1135643322132738170", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T17:38:41.617000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "cubtheman", + "public_flags": 128, + "id": "178586875949350912", + "global_name": "Cub", + "display_name": "Cub", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f5736abd829050906265cd0dd5a6109a" + }, + "roles": [ "1163353762816086016", "1150634635815039138", "1137195462189916262", "1132495232991244298", "1131855863930425394", "1139366614492532787", "1140025493027029171", "1153154189288030259", "1173489923450470453", "1154509955290894427", "1150638639483723806" ], + "premium_since": null, + "pending": false, + "nick": "[PURDY GANG] Cub", + "mute": false, + "joined_at": "2023-09-10T12:53:18.532000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "classypepe", + "public_flags": 0, + "id": "757462480795729930", + "global_name": "classypepe", + "display_name": "classypepe", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ffd7baa2b75c2bcb70885862303e97d0" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T14:15:57.862000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "vwtax", + "public_flags": 0, + "id": "1142657728775458930", + "global_name": null, + "display_name": null, + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "2a56fea53f78e48e42acbb0f18a07c0e" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T03:55:21.643000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "magic_clown", + "public_flags": 0, + "id": "1056030770814263326", + "global_name": "Magic_Clown", + "display_name": "Magic_Clown", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f459305a33e07f515a0270dffae2f9ba" + }, + "roles": [ "1154848133143089312", "1169450276873314374", "1132495232991244298", "1151025333206794321", "1140025493027029171", "1150604748303646744", "1135643322132738170", "1138881285482369084" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-04T01:12:43.389000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "AAPL", + "public_flags": 65536, + "id": "806569145184550922", + "global_name": null, + "display_name": null, + "discriminator": "4501", + "bot": true, + "avatar_decoration_data": null, + "avatar": "d4208b1bbd88cc999a39cd7eee03b456" + }, + "roles": [ "1132495232991244298", "1132514826179072091", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-07-23T03:28:13.564000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "anairdrop", + "public_flags": 128, + "id": "242840588745965569", + "global_name": "an Airdrop", + "display_name": "an Airdrop", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a30e248f5c46edca7ff029312dab85cf" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-25T00:55:14.785000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "dupeai", + "public_flags": 0, + "id": "1128236730496061494", + "global_name": "dupe", + "display_name": "dupe", + "discriminator": "9204", + "bot": false, + "avatar_decoration_data": null, + "avatar": "eafb4636739c0083d182e36395fe7723" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": true, + "joined_at": "2023-09-03T21:22:51.036000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "thefreemarket", + "public_flags": 0, + "id": "1084572831880318988", + "global_name": "Mr. Market", + "display_name": "Mr. Market", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "e52415af900287376dfc3bca1dab8d39" + }, + "roles": [ "1135643322132738170", "1152426486368845895", "1154972272294109194", "1157914001255178250", "1132495232991244298", "1131855863930425394", "1139361736886059058", "1151564908278853652", "1138272440754130965", "1165360991710752979", "1150604748303646744", "1147401491779424346", "1132514826179072091" ], + "premium_since": null, + "pending": false, + "nick": "[BOWL ACTUALIZED 45] Totalus", + "mute": false, + "joined_at": "2023-07-29T02:38:35.107000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "realtimechris", + "public_flags": 0, + "id": "1030016136735100928", + "global_name": "RealTimeChris", + "display_name": "RealTimeChris", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "6f708e85b83e06c2d9ff3d315c1678fc" + }, + "roles": [ "1132495232991244298", "1154509955290894427", "1132514826179072091", "1133964361317240942", "1151630267413434428", "1139726540054216784", "1136839878127128668", "1131855863930425394", "1140025493027029171", "1146278985819500635", "1138881285482369084" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-08-18T18:54:57.820000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "lilwindex4279", + "public_flags": 0, + "id": "1008893121343524945", + "global_name": "ΓÖí ≡¥æ│≡¥Æè≡¥Æì ΓÖí ≡¥æ╛≡¥Æè≡¥ÆÅ≡¥Æà≡¥Æå≡¥ÆÖ", + "display_name": "ΓÖí ≡¥æ│≡¥Æè≡¥Æì ΓÖí ≡¥æ╛≡¥Æè≡¥ÆÅ≡¥Æà≡¥Æå≡¥ÆÖ", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144058522808614923", + "asset": "a_d3da36040163ee0f9176dfe7ced45cdc" + }, + "avatar": "e875791472bca6bc934312f95bcd752a" + }, + "roles": [ "1133448992827641906", "1163915273804460082" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-25T05:09:23.403000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "p09techguruguy01", + "public_flags": 64, + "id": "321178412012011523", + "global_name": "P09-TechGuruGuy01", + "display_name": "P09-TechGuruGuy01", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "3557fc3e76a526f1b723c8239c430afd" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1153154189288030259", "1140025493027029171", "1139361736886059058", "1135643322132738170" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T03:23:32.546000+00:00", + "flags": 1, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "blazzingfire", + "public_flags": 0, + "id": "1067984356855001148", + "global_name": "Natasha", + "display_name": "Natasha", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "05c4516b959fafd2c11666e48f707795" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-27T14:59:27.133000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "iangell_", + "public_flags": 0, + "id": "786269979577417778", + "global_name": "angel", + "display_name": "angel", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "e981e4b2003d0e7fea92a0ac695ed20c" + }, + "roles": [ "1132495232991244298", "1133448992827641906" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-14T17:22:13.396000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "sagepinfu", + "public_flags": 0, + "id": "1048074759918858281", + "global_name": "SageX", + "display_name": "SageX", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "9ed778aea121de72968d51e47155f40f" + }, + "roles": [ "1144017607444402276", "1132495232991244298", "1142127501506777229", "1131855863930425394", "1139361736886059058", "1140025493027029171", "1132320097734770748" ], + "premium_since": null, + "pending": false, + "nick": "SAGE_0%", + "mute": false, + "joined_at": "2023-10-05T00:47:58.065000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "surrist", + "public_flags": 0, + "id": "1121015033472745534", + "global_name": "Surrist", + "display_name": "Surrist", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "4e5adbb571cbf519d271ff0e90cdf897" + }, + "roles": [ "1150819267453931622", "1137195462189916262", "1132495232991244298", "1131855863930425394", "1140025493027029171", "1154509955290894427", "1138881285482369084" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-11T13:51:47.232000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "xanos9597", + "public_flags": 0, + "id": "410643627648483328", + "global_name": "Γûä∩╕╗πâçX╠╖A╠╖N╠╖O╠╖S╠╖ΓòÉΓòÉΓöüΣ╕Ç", + "display_name": "Γûä∩╕╗πâçX╠╖A╠╖N╠╖O╠╖S╠╖ΓòÉΓòÉΓöüΣ╕Ç", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ceab38e2f3c2930fcff7bb7c7f15cd72" + }, + "roles": [ "1152371592911925289", "1132495232991244298", "1131855863930425394", "1140025493027029171", "1159589181316661269", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-15T21:00:07.853000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "varg", + "public_flags": 0, + "id": "701049186535079987", + "global_name": null, + "display_name": null, + "discriminator": "5761", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b1d3993eca3a764b1a7d81ba3121014b" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T10:16:25.701643+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "5feokt", + "public_flags": 0, + "id": "1174224660968263692", + "global_name": "CH3CK BYE-O", + "display_name": "CH3CK BYE-O", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": null + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-12-01T17:49:52.446325+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "xfile_zack", + "public_flags": 256, + "id": "311367925732999168", + "global_name": "XFILE - ZACK", + "display_name": "XFILE - ZACK", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "1fd7518abaa2df5fd4d0a8cb54e49863" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T04:54:08.422000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".abtronic", + "public_flags": 0, + "id": "550482489026543617", + "global_name": "abtronic", + "display_name": "abtronic", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d4ba43d4f3da6be68722e969600e9b19" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1140025493027029171", "1165360991710752979", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-12T02:59:13.565000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "BurntToastΓäó", + "public_flags": 0, + "id": "978519094703837215", + "global_name": null, + "display_name": null, + "discriminator": "7283", + "bot": false, + "avatar_decoration_data": null, + "avatar": "55b5520b2a2811b74de113b0a83d3363" + }, + "roles": [], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-22T20:52:39.703339+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "chubbsxyz", + "public_flags": 0, + "id": "804171760597336115", + "global_name": null, + "display_name": null, + "discriminator": "1876", + "bot": false, + "avatar_decoration_data": null, + "avatar": "4851ea9ca24f08e01b21d99d8d5fdc82" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-16T04:03:09.860000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "taylorst.", + "public_flags": 0, + "id": "805235025871241226", + "global_name": "Taylor St.", + "display_name": "Taylor St.", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "f081b80c588b7ded06ecfe5859c93b5c" + }, + "roles": [ "1152426486368845895", "1132495232991244298", "1131855863930425394", "1140025493027029171", "1135771402880958514", "1139361736886059058", "1136839878127128668" ], + "premium_since": null, + "pending": false, + "nick": "Taylor St.", + "mute": false, + "joined_at": "2023-07-21T13:18:26.578000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "4chanlolz", + "public_flags": 0, + "id": "740746194829180958", + "global_name": "4chanlolz", + "display_name": "4chanlolz", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "884f2a2d35745e9b1385e30308b52b4d" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": "4chanlolz", + "mute": false, + "joined_at": "2023-09-10T12:51:05.965000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "uponaburningbody", + "public_flags": 0, + "id": "1059302859088347189", + "global_name": "Midwest EMO", + "display_name": "Midwest EMO", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a_0a6edb9b63e27d145d06e53ab3fb81d5" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-21T23:47:08.916000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "t0af", + "public_flags": 0, + "id": "308150161966891009", + "global_name": "toph", + "display_name": "toph", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "be7cd031a0b59183606d77d84e641eff" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-19T18:17:42.257000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": ".m3rp.", + "public_flags": 0, + "id": "726759740650160138", + "global_name": "Merp", + "display_name": "Merp", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "7e6e3bd87e70651bfc13dba00d4e0415" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T17:31:11.739000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "≡¥òè≡¥ò₧≡¥òÆ≡¥òÿ≡¥òÜ≡¥òö", + "public_flags": 64, + "id": "197844700944793600", + "global_name": null, + "display_name": null, + "discriminator": "7490", + "bot": false, + "avatar_decoration_data": null, + "avatar": "bf4ebc64ce8887c725d9c36996a05be0" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T02:43:09.170000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "dustnana", + "public_flags": 0, + "id": "578798215420182571", + "global_name": "OUTLAW DUST (ON BOND)", + "display_name": "OUTLAW DUST (ON BOND)", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d2b8be68e17acc5c0dfac382592e0445" + }, + "roles": [ "1132495232991244298", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T02:17:12.972000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "LunaBot ≡ƒîÖ", + "public_flags": 65536, + "id": "451379187031343104", + "global_name": null, + "display_name": null, + "discriminator": "9997", + "bot": true, + "avatar_decoration_data": null, + "avatar": "71be5dabc3f593d47adbdc523b451118" + }, + "roles": [ "1132495232991244298", "1158137449407598682", "1132142645775446046" ], + "premium_since": null, + "pending": false, + "nick": "Dino Radio", + "mute": false, + "joined_at": "2023-07-22T02:50:40.987000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "damn.doom", + "public_flags": 0, + "id": "1160506752316489758", + "global_name": "&,.'`doom`'.,&", + "display_name": "&,.'`doom`'.,&", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a326d66f2446f2166132bc11425d39f9" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-17T22:31:12.616000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "0lenoname", + "public_flags": 0, + "id": "935327222582095922", + "global_name": "Ol'NoName", + "display_name": "Ol'NoName", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "c94d7e94100000a0248e8fda8557866d" + }, + "roles": [ "1132495232991244298", "1154509955290894427", "1131855863930425394", "1140025493027029171", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T00:27:01.550000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "layna.cg", + "public_flags": 0, + "id": "1153915899481423892", + "global_name": "layna", + "display_name": "layna", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b931be8793e0f80f95eea64e777e33d2" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-02T15:56:35.656000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "frostig.", + "public_flags": 0, + "id": "471449896202010654", + "global_name": "'frostig,....", + "display_name": "'frostig,....", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "9139378320c0f48404c2b8b9426a313d" + }, + "roles": [ "1132495232991244298", "1146278985819500635", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T02:33:04.316000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "HeroHarri", + "public_flags": 0, + "id": "881233615801974856", + "global_name": null, + "display_name": null, + "discriminator": "9703", + "bot": false, + "avatar_decoration_data": null, + "avatar": "12a52037362af15820a64ef62c1fa80e" + }, + "roles": [ "1132495232991244298", "1135643322132738170" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T16:53:31.956000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "genuinelygenuis", + "public_flags": 0, + "id": "1025376302351523930", + "global_name": "Genius", + "display_name": "Genius", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "b778a9323b218d20f03eb85c109af92e" + }, + "roles": [ "1132495232991244298", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-18T03:29:01.674000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "nick.jpeg", + "public_flags": 0, + "id": "209157594575536129", + "global_name": "Nick.jpeg", + "display_name": "Nick.jpeg", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d88437fecb97f58bb1b415239efe54e1" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1140025493027029171", "1154509955290894427", "1150638639483723806" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T04:01:25.456000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "MBot-Janny", + "public_flags": 0, + "id": "1142732033978814564", + "global_name": null, + "display_name": null, + "discriminator": "1308", + "bot": true, + "avatar_decoration_data": null, + "avatar": "a4c81bdbac48f332713fa7a3f7f78270" + }, + "roles": [ "1158297926116847618" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-02T07:02:25.783000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "acelogic_", + "public_flags": 256, + "id": "223984406581346304", + "global_name": "Acelogic_", + "display_name": "Acelogic_", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144059132517826601", + "asset": "a_10b9f886b513b77ccdd67c8784f1a496" + }, + "avatar": "000bc5e6392f48fbf939529f944122a9" + }, + "roles": [ "1132022472737292329", "1132495232991244298", "1142127501506777229", "1131855863930425394", "1140025493027029171", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-11T12:12:50.225000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "im14.", + "public_flags": 4194368, + "id": "1079121269385080852", + "global_name": "joe", + "display_name": "joe", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "daea9d49e5057dfed5dff9c59addfa7f" + }, + "roles": [ "1132495232991244298", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-20T02:33:04.447000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "Mouthwash", + "public_flags": 0, + "id": "615370256516644887", + "global_name": null, + "display_name": null, + "discriminator": "7122", + "bot": false, + "avatar_decoration_data": null, + "avatar": "bc4c8c5e4532f4466ead42a667c223c7" + }, + "roles": [ "1132495232991244298", "1131855863930425394", "1140025493027029171", "1165360991710752979", "1138881285482369084", "1150638639483723806" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-17T17:48:55.048000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "rumbler_channel", + "public_flags": 0, + "id": "419757783068704790", + "global_name": "RumblerΓäó", + "display_name": "RumblerΓäó", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "66d415a7b6def4242b1e60e87c268496" + }, + "roles": [ "1144017607444402276", "1165352625173180516", "1137195462189916262", "1165360991710752979", "1132495232991244298", "1132514826179072091", "1142127501506777229", "1173650979418279986", "1133448992827641906", "1131855863930425394", "1132547843064872980", "1139361736886059058", "1140025493027029171", "1144734109021769749", "1153154189288030259", "1135643322132738170", "1146278985819500635", "1136839878127128668" ], + "premium_since": null, + "pending": false, + "nick": "RumblerΓäó", + "mute": false, + "joined_at": "2023-07-22T00:45:52.731000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "donaldayyy", + "public_flags": 0, + "id": "928952095099457577", + "global_name": "donald trump", + "display_name": "donald trump", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a64d2b80e2e1eda926c8751fa20407f9" + }, + "roles": [ "1132495232991244298", "1142127501506777229" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-20T23:44:52.223000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "NVDA", + "public_flags": 65536, + "id": "836385897372581910", + "global_name": null, + "display_name": null, + "discriminator": "7361", + "bot": true, + "avatar_decoration_data": null, + "avatar": "8c8b5465b3da2786eeb821540adcdb6f" + }, + "roles": [ "1132495232991244298", "1132514826179072091", "1158137449407598682" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-07-23T03:28:59+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "zeddicus.zul.zorander", + "public_flags": 0, + "id": "976966669169733672", + "global_name": "zed", + "display_name": "zed", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ea06b1dd403679944f83bba8a3fed0b7" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1156297495857614858", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-26T12:18:26.810000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "chickensnotvegan", + "public_flags": 0, + "id": "992874426771181609", + "global_name": null, + "display_name": null, + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "0aec41bc33e82bb0fd96e2b46558f553" + }, + "roles": [ "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-09T12:09:11.937000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "killstreak5428", + "public_flags": 0, + "id": "692952507990933514", + "global_name": "Killstreak", + "display_name": "Killstreak", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a6915110451b248842e601cf223c09c0" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T06:36:16.578000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "suepaphly", + "public_flags": 64, + "id": "367445249376649217", + "global_name": null, + "display_name": null, + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ca5c8aba850c833ff1cd3c3722af66d9" + }, + "roles": [ "1137195462189916262", "1132495232991244298", "1132514826179072091", "1142127501506777229", "1133448992827641906", "1131855863930425394", "1139361736886059058", "1140025493027029171", "1147382626315935826", "1165360991710752979", "1171877369666076722", "1135643322132738170", "1154509955290894427", "1136839878127128668" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-17T09:21:37.871000+00:00", + "flags": 1, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "angelllll", + "public_flags": 0, + "id": "959729504429965313", + "global_name": null, + "display_name": null, + "discriminator": "4075", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d0ee9b931801cc70fb71fe65a589f9de" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1154509955290894427" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T05:36:05.644000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "holestiktok", + "public_flags": 64, + "id": "438480724342079489", + "global_name": "HolesTikTok - Alex", + "display_name": "HolesTikTok - Alex", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d0038c9339ca51f9df98c16d89b1af88" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-13T05:37:41.956000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "clevername64", + "public_flags": 0, + "id": "175082104886001665", + "global_name": "clevername64", + "display_name": "clevername64", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "a88dac35eae92366c83796ff29093007" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-11-12T03:51:19.092000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "pigbossu", + "public_flags": 0, + "id": "205156380632547328", + "global_name": "pigboss", + "display_name": "pigboss", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "edf3f01da311c843e07b7efcf573ac2b" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T06:13:11.788000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "jimbob5121", + "public_flags": 0, + "id": "279735841444724736", + "global_name": "jimbob", + "display_name": "jimbob", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "561faf4518e678e45b9275bda5dd6abc" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1131855863930425394" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-12-06T22:28:23.533000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "crankspinatra", + "public_flags": 0, + "id": "431013987375906816", + "global_name": "crankspinatra", + "display_name": "crankspinatra", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ca6a54b6376f27a70e8a9b9dcff93637" + }, + "roles": [ "1132495232991244298", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-12-02T00:13:05.121000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "kamikazejew", + "public_flags": 0, + "id": "621531622235308033", + "global_name": "Kamikaze Jew", + "display_name": "Kamikaze Jew", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "33989b496c5fef634b4fce40937b660e" + }, + "roles": [ "1152426486368845895", "1132495232991244298", "1131855863930425394", "1140025493027029171", "1165360991710752979", "1152389946255093911", "1154509955290894427", "1138881285482369084", "1150638639483723806" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-11T03:42:45.768000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "little.toadstool", + "public_flags": 64, + "id": "934618668866883646", + "global_name": "≡¥Æ⌐≡¥æ£≡¥ôç≡¥Æ╛ ≡¥Æ▒≡¥æÆ≡¥æÆ≡¥ôÅ≡¥ôü≡¥æÆ≡¥Æ╖≡¥ôè≡¥Æ╖", + "display_name": "≡¥Æ⌐≡¥æ£≡¥ôç≡¥Æ╛ ≡¥Æ▒≡¥æÆ≡¥æÆ≡¥ôÅ≡¥ôü≡¥æÆ≡¥Æ╖≡¥ôè≡¥Æ╖", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144048390594908212", + "asset": "a_db9baf0ba7cf449d2b027c06309dbe8d" + }, + "avatar": "cccfe75b69dea48e45f17095151d0cce" + }, + "roles": [ "1165352625173180516", "1132495232991244298", "1150637930436636752", "1133448992827641906", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-21T17:41:06.158000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "shigx", + "public_flags": 0, + "id": "480225105616568331", + "global_name": "Shig", + "display_name": "Shig", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "7e80be2e6d6edaf51509037615bf98cf" + }, + "roles": [ "1131855863930425394", "1140025493027029171", "1132495232991244298" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-12-09T03:50:29.372000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "meggymoon", + "public_flags": 64, + "id": "341659789828423709", + "global_name": "meggymoonΓ£¿", + "display_name": "meggymoonΓ£¿", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": { + "sku_id": "1144059132517826601", + "asset": "a_10b9f886b513b77ccdd67c8784f1a496" + }, + "avatar": "7cee08b9b8904786376a326b50e4d7fb" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1133448992827641906", "1138881285482369084" ], + "premium_since": null, + "pending": false, + "nick": "meggyhodl", + "mute": false, + "joined_at": "2023-10-31T00:14:51.868000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "rodoh", + "public_flags": 0, + "id": "130117433661980672", + "global_name": "---0.00-", + "display_name": "---0.00-", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ffec8c3cf45d02241e940c4128e76ee0" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-24T22:30:34.231000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "fatnig3r", + "public_flags": 0, + "id": "756544067827007498", + "global_name": "Fatpig", + "display_name": "Fatpig", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "5333ec67a497a9189c603fd3a1b23b85" + }, + "roles": [ "1132495232991244298", "1154509955290894427", "1133448992827641906", "1140025493027029171", "1146278985819500635" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T17:56:32.491000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "kimilsung", + "public_flags": 0, + "id": "247121074393841664", + "global_name": "Kim Il-Sung", + "display_name": "Kim Il-Sung", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "ae65c1197cf15a07e87958a1305c5f1e" + }, + "roles": [ "1165355605033230336", "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-21T01:15:10.179000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "peregrinus", + "public_flags": 0, + "id": "193017815232413697", + "global_name": "peregrinus", + "display_name": "peregrinus", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d68b2e176dd52da89888db7462feb63e" + }, + "roles": [ "1131855863930425394", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-10-13T01:56:01.280000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "malibumafia", + "public_flags": 64, + "id": "263930496579272715", + "global_name": "MalibuMafia", + "display_name": "MalibuMafia", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "371fc22d7edf15c3c8caf3bb44b42342" + }, + "roles": [ "1131855863930425394", "1153154189288030259", "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-23T01:52:54.067000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "sambankmanfried_ftx", + "public_flags": 0, + "id": "756772701279879188", + "global_name": "Sam Bankman-Fried", + "display_name": "Sam Bankman-Fried", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "3ecbe6d45b50bc5d5168b53752ef503e" + }, + "roles": [ "1132495232991244298", "1140025493027029171", "1145791399162294334" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-10T05:28:02.583000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "bestfriendbear", + "public_flags": 0, + "id": "1131409583294926918", + "global_name": "Friend Bear", + "display_name": "Friend Bear", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "77a183d3bc39b60b987f439cf8ebbe00" + }, + "roles": [ "1132495232991244298", "1140025493027029171" ], + "premium_since": null, + "pending": false, + "nick": null, + "mute": false, + "joined_at": "2023-09-16T03:37:54.270000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "silverenien", + "public_flags": 0, + "id": "1179873808795049990", + "global_name": "silversteuy", + "display_name": "silversteuy", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "d9137fc4d69e5fc6613840fbe307d302" + }, + "roles": [ "1132022472737292329", "1153154189288030259", "1144017607444402276" ], + "premium_since": null, + "pending": false, + "nick": "silverstein milf hunter", + "mute": false, + "joined_at": "2023-12-05T22:22:32.369000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + }, + { + "user": { + "username": "riskfreerate", + "public_flags": 0, + "id": "1141198193955196939", + "global_name": "RiskFreeRate", + "display_name": "RiskFreeRate", + "discriminator": "0", + "bot": false, + "avatar_decoration_data": null, + "avatar": "940ab95221b86505186c3222af197b63" + }, + "roles": [ "1154862022111010816", "1144017607444402276", "1132495232991244298", "1157914001255178250", "1142127501506777229", "1154851589857742898", "1140025493027029171", "1165360991710752979", "1167576534178082997", "1132514826179072091", "1136839878127128668" ], + "premium_since": null, + "pending": false, + "nick": "[MENTAL BREAK] Totalus", + "mute": false, + "joined_at": "2023-09-10T13:36:16.195000+00:00", + "flags": 0, + "deaf": false, + "communication_disabled_until": null, + "avatar": null + } + ], + "large": false, + "member_count": 197, + "version": 1701620879449, + "emojis": [ + { + "version": 1689995175210, + "roles": [], + "require_colons": true, + "name": "cub", + "managed": false, + "id": "1132146564182315069", + "available": true, + "animated": true + }, + { + "version": 1689995182331, + "roles": [], + "require_colons": true, + "name": "woodyremovebgpreview", + "managed": false, + "id": "1132146594075123752", + "available": true, + "animated": false + }, + { + "version": 1689995198991, + "roles": [], + "require_colons": true, + "name": "ram", + "managed": false, + "id": "1132146663729926275", + "available": true, + "animated": false + }, + { + "version": 1690001101007, + "roles": [], + "require_colons": true, + "name": "engineer", + "managed": false, + "id": "1132171418793152612", + "available": true, + "animated": false + }, + { + "version": 1690001316157, + "roles": [], + "require_colons": true, + "name": "suep", + "managed": false, + "id": "1132172321151520788", + "available": true, + "animated": false + }, + { + "version": 1691519993124, + "roles": [], + "require_colons": true, + "name": "red", + "managed": false, + "id": "1138542114049900544", + "available": true, + "animated": false + }, + { + "version": 1693264635956, + "roles": [], + "require_colons": true, + "name": "353055289_925417528687629_655473", + "managed": false, + "id": "1145859672771932220", + "available": true, + "animated": false + }, + { + "version": 1693264657425, + "roles": [], + "require_colons": true, + "name": "IMG_6745", + "managed": false, + "id": "1145859766380396704", + "available": true, + "animated": false + }, + { + "version": 1693525954985, + "roles": [], + "require_colons": true, + "name": "1453joethinking", + "managed": false, + "id": "1146955727823458336", + "available": true, + "animated": false + }, + { + "version": 1693525955450, + "roles": [], + "require_colons": true, + "name": "1330crykekw", + "managed": false, + "id": "1146955729849294969", + "available": true, + "animated": false + }, + { + "version": 1693525955732, + "roles": [], + "require_colons": true, + "name": "4775_Bible_Jew", + "managed": false, + "id": "1146955731044683776", + "available": true, + "animated": false + }, + { + "version": 1693525955986, + "roles": [], + "require_colons": true, + "name": "1766peepochomky", + "managed": false, + "id": "1146955732084850748", + "available": true, + "animated": false + }, + { + "version": 1693525956216, + "roles": [], + "require_colons": true, + "name": "2092ybayo", + "managed": false, + "id": "1146955733003423815", + "available": true, + "animated": false + }, + { + "version": 1693525956590, + "roles": [], + "require_colons": true, + "name": "2174pepecool", + "managed": false, + "id": "1146955734630813816", + "available": true, + "animated": false + }, + { + "version": 1693525956910, + "roles": [], + "require_colons": true, + "name": "2149gigachad", + "managed": false, + "id": "1146955735943622746", + "available": true, + "animated": false + }, + { + "version": 1693525957273, + "roles": [], + "require_colons": true, + "name": "3459_LMAO", + "managed": false, + "id": "1146955737436782632", + "available": true, + "animated": false + }, + { + "version": 1693525957883, + "roles": [], + "require_colons": true, + "name": "9650lmao", + "managed": false, + "id": "1146955740007911565", + "available": true, + "animated": false + }, + { + "version": 1693525959763, + "roles": [], + "require_colons": true, + "name": "JewLol", + "managed": false, + "id": "1146955742520287343", + "available": true, + "animated": false + }, + { + "version": 1694266817091, + "roles": [], + "require_colons": true, + "name": "projectwallstreet", + "managed": false, + "id": "1150063091061641246", + "available": true, + "animated": false + }, + { + "version": 1694624324347, + "roles": [], + "require_colons": true, + "name": "stonksmartemoji", + "managed": false, + "id": "1151562622852935860", + "available": true, + "animated": false + }, + { + "version": 1694958226297, + "roles": [], + "require_colons": true, + "name": "45", + "managed": false, + "id": "1152963109166784552", + "available": true, + "animated": false + }, + { + "version": 1695579118961, + "roles": [], + "require_colons": true, + "name": "aeye", + "managed": false, + "id": "1155567321713225798", + "available": true, + "animated": false + }, + { + "version": 1695581474925, + "roles": [], + "require_colons": true, + "name": "hand", + "managed": false, + "id": "1155577203409572001", + "available": true, + "animated": false + }, + { + "version": 1695782669036, + "roles": [], + "require_colons": true, + "name": "nuke", + "managed": false, + "id": "1156421052377866351", + "available": true, + "animated": false + }, + { + "version": 1695782743894, + "roles": [], + "require_colons": true, + "name": "nuke1", + "managed": false, + "id": "1156421360629854268", + "available": true, + "animated": false + }, + { + "version": 1695782786499, + "roles": [], + "require_colons": true, + "name": "nuke2", + "managed": false, + "id": "1156421533464535141", + "available": true, + "animated": false + }, + { + "version": 1695783780895, + "roles": [], + "require_colons": true, + "name": "johnny3", + "managed": false, + "id": "1156425736140357743", + "available": true, + "animated": false + }, + { + "version": 1696215940654, + "roles": [], + "require_colons": true, + "name": "hit", + "managed": false, + "id": "1158238332002766848", + "available": true, + "animated": false + }, + { + "version": 1698523556729, + "roles": [], + "require_colons": true, + "name": "patgasm", + "managed": false, + "id": "1167917188859048077", + "available": true, + "animated": false + }, + { + "version": 1698524694207, + "roles": [], + "require_colons": true, + "name": "bird_2", + "managed": false, + "id": "1167921959837909112", + "available": true, + "animated": false + }, + { + "version": 1698524752125, + "roles": [], + "require_colons": true, + "name": "objection20", + "managed": false, + "id": "1167922202755215533", + "available": true, + "animated": false + }, + { + "version": 1698524847624, + "roles": [], + "require_colons": true, + "name": "ur_poor", + "managed": false, + "id": "1167922603307040858", + "available": true, + "animated": false + }, + { + "version": 1699566014076, + "roles": [], + "require_colons": true, + "name": "pepogun", + "managed": false, + "id": "1167924656133652572", + "available": true, + "animated": true + }, + { + "version": 1698525337404, + "roles": [], + "require_colons": true, + "name": "6442smurfing", + "managed": false, + "id": "1167924657589071882", + "available": true, + "animated": false + }, + { + "version": 1698525337729, + "roles": [], + "require_colons": true, + "name": "ace002", + "managed": false, + "id": "1167924658893504602", + "available": true, + "animated": true + }, + { + "version": 1698525338001, + "roles": [], + "require_colons": true, + "name": "addiknight15", + "managed": false, + "id": "1167924659942080522", + "available": true, + "animated": false + }, + { + "version": 1698525338297, + "roles": [], + "require_colons": true, + "name": "addiphone76", + "managed": false, + "id": "1167924661330399344", + "available": true, + "animated": false + }, + { + "version": 1698525338705, + "roles": [], + "require_colons": true, + "name": "american", + "managed": false, + "id": "1167924663016493116", + "available": true, + "animated": true + }, + { + "version": 1698525339057, + "roles": [], + "require_colons": true, + "name": "apusad99", + "managed": false, + "id": "1167924664341889054", + "available": true, + "animated": false + }, + { + "version": 1698525339284, + "roles": [], + "require_colons": true, + "name": "autist22", + "managed": false, + "id": "1167924665482747965", + "available": true, + "animated": false + }, + { + "version": 1698525339982, + "roles": [], + "require_colons": true, + "name": "based71", + "managed": false, + "id": "1167924668368424970", + "available": true, + "animated": false + }, + { + "version": 1698525340427, + "roles": [], + "require_colons": true, + "name": "billetes74", + "managed": false, + "id": "1167924670230708315", + "available": true, + "animated": true + }, + { + "version": 1698525341277, + "roles": [], + "require_colons": true, + "name": "coggers65", + "managed": false, + "id": "1167924673514848360", + "available": true, + "animated": true + }, + { + "version": 1698525342125, + "roles": [], + "require_colons": true, + "name": "dmdollar", + "managed": false, + "id": "1167924677386186874", + "available": true, + "animated": false + }, + { + "version": 1698525342964, + "roles": [], + "require_colons": true, + "name": "expanddong91", + "managed": false, + "id": "1167924680800354315", + "available": true, + "animated": false + }, + { + "version": 1698525343751, + "roles": [], + "require_colons": true, + "name": "feelsstrongman21", + "managed": false, + "id": "1167924684206120960", + "available": true, + "animated": false + }, + { + "version": 1698525344730, + "roles": [], + "require_colons": true, + "name": "festivepepe", + "managed": false, + "id": "1167924688299769856", + "available": true, + "animated": false + }, + { + "version": 1698525345443, + "roles": [], + "require_colons": true, + "name": "ghmmnice91", + "managed": false, + "id": "1167924691218993274", + "available": true, + "animated": false + }, + { + "version": 1698525346229, + "roles": [], + "require_colons": true, + "name": "hhsalami", + "managed": false, + "id": "1167924694171787266", + "available": true, + "animated": true + }, + { + "version": 1698525347260, + "roles": [], + "require_colons": true, + "name": "kermitspaz", + "managed": false, + "id": "1167924698882003108", + "available": true, + "animated": true + }, + { + "version": 1698525347928, + "roles": [], + "require_colons": true, + "name": "lcworryrave", + "managed": false, + "id": "1167924701713158154", + "available": true, + "animated": true + }, + { + "version": 1698525348903, + "roles": [], + "require_colons": true, + "name": "memerlistening", + "managed": false, + "id": "1167924705844535328", + "available": true, + "animated": false + }, + { + "version": 1698525349608, + "roles": [], + "require_colons": true, + "name": "narutopepe", + "managed": false, + "id": "1167924708721819779", + "available": true, + "animated": false + }, + { + "version": 1698525350447, + "roles": [], + "require_colons": true, + "name": "olzking", + "managed": false, + "id": "1167924712224063548", + "available": true, + "animated": false + }, + { + "version": 1698525351459, + "roles": [], + "require_colons": true, + "name": "parrotloop1", + "managed": false, + "id": "1167924716510658561", + "available": true, + "animated": true + }, + { + "version": 1698525352095, + "roles": [], + "require_colons": true, + "name": "peepogiggle", + "managed": false, + "id": "1167924718981107823", + "available": true, + "animated": false + }, + { + "version": 1698525352919, + "roles": [], + "require_colons": true, + "name": "peeposhy", + "managed": false, + "id": "1167924722651103324", + "available": true, + "animated": false + }, + { + "version": 1698525353933, + "roles": [], + "require_colons": true, + "name": "pepearma3", + "managed": false, + "id": "1167924726862184499", + "available": true, + "animated": false + }, + { + "version": 1698525354540, + "roles": [], + "require_colons": true, + "name": "pepedance46", + "managed": false, + "id": "1167924729483632721", + "available": true, + "animated": true + }, + { + "version": 1698525355693, + "roles": [], + "require_colons": true, + "name": "pepehighking", + "managed": false, + "id": "1167924734277726248", + "available": true, + "animated": true + }, + { + "version": 1699566044820, + "roles": [], + "require_colons": true, + "name": "pepegooseking", + "managed": false, + "id": "1167924736433586247", + "available": true, + "animated": true + }, + { + "version": 1698525357131, + "roles": [], + "require_colons": true, + "name": "pepepoint12", + "managed": false, + "id": "1167924740313333801", + "available": true, + "animated": false + }, + { + "version": 1698525357942, + "roles": [], + "require_colons": true, + "name": "pepewriting", + "managed": false, + "id": "1167924743702323342", + "available": true, + "animated": false + }, + { + "version": 1698525358727, + "roles": [], + "require_colons": true, + "name": "picklericktwerki", + "managed": false, + "id": "1167924747015831602", + "available": true, + "animated": true + }, + { + "version": 1701235455793, + "roles": [], + "require_colons": true, + "name": "poker77", + "managed": false, + "id": "1167924751004610752", + "available": true, + "animated": false + }, + { + "version": 1701235455802, + "roles": [], + "require_colons": true, + "name": "renpepegamer", + "managed": false, + "id": "1167924754150326292", + "available": true, + "animated": false + }, + { + "version": 1698525361493, + "roles": [], + "require_colons": true, + "name": "saved77", + "managed": false, + "id": "1167924758583713913", + "available": true, + "animated": true + }, + { + "version": 1699566027983, + "roles": [], + "require_colons": true, + "name": "pepoduck", + "managed": false, + "id": "1167924761108676730", + "available": true, + "animated": true + }, + { + "version": 1698525363321, + "roles": [], + "require_colons": true, + "name": "signback", + "managed": false, + "id": "1167924766271873225", + "available": true, + "animated": true + }, + { + "version": 1701235455806, + "roles": [], + "require_colons": true, + "name": "soup26", + "managed": false, + "id": "1167924768645861518", + "available": true, + "animated": false + }, + { + "version": 1698525364998, + "roles": [], + "require_colons": true, + "name": "Sus", + "managed": false, + "id": "1167924773351850037", + "available": true, + "animated": true + }, + { + "version": 1701235455811, + "roles": [], + "require_colons": true, + "name": "thatstoxic77", + "managed": false, + "id": "1167924775054741544", + "available": true, + "animated": false + }, + { + "version": 1701235455815, + "roles": [], + "require_colons": true, + "name": "watching52", + "managed": false, + "id": "1167924779190341702", + "available": true, + "animated": false + }, + { + "version": 1701235455820, + "roles": [], + "require_colons": true, + "name": "yep31", + "managed": false, + "id": "1167924782013108357", + "available": true, + "animated": false + }, + { + "version": 1699566053591, + "roles": [], + "require_colons": true, + "name": "pepogun2", + "managed": false, + "id": "1167925163640242256", + "available": true, + "animated": true + }, + { + "version": 1701235455824, + "roles": [], + "require_colons": true, + "name": "6442smurfing", + "managed": false, + "id": "1167925165259247676", + "available": true, + "animated": false + }, + { + "version": 1698525458776, + "roles": [], + "require_colons": true, + "name": "ace002", + "managed": false, + "id": "1167925166622392462", + "available": true, + "animated": true + }, + { + "version": 1701235455828, + "roles": [], + "require_colons": true, + "name": "addiknight15", + "managed": false, + "id": "1167925167566106735", + "available": true, + "animated": false + }, + { + "version": 1701235455835, + "roles": [], + "require_colons": true, + "name": "apusad99", + "managed": false, + "id": "1167932289171345440", + "available": true, + "animated": false + }, + { + "version": 1701235455839, + "roles": [], + "require_colons": true, + "name": "autist22", + "managed": false, + "id": "1167932290098282658", + "available": true, + "animated": false + }, + { + "version": 1701235455854, + "roles": [], + "require_colons": true, + "name": "babypatbk", + "managed": false, + "id": "1167932291369160917", + "available": true, + "animated": false + }, + { + "version": 1701235455858, + "roles": [], + "require_colons": true, + "name": "based71", + "managed": false, + "id": "1167932292837154817", + "available": true, + "animated": false + }, + { + "version": 1701235455862, + "roles": [], + "require_colons": true, + "name": "basedg", + "managed": false, + "id": "1167932294112227348", + "available": true, + "animated": false + }, + { + "version": 1701235455866, + "roles": [], + "require_colons": true, + "name": "bedge10", + "managed": false, + "id": "1167932295395672104", + "available": true, + "animated": false + }, + { + "version": 1698527158747, + "roles": [], + "require_colons": true, + "name": "billetes74", + "managed": false, + "id": "1167932296809152573", + "available": true, + "animated": true + }, + { + "version": 1701235455872, + "roles": [], + "require_colons": true, + "name": "bloodpepeking", + "managed": false, + "id": "1167932297828368437", + "available": true, + "animated": false + }, + { + "version": 1698527159645, + "roles": [], + "require_colons": true, + "name": "coggers65", + "managed": false, + "id": "1167932300567269526", + "available": true, + "animated": true + }, + { + "version": 1698527160307, + "roles": [], + "require_colons": true, + "name": "dknplan53", + "managed": false, + "id": "1167932303348088892", + "available": true, + "animated": true + }, + { + "version": 1701235455875, + "roles": [], + "require_colons": true, + "name": "emoji1746", + "managed": false, + "id": "1167932306716098630", + "available": true, + "animated": false + }, + { + "version": 1701235455879, + "roles": [], + "require_colons": true, + "name": "feelscringeman85", + "managed": false, + "id": "1167932310499373096", + "available": true, + "animated": false + }, + { + "version": 1701235455887, + "roles": [], + "require_colons": true, + "name": "gays", + "managed": false, + "id": "1167932314060345425", + "available": true, + "animated": false + }, + { + "version": 1698527163691, + "roles": [], + "require_colons": true, + "name": "hhsalami", + "managed": false, + "id": "1167932317533208706", + "available": true, + "animated": true + }, + { + "version": 1698527164507, + "roles": [], + "require_colons": true, + "name": "knkdope", + "managed": false, + "id": "1167932320980934776", + "available": true, + "animated": true + }, + { + "version": 1698527165346, + "roles": [], + "require_colons": true, + "name": "movie94", + "managed": false, + "id": "1167932324491567235", + "available": true, + "animated": true + }, + { + "version": 1701235455890, + "roles": [], + "require_colons": true, + "name": "olzking", + "managed": false, + "id": "1167932328249663649", + "available": true, + "animated": false + }, + { + "version": 1701235455895, + "roles": [], + "require_colons": true, + "name": "peephmm", + "managed": false, + "id": "1167932331189866607", + "available": true, + "animated": false + }, + { + "version": 1701235455900, + "roles": [], + "require_colons": true, + "name": "peepowow46", + "managed": false, + "id": "1167932334926991440", + "available": true, + "animated": false + }, + { + "version": 1698527168687, + "roles": [], + "require_colons": true, + "name": "pepega", + "managed": false, + "id": "1167932338550874174", + "available": true, + "animated": true + }, + { + "version": 1698527169434, + "roles": [], + "require_colons": true, + "name": "pepekangaroo", + "managed": false, + "id": "1167932341637882017", + "available": true, + "animated": true + }, + { + "version": 1701235455904, + "roles": [], + "require_colons": true, + "name": "peppocomfy37", + "managed": false, + "id": "1167932345458884680", + "available": true, + "animated": false + }, + { + "version": 1698527385288, + "roles": [], + "require_colons": true, + "name": "pokemontwerk", + "managed": false, + "id": "1167933246986792981", + "available": true, + "animated": true + }, + { + "version": 1701235455907, + "roles": [], + "require_colons": true, + "name": "poker77", + "managed": false, + "id": "1167933248270245969", + "available": true, + "animated": false + }, + { + "version": 1701235455912, + "roles": [], + "require_colons": true, + "name": "popeyes62", + "managed": false, + "id": "1167933249482399844", + "available": true, + "animated": false + }, + { + "version": 1701235455926, + "roles": [], + "require_colons": true, + "name": "promote", + "managed": false, + "id": "1167933250321256499", + "available": true, + "animated": false + }, + { + "version": 1701235455939, + "roles": [], + "require_colons": true, + "name": "reinas57", + "managed": false, + "id": "1167933251244007495", + "available": true, + "animated": false + }, + { + "version": 1701235455957, + "roles": [], + "require_colons": true, + "name": "renpepegamer", + "managed": false, + "id": "1167933252099641376", + "available": true, + "animated": false + }, + { + "version": 1698527387063, + "roles": [], + "require_colons": true, + "name": "rotation", + "managed": false, + "id": "1167933253668315319", + "available": true, + "animated": true + }, + { + "version": 1701235455972, + "roles": [], + "require_colons": true, + "name": "sacred20", + "managed": false, + "id": "1167933255937446058", + "available": true, + "animated": false + }, + { + "version": 1698527387854, + "roles": [], + "require_colons": true, + "name": "shpepesteer", + "managed": false, + "id": "1167933257782935572", + "available": true, + "animated": true + }, + { + "version": 1701235455977, + "roles": [], + "require_colons": true, + "name": "stfuisaac", + "managed": false, + "id": "1167933261088030850", + "available": true, + "animated": false + }, + { + "version": 1698527389494, + "roles": [], + "require_colons": true, + "name": "toe33", + "managed": false, + "id": "1167933264632221826", + "available": true, + "animated": true + }, + { + "version": 1701235455981, + "roles": [], + "require_colons": true, + "name": "yep31", + "managed": false, + "id": "1167933268050583582", + "available": true, + "animated": false + }, + { + "version": 1699566077909, + "roles": [], + "require_colons": true, + "name": "pepokeeb", + "managed": false, + "id": "1172289452845047860", + "available": true, + "animated": true + }, + { + "version": 1701235455985, + "roles": [], + "require_colons": true, + "name": "Cuck", + "managed": false, + "id": "1177104085363740692", + "available": true, + "animated": false + } + ], + "discovery_splash": null, + "nsfw": false, + "max_members": 500000, + "max_stage_video_channel_users": 50 + } +} diff --git a/Include/jsonifier/Allocator.hpp b/Include/jsonifier/Allocator.hpp index 4a7eeef87..451894304 100644 --- a/Include/jsonifier/Allocator.hpp +++ b/Include/jsonifier/Allocator.hpp @@ -23,13 +23,13 @@ /// Feb 3, 2023 #pragma once -#include +#include #include namespace jsonifier_internal { - template JSONIFIER_INLINE uint64_t roundUpToMultiple(uint64_t num) { - uint64_t remainder = num % multiple; + template JSONIFIER_INLINE value_type roundUpToMultiple(value_type num) { + value_type remainder = num % multiple; return remainder == 0 ? num : num + (multiple - remainder); } @@ -40,7 +40,7 @@ namespace jsonifier_internal { #if defined(_MSC_VER) template JSONIFIER_INLINE value_type* jsonifierAlignedAlloc(uint64_t size) { - return static_cast(_aligned_malloc(roundUpToMultiple(size * sizeof(value_type)), BytesPerStep)); + return static_cast(_aligned_malloc(roundUpToMultiple(size * sizeof(value_type)), BytesPerStep)); } JSONIFIER_INLINE void jsonifierFree(void* ptr) { @@ -50,7 +50,7 @@ namespace jsonifier_internal { #else template JSONIFIER_INLINE value_type* jsonifierAlignedAlloc(uint64_t size) { - return static_cast(std::aligned_alloc(BytesPerStep, roundUpToMultiple(size * sizeof(value_type)))); + return static_cast(std::aligned_alloc(BytesPerStep, roundUpToMultiple(size * sizeof(value_type)))); } JSONIFIER_INLINE void jsonifierFree(void* ptr) { @@ -66,14 +66,14 @@ namespace jsonifier_internal { using size_type = uint64_t; JSONIFIER_INLINE pointer allocate(size_type n) { - if (n == 0) { + if (n == 0) [[unlikely]] { return nullptr; } return jsonifierAlignedAlloc(n); } JSONIFIER_INLINE void deallocate(pointer ptr, size_type) { - if (ptr) { + if (ptr) [[likely]] { jsonifierFree(ptr); } } @@ -87,7 +87,7 @@ namespace jsonifier_internal { } }; - template class alloc_wrapper : public aligned_allocator { + template class alloc_wrapper : public std::allocator_traits>, public aligned_allocator { public: using value_type = value_type_new; using pointer = value_type*; diff --git a/Include/jsonifier/Base.hpp b/Include/jsonifier/Base.hpp index b6b415338..16b7a4d55 100644 --- a/Include/jsonifier/Base.hpp +++ b/Include/jsonifier/Base.hpp @@ -32,39 +32,6 @@ namespace jsonifier_internal { - template constexpr auto indexer(std::index_sequence&&) { - return [](auto f) -> decltype(auto) { - return decltype(f)(f)(std::integral_constant{}...); - }; - } - - template constexpr auto forEach(funtion_type&& f) { - return indexer(std::make_index_sequence{})([&](auto... x) { - (std::forward>(f)(x), ...); - }); - } - - template constexpr decltype(auto) convSv(value_type&& value) noexcept { - if constexpr (std::is_convertible_v) { - return jsonifier::string_view{ value }; - } else { - return std::forward(value); - } - } - - JSONIFIER_INLINE decltype(auto) getMember(auto&& value, auto& member_ptr) { - using value_type = jsonifier::concepts::unwrap; - if constexpr (std::is_member_object_pointer_v) { - return value.*member_ptr; - } else if constexpr (std::is_pointer_v) { - return *member_ptr; - } else { - return member_ptr; - } - } - - template using member_t = decltype(getMember(std::declval(), std::declval&>())); - template class stop_watch { public: using hr_clock = std::chrono::high_resolution_clock; @@ -78,8 +45,10 @@ namespace jsonifier_internal { } JSONIFIER_INLINE stop_watch& operator=(stop_watch&& other) { - totalNumberOfTimeUnits.store(other.totalNumberOfTimeUnits.load(std::memory_order_acquire), std::memory_order_release); - startTimeInTimeUnits.store(other.startTimeInTimeUnits.load(std::memory_order_acquire), std::memory_order_release); + if (this != &other) [[likely]] { + totalNumberOfTimeUnits.store(other.totalNumberOfTimeUnits.load(std::memory_order_acquire), std::memory_order_release); + startTimeInTimeUnits.store(other.startTimeInTimeUnits.load(std::memory_order_acquire), std::memory_order_release); + } return *this; } @@ -88,8 +57,10 @@ namespace jsonifier_internal { } JSONIFIER_INLINE stop_watch& operator=(const stop_watch& other) { - totalNumberOfTimeUnits.store(other.totalNumberOfTimeUnits.load(std::memory_order_acquire), std::memory_order_release); - startTimeInTimeUnits.store(other.startTimeInTimeUnits.load(std::memory_order_acquire), std::memory_order_release); + if (this != &other) [[likely]] { + totalNumberOfTimeUnits.store(other.totalNumberOfTimeUnits.load(std::memory_order_acquire), std::memory_order_release); + startTimeInTimeUnits.store(other.startTimeInTimeUnits.load(std::memory_order_acquire), std::memory_order_release); + } return *this; } @@ -99,7 +70,7 @@ namespace jsonifier_internal { JSONIFIER_INLINE bool hasTimeElapsed() { if (std::chrono::duration_cast(hr_clock::now().time_since_epoch()) - startTimeInTimeUnits.load(std::memory_order_acquire) >= - totalNumberOfTimeUnits.load(std::memory_order_acquire)) { + totalNumberOfTimeUnits.load(std::memory_order_acquire)) [[likely]] { return true; } else { return false; @@ -107,7 +78,7 @@ namespace jsonifier_internal { } JSONIFIER_INLINE void reset(value_type newTimeValue = value_type{}) { - if (newTimeValue != value_type{}) { + if (newTimeValue != value_type{}) [[likely]] { totalNumberOfTimeUnits.store(newTimeValue, std::memory_order_release); startTimeInTimeUnits.store(std::chrono::duration_cast(hr_clock::now().time_since_epoch()), std::memory_order_release); } else { @@ -133,23 +104,17 @@ namespace jsonifier_internal { namespace jsonifier { - template constexpr auto createArray(value_types&&... args) { - constexpr auto newSize = sizeof...(value_types); - if constexpr (newSize > 0) { - return jsonifier_internal::array{ std::make_tuple(std::forward(args)...) }; - } else { - return jsonifier_internal::array{ jsonifier::concepts::empty_val{} }; - } + template constexpr decltype(auto) createScalarValue(value_types&& args) { + return scalar_value{ std::make_tuple(std::forward(args)) }; } - template constexpr auto createObject(value_types&&... args) { - constexpr auto newSize = sizeof...(value_types); - if constexpr (newSize > 0) { + template constexpr decltype(auto) createValue(value_types&&... args) { + if constexpr (sizeof...(value_types) > 0) { auto newTuple = std::make_tuple(jsonifier_internal::convSv(std::forward(args))...); using tuple_type = jsonifier::concepts::unwrap; - return jsonifier_internal::object{ jsonifier_internal::group_builder::op(std::move(newTuple)) }; + return value{ jsonifier_internal::group_builder::op(std::move(newTuple)) }; } else { - return jsonifier_internal::object{ jsonifier::concepts::empty_val{} }; + return value{ jsonifier::concepts::empty_val{} }; } } diff --git a/Include/jsonifier/CTimeVector.hpp b/Include/jsonifier/CTimeVector.hpp index d859bd974..f48c3d676 100644 --- a/Include/jsonifier/CTimeVector.hpp +++ b/Include/jsonifier/CTimeVector.hpp @@ -42,9 +42,10 @@ namespace jsonifier_internal { constexpr ctime_vector() = default; - constexpr ctime_vector(size_type count, const auto& value) : sizeVal(count) { - for (size_type x = 0; x < N; ++x) + template constexpr ctime_vector(size_type count, const value_type_newer& value) : sizeVal(count) { + for (size_type x = 0; x < N; ++x) { data[x] = value; + } } constexpr iterator begin() { @@ -84,7 +85,7 @@ namespace jsonifier_internal { } template constexpr void pushBack(value_type_newer&& a) { - data[sizeVal++] = std::forward(a); + data[sizeVal++] = static_cast(a); } constexpr void pop_back() { diff --git a/Include/jsonifier/Compare.hpp b/Include/jsonifier/Compare.hpp index aa64d7e39..692d7e6f8 100644 --- a/Include/jsonifier/Compare.hpp +++ b/Include/jsonifier/Compare.hpp @@ -27,441 +27,72 @@ namespace jsonifier_internal { -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - - template JSONIFIER_INLINE uint64_t find(const char_type01* str, uint64_t length, const char_type02* sub, uint64_t subLength = 1) { - static constexpr uint64_t vecSize = sizeof(simd_int_512); - uint64_t remainingBytes{ length }; - uint64_t index{}; - - if (subLength == 0) { - return 0; - } - auto strNew = str; - - while (remainingBytes >= vecSize) { - simd_int_512 currentVec = gatherValuesU(strNew); - - const simd_int_512 subVec = _mm512_set1_epi8(static_cast(sub[0])); - uint64_t mask = static_cast(_mm512_cmpeq_epi8_mask(subVec, currentVec)); - do { - if (mask != 0) { - uint64_t pos = tzcnt(mask); - if (memcmp(strNew + pos, sub, subLength) == 0) { - return pos + index; - } - mask = blsr(mask); - } - } while (mask != 0); - - strNew += vecSize; - index += vecSize; - remainingBytes -= vecSize; - } - - if (remainingBytes >= subLength) { - for (int64_t x = 0; x < static_cast(remainingBytes); ++x) { - if (str[index + x] == sub[0]) { - if (memcmp(str + index + x, sub, subLength) == 0) { - return index + x; - } - } - } - } - - return std::numeric_limits::max(); - } - - template JSONIFIER_INLINE bool compareValues(const value_type01* string1, const value_type02* string2, uint64_t length); - - template constexpr uint64_t getIntervalCount(uint64_t originalLength) { - return originalLength * sizeof(value_type) / sizeof(IndexType); - } - - template - JSONIFIER_INLINE bool compareValues16(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_128) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint16_t maskValue{ 0xFFFF }; - - auto destvector = gatherValuesU(string1); - auto sourcevector = gatherValuesU(string2); - if (_mm_movemask_pd(_mm_cmpeq_pd(destvector, sourcevector)) != maskValue) { - return false; - } - - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm_movemask_pd(_mm_cmpeq_pd(destvector, sourcevector)) != maskValue) { - return false; - } - } - - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - - return true; - } - - template JSONIFIER_INLINE bool compareValues16(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_128) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint16_t maskValue{ 0xFFFF }; - simd_int_128 destvector = gatherValuesU(string1); - simd_int_128 sourcevector = gatherValuesU(string2); - if (_mm_movemask_epi8(_mm_cmpeq_epi8(destvector, sourcevector)) != maskValue) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm_movemask_epi8(_mm_cmpeq_epi8(destvector, sourcevector)) != maskValue) { + using integer_list = jsonifier::concepts::type_list; + +#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_ANY_AVX) + + template JSONIFIER_INLINE bool compareShort(char_type01* string1, char_type02* string2, uint64_t lengthNew) { + #if defined(_WIN32) + using integer_type = typename jsonifier::concepts::get_type_at_index::type; + static constexpr uint64_t size{ sizeof(integer_type) }; + integer_type value01[2]{}; + while (lengthNew >= size) { + std::memcpy(value01, string1, sizeof(integer_type)); + std::memcpy(value01 + 1, string2, sizeof(integer_type)); + lengthNew -= size; + string1 += size; + string2 += size; + if (value01[0] != value01[1]) { return false; } } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - return true; - } - - template - JSONIFIER_INLINE bool compareValues32(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_256) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint32_t maskValue{ 0xFFFFFFFFu }; - simd_float_256 destvector = gatherValuesU(string1); - simd_float_256 sourcevector = gatherValuesU(string2); - if (_mm256_movemask_pd(_mm256_cmp_pd(destvector, sourcevector, _CMP_EQ_OQ)) != maskValue) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm256_movemask_pd(_mm256_cmp_pd(destvector, sourcevector, _CMP_EQ_OQ)) != maskValue) { - return false; - } - } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - return true; - } - - template JSONIFIER_INLINE bool compareValues32(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_256) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint32_t maskValue{ 0xFFFFFFFFu }; - simd_int_256 destvector = gatherValuesU(string1); - simd_int_256 sourcevector = gatherValuesU(string2); - if (_mm256_movemask_epi8(_mm256_cmpeq_epi8(destvector, sourcevector)) != maskValue) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm256_movemask_epi8(_mm256_cmpeq_epi8(destvector, sourcevector)) != maskValue) { - return false; - } - } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - return true; - } - - template - JSONIFIER_INLINE bool compareValues64(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_512) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint64_t maskValue{ 0xFFFFFFFFFFFFFFF }; - auto destvector = gatherValuesU(string1); - auto sourcevector = gatherValuesU(string2); - if (_mm512_cmpeq_epi8_mask(destvector, sourcevector) != maskValue) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm512_cmpeq_epi8_mask(destvector, sourcevector) != maskValue) { - return false; - } - } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - return true; - } - - template JSONIFIER_INLINE bool compareValues64(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_512) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint64_t maskValue{ 0xFFFFFFFFFFFFFFF }; - simd_int_512 destvector = gatherValuesU(string1); - simd_int_512 sourcevector = gatherValuesU(string2); - if (_mm512_cmpeq_epi8_mask(destvector, sourcevector) != maskValue) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm512_cmpeq_epi8_mask(destvector, sourcevector) != maskValue) { - return false; - } - } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - return true; - } - - template JSONIFIER_INLINE bool compareValues(const value_type01* string1, const value_type02* string2, uint64_t length) { - if (length >= 64) { - return compareValues64(string1, string2, length); - } else if (length >= 32) { - return compareValues32(string1, string2, length); - } else if (length >= 16) { - return compareValues16(string1, string2, length); + if constexpr (index < integer_list::size - 1) { + return compareShort(string1, string2, lengthNew); } else { - return (std::memcmp(string1, string2, length * sizeof(value_type01)) == 0); + return true; } + #else + return std::memcmp(string1, string2, lengthNew) == 0; + #endif } -#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) - - template JSONIFIER_INLINE uint64_t find(const char_type01* str, uint64_t length, const char_type02* sub, uint64_t subLength = 1) { - static constexpr uint64_t vecSize = sizeof(simd_int_256); - uint64_t remainingBytes{ length }; - uint64_t index{}; - - if (subLength == 0) { - return 0; - } - auto strNew = str; - - while (remainingBytes >= vecSize) { - simd_int_256 currentVec = gatherValuesU(strNew); - - const simd_int_256 subVec = _mm256_set1_epi8(static_cast(sub[0])); - uint32_t mask = static_cast(_mm256_movemask_epi8(_mm256_cmpeq_epi8(subVec, currentVec))); - do { - if (mask != 0) { - uint64_t pos = static_cast(tzcnt(mask)); - if (memcmp(strNew + pos, sub, subLength) == 0) { - return pos + index; - } - mask = blsr(mask); - } - } while (mask != 0); - - strNew += vecSize; - index += vecSize; - remainingBytes -= vecSize; - } - - if (remainingBytes >= subLength) { - for (int64_t x = 0; x < static_cast(remainingBytes); ++x) { - if (str[index + x] == sub[0]) { - if (memcmp(str + index + x, sub, subLength) == 0) { - return index + x; - } - } - } - } - - return std::numeric_limits::max(); - } - - template JSONIFIER_INLINE bool compareValues(const value_type01* string1, const value_type02* string2, uint64_t length); - - template constexpr uint64_t getIntervalCount(uint64_t originalLength) { - return originalLength * sizeof(value_type) / sizeof(IndexType); - } - - template - JSONIFIER_INLINE bool compareValues16(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_128) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint16_t maskValue{ 0xFFFF }; - - simd_float_128 destvector = gatherValuesU(string1); - simd_float_128 sourcevector = gatherValuesU(string2); - if (_mm_movemask_pd(_mm_cmpeq_pd(destvector, sourcevector)) != maskValue) { - return false; - } - - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm_movemask_pd(_mm_cmpeq_pd(destvector, sourcevector)) != maskValue) { + template JSONIFIER_INLINE bool compare(char_type01* string1, char_type02* string2, uint64_t lengthNew) { + using integer_type = typename jsonifier::concepts::get_type_at_index::type::integer_type; + using simd_type = typename jsonifier::concepts::get_type_at_index::type::type; + static constexpr uint64_t vectorSize = sizeof(simd_type); + static constexpr integer_type maskValue{ jsonifier::concepts::get_type_at_index::type::mask }; + while (lengthNew >= vectorSize) { + if (simd_base::cmpeq(gatherValuesU(string1), gatherValuesU(string2)) != maskValue) { return false; } + string1 += vectorSize; + string2 += vectorSize; + lengthNew -= vectorSize; } - - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - - return true; - } - - template JSONIFIER_INLINE bool compareValues16(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_128) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint16_t maskValue{ 0xFFFF }; - simd_int_128 destvector = gatherValuesU(string1); - simd_int_128 sourcevector = gatherValuesU(string2); - if (_mm_movemask_epi8(_mm_cmpeq_epi8(destvector, sourcevector)) != maskValue) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm_movemask_epi8(_mm_cmpeq_epi8(destvector, sourcevector)) != maskValue) { - return false; + if constexpr (index < avx_list::size - 1) { + if (lengthNew > 0) { + return compare(string1, string2, lengthNew); } - } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); + } else if (lengthNew > 0) { + return compareShort(string1, string2, lengthNew); } return true; } - template - JSONIFIER_INLINE bool compareValues32(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_256) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint32_t maskValue{ 0xFFFFFFFFu }; - simd_float_256 destvector = gatherValuesU(string1); - simd_float_256 sourcevector = gatherValuesU(string2); - if (_mm256_movemask_pd(_mm256_cmp_pd(destvector, sourcevector, _CMP_EQ_OQ)) != maskValue) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm256_movemask_pd(_mm256_cmp_pd(destvector, sourcevector, _CMP_EQ_OQ)) != maskValue) { - return false; - } - } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - return true; - } - - template JSONIFIER_INLINE bool compareValues32(const value_type01* string1, const value_type02* string2, uint64_t length) { - static constexpr uint64_t vectorSize = sizeof(simd_int_256) / sizeof(value_type01); - const uint64_t intervalCount = getIntervalCount(length); - const uint64_t remainder = length % vectorSize; - static constexpr uint32_t maskValue{ 0xFFFFFFFFu }; - simd_int_256 destvector = gatherValuesU(string1); - simd_int_256 sourcevector = gatherValuesU(string2); - if (_mm256_movemask_epi8(_mm256_cmpeq_epi8(destvector, sourcevector)) != static_cast(maskValue)) { - return false; - } - for (uint64_t x = 1; x < intervalCount; ++x) { - destvector = gatherValuesU(string1 + x * vectorSize); - sourcevector = gatherValuesU(string2 + x * vectorSize); - if (_mm256_movemask_epi8(_mm256_cmpeq_epi8(destvector, sourcevector)) != static_cast(maskValue)) { - return false; - } - } - if (remainder > 0) { - return compareValues(string1 + (vectorSize * intervalCount), string2 + (vectorSize * intervalCount), remainder); - } - return true; - } - - template JSONIFIER_INLINE bool compareValues(const value_type01* string1, const value_type02* string2, uint64_t length) { - if (length >= 32) { - return compareValues32(string1, string2, length); - } else if (length >= 16) { - return compareValues16(string1, string2, length); - } else { - return (std::memcmp(string1, string2, length * sizeof(value_type01)) == 0); - } - } - -#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) - - template JSONIFIER_INLINE uint64_t find(const char_type01* str, uint64_t length, const char_type02* sub, uint64_t subLength = 1) { - static constexpr uint64_t vecSize = sizeof(simd_int_128); - uint64_t remainingBytes{ length }; - uint64_t index{}; - - if (subLength == 0) { - return 0; - } - auto strNew = str; - - while (remainingBytes >= vecSize) { - simd_int_128 currentVec = gatherValuesU(strNew); - - const simd_int_128 subVec = _mm_set1_epi8(static_cast(sub[0])); - uint16_t mask = static_cast(_mm_movemask_epi8(_mm_cmpeq_epi8(subVec, currentVec))); - do { - if (mask != 0) { - uint64_t pos = static_cast(tzcnt(mask)); - if (memcmp(strNew + pos, sub, subLength) == 0) { - return pos + index; - } - mask = blsr(mask); - } - } while (mask != 0); - - strNew += vecSize; - index += vecSize; - remainingBytes -= vecSize; - } - - if (remainingBytes >= subLength) { - for (int64_t x = 0; x < static_cast(remainingBytes); ++x) { - if (str[index + x] == sub[0]) { - if (memcmp(str + index + x, sub, subLength) == 0) { - return index + x; - } - } - } - } - - return std::numeric_limits::max(); - } - - template JSONIFIER_INLINE bool compareValues(const value_type01* string1, const value_type02* string2, uint64_t length) { - return (std::memcmp(string1, string2, length * sizeof(value_type01)) == 0); - } - #else - template JSONIFIER_INLINE uint64_t find(const value_type01* str, uint64_t length, value_type02* target, uint64_t subLength = 1) { - std::basic_string_view> newString{ target, subLength }; - return std::basic_string_view{ static_cast(str), length }.find(newString); - } - - template JSONIFIER_INLINE bool compareValues(const void* destvector, const void* sourcevector, uint64_t length) { - return std::basic_string_view>{ static_cast(destvector), length } == - std::basic_string_view>{ static_cast(sourcevector), length }; + JSONIFIER_INLINE bool compare(const void* string1, const void* string2, uint64_t lengthNew) { + std::basic_string_view> string01{ static_cast(string1), lengthNew }; + std::basic_string_view> string02{ static_cast(string2), lengthNew }; + return string01 == string02; } #endif class jsonifier_core_internal { public: - template - JSONIFIER_INLINE static bool compare(const value_type01* destvector, const value_type02* sourcevector, uint64_t length) { - return compareValues(destvector, sourcevector, length); + template JSONIFIER_INLINE static bool compare(const value_type01* string1, const value_type02* string2, uint64_t lengthNew) { + return jsonifier_internal::compare(string1, string2, lengthNew); } }; diff --git a/Include/jsonifier/Derailleur.hpp b/Include/jsonifier/Derailleur.hpp index 77bb5f005..e467f6aa2 100644 --- a/Include/jsonifier/Derailleur.hpp +++ b/Include/jsonifier/Derailleur.hpp @@ -33,11 +33,11 @@ namespace jsonifier_internal { return static_cast(currentValue) == value; } - template<> JSONIFIER_INLINE bool containsValue(uint8_t value) { + template<> JSONIFIER_INLINE bool containsValue(uint8_t value) { return value == 0x74u || value == 0x66u; } - template<> JSONIFIER_INLINE bool containsValue(uint8_t value) { + template<> JSONIFIER_INLINE bool containsValue(uint8_t value) { return numberTable[value]; } @@ -46,118 +46,114 @@ namespace jsonifier_internal { using size_type = uint64_t; template JSONIFIER_INLINE static bool checkForMatchClosed(iterator&& iter) { - if (containsValue(*iter)) { + if (containsValue(*iter)) [[likely]] { ++iter; return true; - } else { + } else [[unlikely]] { return false; } } template JSONIFIER_INLINE static bool checkForMatchClosed(iterator&& iter, iterator&& end, std::source_location location = std::source_location::current()) { - auto oldValue = *iter; - if (containsValue(*iter)) { + if (containsValue(*iter)) [[likely]] { ++iter; return true; - } else { - auto oldIter = iter; + } else [[unlikely]] { skipValue(iter, end); return false; } } - template JSONIFIER_INLINE static bool checkForMatchOpen(iterator&& iter) { - if (*iter == static_cast(c)) { + template JSONIFIER_INLINE static bool checkForMatchOpen(iterator&& iter) { + if (*iter == c) [[likely]] { ++iter; return true; - } else { + } else [[unlikely]] { return false; } } + template JSONIFIER_INLINE static void skipKey(iterator&& iter) { + ++iter; + return; + } + template JSONIFIER_INLINE static void skipKey(iterator&& iter, iterator&& end) { - if constexpr (std::same_as, jsonifier::jsonifier_core>, iterator>) { - ++iter; - return; - } else { - ++iter; - while (iter != end) { - switch (*iter) { - case 0x22u: { - ++iter; - return; - } - default: { + ++iter; + while (iter != end) { + switch (*iter) { + [[unlikely]] case 0x22u : { + ++iter; + return; + } + [[likely]] default : { ++iter; break; } - } } } } template JSONIFIER_INLINE static void skipToEndOfArray(iterator&& iter) { size_type currentDepth{ 1 }; - while (iter != iter && currentDepth > 0) { + while (iter && currentDepth > 0) { switch (*iter) { - case 0x5B: { + [[unlikely]] case 0x5B : { ++currentDepth; ++iter; break; } - case 0x5D: { + [[unlikely]] case 0x5D : { --currentDepth; ++iter; break; } - default: { - ++iter; - break; - } + [[likely]] default : { + ++iter; + break; + } } } } template JSONIFIER_INLINE static void skipToEndOfObject(iterator&& iter) { size_type currentDepth{ 1 }; - while (iter != iter && currentDepth > 0) { + while (iter && currentDepth > 0) { switch (*iter) { - case 0x7B: { + [[unlikely]] case 0x7B : { ++currentDepth; ++iter; break; } - case 0x7D: { + [[unlikely]] case 0x7D : { --currentDepth; ++iter; break; } - default: { - ++iter; - break; - } + [[likely]] default : { + ++iter; + break; + } } } } template JSONIFIER_INLINE static void skipToNextValue(iterator&& iter) { - while (iter != iter && *iter != 0x2Cu) { + while (iter && *iter != 0x2Cu) { switch (*iter) { - case 0x7B: { - skipObject(std::forward(iter)); + [[unlikely]] case 0x7B : { + skipObject(iter); break; } - case 0x5B: { - skipArray(std::forward(iter)); + [[unlikely]] case 0x5B : { + skipArray(iter); break; } - case 0x00ll: { - return; - } - default: { - ++iter; - } + [[unlikely]] case 0x00ll : { return; } + [[likely]] default : { + ++iter; + } } } } @@ -165,98 +161,142 @@ namespace jsonifier_internal { template JSONIFIER_INLINE static void skipToNextValue(iterator&& iter, iterator&& end) { while (iter != end && *iter != 0x2Cu) { switch (*iter) { - case 0x7B: { - skipObject(std::forward(iter), std::forward(end)); + [[unlikely]] case 0x7B : { + skipObject(iter, end); break; } - case 0x5B: { - skipArray(std::forward(iter), std::forward(end)); + [[unlikely]] case 0x5B : { + skipArray(iter, end); break; } - case 0x00ll: { - return; - } - default: { - ++iter; - } + [[unlikely]] case 0x00ll : { return; } + [[likely]] default : { + ++iter; + } } } } template JSONIFIER_INLINE static void skipValue(iterator&& iter) { switch (*iter) { - case 0x7B: { - skipObject(std::forward(iter)); + [[unlikely]] case 0x7B : { + skipObject(iter); break; } - case 0x5B: { - skipArray(std::forward(iter)); + [[unlikely]] case 0x5B : { + skipArray(iter); break; } - case 0x00ll: { - return; - } - default: { - ++iter; - } + [[unlikely]] case 0x00ll : { return; } + [[likely]] default : { + ++iter; + } } } template JSONIFIER_INLINE static void skipValue(iterator&& iter, iterator&& end) { switch (*iter) { - case 0x7B: { - skipObject(std::forward(iter), std::forward(end)); + [[unlikely]] case 0x7B : { + skipObject(iter, end); break; } - case 0x5B: { - skipArray(std::forward(iter), std::forward(end)); + [[unlikely]] case 0x5B : { + skipArray(iter, end); break; } - case 0x00ll: { - return; - } - default: { - ++iter; - } + [[unlikely]] case 0x00ll : { return; } + [[likely]] default : { + ++iter; + } } } - template JSONIFIER_INLINE static size_type countValueElements(iterator iter, iterator end) { + template JSONIFIER_INLINE static size_type countValueElements(iterator iter) { + auto newValue = *iter; size_type currentDepth{ 1 }; - size_type currentCount{ 0 }; - while (iter != end && currentDepth > 0) { + if (newValue == ']' || newValue == '}') [[unlikely]] { + return 0; + } + size_type currentCount{ 1 }; + while (iter && currentDepth > 0) { switch (*iter) { - case 0x5B: { + [[unlikely]] case 0x5B : { ++currentDepth; ++iter; break; } - case 0x5D: { + [[unlikely]] case 0x5D : { --currentDepth; ++iter; break; } - case 0x7B: { + [[unlikely]] case 0x7B : { ++currentDepth; ++iter; break; } - case 0x7D: { + [[unlikely]] case 0x7D : { --currentDepth; ++iter; break; } - case 0x2Cu: { - if (currentDepth == 1) { + [[unlikely]] case 0x2Cu : { + if (currentDepth == 1) [[likely]] { ++currentCount; } ++iter; break; } - default: { + [[likely]] default : { + ++iter; + break; + } + } + } + ++iter; + return currentCount; + } + + template JSONIFIER_INLINE static size_type countValueElements(iterator iter, iterator end) { + size_type currentDepth{ 1 }; + ++iter; + if (*iter == ']' || *iter == '}') [[unlikely]] { + return 0; + } + size_type currentCount{ 1 }; + while (iter != end && currentDepth > 0) { + switch (*iter) { + [[unlikely]] case 0x5B : { + ++currentDepth; + ++iter; + break; + } + [[unlikely]] case 0x5D : { + --currentDepth; + ++iter; + break; + } + [[unlikely]] case 0x7B : { + ++currentDepth; + ++iter; + break; + } + [[unlikely]] case 0x7D : { + --currentDepth; + ++iter; + break; + } + [[unlikely]] case 0x2Cu : { + if (currentDepth == 1) [[likely]] { + ++currentCount; + } ++iter; break; } + [[likely]] default : { + ++iter; + break; + } } } return currentCount; @@ -266,22 +306,22 @@ namespace jsonifier_internal { template JSONIFIER_INLINE static void skipObject(iterator&& iter) { ++iter; size_type currentDepth{ 1 }; - while (iter != iter && currentDepth > 0) { + while (iter && currentDepth > 0) { switch (*iter) { - case 0x7B: { + [[unlikely]] case 0x7B : { ++currentDepth; ++iter; break; } - case 0x7D: { + [[unlikely]] case 0x7D : { --currentDepth; ++iter; break; } - default: { - ++iter; - break; - } + [[likely]] default : { + ++iter; + break; + } } } } @@ -291,20 +331,20 @@ namespace jsonifier_internal { size_type currentDepth{ 1 }; while (iter != end && currentDepth > 0) { switch (*iter) { - case 0x7B: { + [[unlikely]] case 0x7B : { ++currentDepth; ++iter; break; } - case 0x7D: { + [[unlikely]] case 0x7D : { --currentDepth; ++iter; break; } - default: { - ++iter; - break; - } + [[likely]] default : { + ++iter; + break; + } } } } @@ -312,22 +352,22 @@ namespace jsonifier_internal { template JSONIFIER_INLINE static void skipArray(iterator&& iter) { ++iter; size_type currentDepth{ 1 }; - while (iter != iter && currentDepth > 0) { + while (iter && currentDepth > 0) { switch (*iter) { - case 0x5B: { + [[unlikely]] case 0x5B : { ++currentDepth; ++iter; break; } - case 0x5D: { + [[unlikely]] case 0x5D : { --currentDepth; ++iter; break; } - default: { - ++iter; - break; - } + [[likely]] default : { + ++iter; + break; + } } } } @@ -337,20 +377,20 @@ namespace jsonifier_internal { size_type currentDepth{ 1 }; while (iter != end && currentDepth > 0) { switch (*iter) { - case 0x5B: { + [[unlikely]] case 0x5B : { ++currentDepth; ++iter; break; } - case 0x5D: { + [[unlikely]] case 0x5D : { --currentDepth; ++iter; break; } - default: { - ++iter; - break; - } + [[likely]] default : { + ++iter; + break; + } } } } diff --git a/Include/jsonifier/Error.hpp b/Include/jsonifier/Error.hpp index 74c760863..cc3f436b3 100644 --- a/Include/jsonifier/Error.hpp +++ b/Include/jsonifier/Error.hpp @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -49,27 +48,27 @@ namespace jsonifier_internal { Serialize_Error = 11 }; - enum class json_structural_type : uint8_t { - Unset = 0x00u, - Object_Start = 0x7Bu, - Object_End = 0x7Du, - Array_Start = 0x5Bu, - Array_End = 0x5Du, - String = 0x22u, - Bool = 0x74u, - Number = 0x2Du, - Colon = 0x3Au, - Comma = 0x2Cu, - Null = 0x6Eu + enum json_structural_type : uint8_t { + Jsonifier_Unset = 0x00u, + Jsonifier_Object_Start = 0x7Bu, + Jsonifier_Object_End = 0x7Du, + Jsonifier_Array_Start = 0x5Bu, + Jsonifier_Array_End = 0x5Du, + Jsonifier_String = 0x22u, + Jsonifier_Bool = 0x74u, + Jsonifier_Number = 0x2Du, + Jsonifier_Colon = 0x3Au, + Jsonifier_Comma = 0x2Cu, + Jsonifier_Null = 0x6Eu }; - inline std::unordered_map errorMap{ { error_code::Success, "Success" }, { error_code::Parse_Error, "Parse Error." }, + JSONIFIER_INLINE std::unordered_map errorMap{ { error_code::Success, "Success" }, { error_code::Parse_Error, "Parse Error." }, { error_code::Number_Error, "Number Error." }, { error_code::Unknown_Key, "Unknown Key" }, { error_code::Incorrect_Type, "Incorrect Type" }, { error_code::Setup_Error, "Setup Error." }, { error_code::Inadequate_String_Length, "Inadequate String Length" }, { error_code::Key_Parsing_Error, "Key Parsing Error" } }; JSONIFIER_INLINE bool isTypeType(uint8_t c) { static constexpr uint8_t array01[]{ "0123456789-ftn\"{[" }; - return find(array01, std::size(array01), &c, 1) != jsonifier::string::npos; + return jsonifier::string_view_base{ array01, std::size(array01) }.find(c) != jsonifier::string::npos; } JSONIFIER_INLINE bool isDigitType(uint8_t c) { @@ -84,17 +83,17 @@ namespace jsonifier_internal { static constexpr jsonifier::string_view str{ "String" }; static constexpr jsonifier::string_view null{ "Null" }; static constexpr jsonifier::string_view unset{ "Unset" }; - if (isDigitType(charToCheck)) { + if (isDigitType(charToCheck)) [[likely]] { return number; - } else if (charToCheck == 0x74u || charToCheck == 0x66u) { + } else if (charToCheck == 0x74u || charToCheck == 0x66u) [[likely]] { return boolean; - } else if (charToCheck == 0x7B) { + } else if (charToCheck == 0x7B) [[unlikely]] { return object; - } else if (charToCheck == 0x5B) { + } else if (charToCheck == 0x5B) [[unlikely]] { return array; - } else if (charToCheck == 0x22u) { + } else if (charToCheck == 0x22u) [[unlikely]] { return str; - } else if (charToCheck == 0x6Eu) { + } else if (charToCheck == 0x6Eu) [[unlikely]] { return null; } else { return unset; @@ -102,7 +101,7 @@ namespace jsonifier_internal { } JSONIFIER_INLINE error_code collectMisReadType(uint8_t c, uint8_t currentValue) { - if (isTypeType(currentValue) && isTypeType(c)) { + if (isTypeType(currentValue) && isTypeType(c)) [[likely]] { return error_code::Wrong_Type; } else { return error_code::Damaged_Input; @@ -120,7 +119,7 @@ namespace jsonifier_internal { intendedValue = static_cast(typeNew); errorIndex = static_cast(iter.getCurrentStringIndex()); errorIndexReal = roundDownToMultiple(static_cast(iter.getCurrentStringIndex())); - if (errorIndexReal < jsonifier::string{}.maxSize()) { + if (errorIndexReal < jsonifier::string{}.max_size()) { stringView = iter.getRootPtr(); } stringLength = static_cast(iter.getEndPtr() - iter.getRootPtr()); @@ -133,7 +132,7 @@ namespace jsonifier_internal { JSONIFIER_INLINE error(const iterator& iter, error_code typeNew, std::source_location locationNew = std::source_location::current()) noexcept { errorIndex = static_cast(iter.getCurrentStringIndex()); errorIndexReal = roundDownToMultiple(static_cast(iter.getCurrentStringIndex())); - if (errorIndexReal < jsonifier::string{}.maxSize()) { + if (errorIndexReal < jsonifier::string{}.max_size()) { stringView = iter.getRootPtr(); } location = locationNew; @@ -160,8 +159,8 @@ namespace jsonifier_internal { JSONIFIER_INLINE jsonifier::string reportError() const { #if defined(DEV) - simd_string_reader section{}; - std::string resultString{}; + simd_string_reader section{}; + jsonifier::string resultString{}; if (stringView) { resultString = section.resetWithErrorPrintOut(stringView, stringLength, errorIndexReal); } diff --git a/Include/jsonifier/Expected.hpp b/Include/jsonifier/Expected.hpp deleted file mode 100644 index 771bdc873..000000000 --- a/Include/jsonifier/Expected.hpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - MIT License - - Copyright (c) 2023 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 20, 2023 -#pragma once - -#include -#include - -namespace jsonifier_internal { - - template class unexpected { - public: - using unexpected_type = unexpected_type_new; - - template unexpected_type_newer> constexpr unexpected& operator=(unexpected_type_newer&& other) { - unex = std::forward(other); - return *this; - } - - template unexpected_type_newer> constexpr unexpected(unexpected_type_newer&& other) { - *this = std::forward(other); - } - - constexpr unexpected_type&& error() const&& { - return std::move(unex); - } - - constexpr unexpected_type& error() const& { - return unex; - } - - protected: - unexpected_type unex{}; - }; - - template class expected { - public: - using value_type = expected_type; - using pointer = value_type*; - using unexpected_type = unexpected; - - constexpr expected& operator=(expected&& other) { - std::swap(hasValue, other.hasValue); - if (hasValue) { - std::construct_at(&val, std::move(other.val)); - } else { - std::construct_at(&unex, std::move(other.unex)); - } - return *this; - } - - constexpr expected(expected&& other) : unex{} { - *this = std::move(other); - } - - constexpr expected& operator=(const expected& other) { - hasValue = other.hasValue; - if (hasValue) { - std::construct_at(&val, other.val); - } else { - std::construct_at(&unex, other.unex); - } - return *this; - } - - constexpr expected(const expected& other) : unex{} { - *this = other; - } - - template expected_type_newer> constexpr expected& operator=(expected_type_newer&& other) { - val = std::forward(other); - hasValue = true; - return *this; - } - - template expected_type_newer> constexpr expected(expected_type_newer&& other) { - *this = std::forward(other); - } - - template unexpected_type_newer> constexpr expected& operator=(unexpected_type_newer&& other) { - unex = std::forward(other); - hasValue = false; - return *this; - } - - template unexpected_type_newer> constexpr expected(unexpected_type_newer&& other) { - *this = std::forward(other); - } - - constexpr void swap(expected& other) { - std::swap(hasValue, other.hasValue); - if (hasValue) { - std::swap(val, other.val); - } else { - std::swap(unex, other.unex); - } - } - - constexpr pointer operator->() const { - return &val; - } - - constexpr value_type&& operator*() const&& { - return std::move(val); - } - - constexpr value_type& operator*() const& { - return val; - } - - constexpr explicit operator bool() const { - return hasValue; - } - - constexpr bool has_value() const { - return hasValue; - } - - constexpr value_type value() const&& { - return std::move(val); - } - - constexpr value_type value() const& { - return val; - } - - constexpr unexpected_type error() const&& { - return std::move(unex); - } - - constexpr unexpected_type error() const& { - return unex; - } - - friend constexpr bool operator==(const expected& x, const expected& y) { - if (x.hasValue == y.hasValue) { - if (x.hasValue) { - return x.val == y.val; - } else { - return x.unex == y.unex; - } - } - return false; - } - - constexpr ~expected() { - if (hasValue) { - std::destroy_at(&val); - } else { - std::destroy_at(&unex); - } - }; - - protected: - bool hasValue{}; - union { - unexpected_type unex; - value_type val; - }; - }; - -} diff --git a/Include/jsonifier/Hash.hpp b/Include/jsonifier/Hash.hpp index 84f97914a..4ee80c6d1 100644 --- a/Include/jsonifier/Hash.hpp +++ b/Include/jsonifier/Hash.hpp @@ -32,23 +32,15 @@ namespace jsonifier_internal { // https://en.wikipedia.org/wiki/Fowler�Noll�Vo_hash_function // http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param - static constexpr uint64_t fnv64OffsetBasis{ 0xcbf29ce484222325ull }; - static constexpr uint64_t fnv64Prime{ 0x00000100000001B3ull }; + constexpr uint32_t fnv64OffsetBasis{ 0x811c9dc5u }; + constexpr uint32_t fnv64Prime{ 0x01000193u }; - template constexpr uint64_t fnv1aHash(const string_t& value) { - uint64_t d{ fnv64OffsetBasis }; - for (const auto& c: value) { - d = (d ^ static_cast(c)) * static_cast(fnv64Prime); + template constexpr uint64_t fnv1aHash(const string_t& value, uint32_t seed) { + uint32_t hash = (fnv64OffsetBasis ^ seed) * fnv64Prime; + for (const auto& valueNew: value) { + hash = (hash ^ static_cast(static_cast(valueNew))) * fnv64Prime; } - return d >> 8; - } - - template constexpr uint64_t fnv1aHash(const string_t& value, uint64_t seed) { - uint64_t d = (fnv64OffsetBasis ^ seed) * static_cast(fnv64Prime); - for (const auto& c: value) { - d = (d ^ static_cast(c)) * static_cast(fnv64Prime); - } - return d >> 8; + return static_cast(hash >> 8); } template struct hash; diff --git a/Include/jsonifier/HashMap.hpp b/Include/jsonifier/HashMap.hpp index 498a298b1..5518dcd0f 100644 --- a/Include/jsonifier/HashMap.hpp +++ b/Include/jsonifier/HashMap.hpp @@ -26,7 +26,6 @@ #include #include -#include #include #include #include @@ -54,10 +53,7 @@ namespace jsonifier_internal { if (std::is_constant_evaluated()) { return stringConstCompare(std::forward(lhs), std::forward(rhs)); } else { - if (lhs.size() == rhs.size()) { - return jsonifier_core_internal::compare(lhs.data(), rhs.data(), rhs.size()); - } - return false; + return lhs.size() == rhs.size() ? jsonifier_core_internal::compare(lhs.data(), rhs.data(), rhs.size()) : false; } } }; @@ -122,19 +118,13 @@ namespace jsonifier_internal { } constexpr uint_type operator()() { - using uint_least_t = uint64_t; - uint_least_t tmp = static_cast(multiplier) * state + increment; + using uint_least_t = uint32_t; + uint_least_t tmp = multiplier * state + increment; state = modulo(tmp, std::integral_constant()); return state; } - constexpr void discard(uint64_t n) const { - while (n--) { - operator()(); - } - } - constexpr bool operator==(linear_congruential_engine const& other) const { return state == other.state; } @@ -143,15 +133,15 @@ namespace jsonifier_internal { uint_type state{ 1u }; static_assert(std::unsigned_integral, "uint_type must be an unsigned integral type."); - template static constexpr uint_type modulo(value_type value, std::integral_constant) { - return static_cast(value); + template constexpr static uint_type modulo(value_type value, std::integral_constant) { + return value; } - template static constexpr uint_type modulo(value_type value, std::integral_constant) { - return static_cast(value % m2); + template constexpr static uint_type modulo(value_type value, std::integral_constant) { + return value % m2; } }; - using default_prg_t = linear_congruential_engine; + using default_prg_t = linear_congruential_engine; // from // https://stackoverflow.com/questions/55941964/how-to-filter-duplicate-types-from-std::tuple-c @@ -174,8 +164,8 @@ namespace jsonifier_internal { template>> struct value_tuple_variant; - template struct value_tuple_variant> { - using type = typename tuple_variant>>>()...))>::type; + template struct value_tuple_variant> { + using type = typename tuple_variant>>>()...))>::type; }; template using value_tuple_variant_t = typename value_tuple_variant::type; @@ -186,12 +176,12 @@ namespace jsonifier_internal { } }; - template struct pmh_buckets { - static constexpr auto bucket_max = 2 * (1u << (log(m) / 2)); + template struct pmh_buckets { + constexpr static auto bucketMax = 2 * (1u << (log(m) / 2)); - using bucket_t = ctime_vector; + using bucket_t = ctime_vector; std::array buckets; - uint64_t seed; + uint32_t seed; struct bucket_ref { uint32_t hash; @@ -227,7 +217,7 @@ namespace jsonifier_internal { } }; - template pmh_buckets constexpr makePmhBuckets(const std::array& items) { + template pmh_buckets constexpr makePmhBuckets(const std::array& items) { default_prg_t prg{}; using result_t = pmh_buckets; using hasher = hash; @@ -240,8 +230,8 @@ namespace jsonifier_internal { result.seed = prg(); rejected = false; for (uint64_t x = 0; x < n; ++x) { - auto& bucket = result.buckets[hasher{}(items[x].first, static_cast(result.seed)) % m]; - if (bucket.size() >= result_t::bucket_max) [[unlikely]] { + auto& bucket = result.buckets[hasher{}(items[x].first, result.seed) % m]; + if (bucket.size() >= result_t::bucketMax) [[unlikely]] { rejected = true; break; } @@ -262,11 +252,11 @@ namespace jsonifier_internal { } struct seed_or_index { - using value_type = uint64_t; + using value_type = uint32_t; protected: - static constexpr value_type MinusOne = std::numeric_limits::max(); - static constexpr value_type HighBit = ~(MinusOne >> 1); + constexpr static value_type minusOne = std::numeric_limits::max(); + constexpr static value_type highBit = ~(minusOne >> 1); value_type val{ 0 }; @@ -280,39 +270,36 @@ namespace jsonifier_internal { } constexpr bool isSeed() const { - return val & HighBit; + return val & highBit; } - constexpr seed_or_index(bool isSeed, value_type value) : val(isSeed ? (value | HighBit) : (value & ~HighBit)) { + constexpr seed_or_index(bool isSeed, value_type value) : val(isSeed ? (value | highBit) : (value & ~highBit)) { } constexpr seed_or_index() = default; }; - template struct pmh_tables : public hash, - public hash>, - public hash>, - public hash> { + template struct pmh_tables : public hash, public hash> { constexpr pmh_tables() = default; - constexpr pmh_tables(uint64_t firstSeedNew, std::array firstTableNew, std::array secondTableNew) + constexpr pmh_tables(uint32_t firstSeedNew, std::array firstTableNew, std::array secondTableNew) : firstSeed{ firstSeedNew }, firstTable{ firstTableNew }, secondTable{ secondTableNew } {}; - uint64_t firstSeed{}; + uint32_t firstSeed{}; std::array firstTable{}; std::array secondTable{}; template using hasher = hash; template constexpr uint64_t lookup(const key_type& key) const { - auto const d = m > 0 ? firstTable[hasher::operator()(key, static_cast(firstSeed)) % m] : seed_or_index{}; + auto const d = m > 0 ? firstTable[hasher::operator()(key, firstSeed) % m] : seed_or_index{}; if (!d.isSeed()) [[unlikely]] { - return m > 0 ? static_cast(d.value()) : 0; + return m > 0 ? d.value() : 0; } else [[likely]] { - return m > 0 ? secondTable[hasher::operator()(key, static_cast(d.value())) % m] : 0; + return m > 0 ? secondTable[hasher::operator()(key, d.value()) % m] : 0; } } }; - template pmh_tables constexpr makePmhTables(const std::array& items) { + template pmh_tables constexpr makePmhTables(const std::array& items) { default_prg_t prg{}; auto stepOne = makePmhBuckets(items); auto buckets = stepOne.getSortedBuckets(); @@ -328,10 +315,10 @@ namespace jsonifier_internal { auto const bsize = bucket.size(); if (bsize == 1) { - G[bucket.hash] = { false, static_cast(bucket[0]) }; + G[bucket.hash] = { false, bucket[0] }; } else if (bsize > 1) { seed_or_index d{ true, prg() }; - ctime_vector bucketSlots; + ctime_vector bucketSlots; while (bucketSlots.size() < bsize) { auto slot = hasher{}(items[bucket[bucketSlots.size()]].first, d.value()) % m; @@ -362,7 +349,7 @@ namespace jsonifier_internal { protected string_compare_helper, protected pmh_tables { public: - static constexpr auto storageSize = nextHighestPowerOfTwo(n) * (n < 32 ? 2 : 1); + constexpr static auto storageSize = nextHighestPowerOfTwo(n) * (n < 32 ? 2 : 1); using container_type = std::array, n>; using tables_type = pmh_tables; @@ -383,8 +370,8 @@ namespace jsonifier_internal { } template constexpr const_iterator find(key_type_newer&& keyNew) const { - auto kv = static_cast(tables_type::lookup(keyNew)); - auto newIter = container_type::begin() + kv; + auto kv = tables_type::lookup(keyNew); + auto newIter = container_type::begin() + static_cast(kv); if (key_equal::operator()(newIter->first, keyNew)) { return newIter; } else { @@ -393,15 +380,15 @@ namespace jsonifier_internal { } }; - template constexpr auto makeMapImpl(std::index_sequence) { + template constexpr auto makeMapImpl(std::index_sequence) { using value_t = value_tuple_variant_t>; constexpr auto n = std::tuple_size_v>; if constexpr (n == 0) { return unordered_map{}; } else { - static_assert(sizeof...(I) == n); + static_assert(sizeof...(indices) == n); return unordered_map({ std::pair( - jsonifier::string_view(get<0>(get(jsonifier::concepts::coreV))), get<1>(get(jsonifier::concepts::coreV)))... }); + jsonifier::string_view(get<0>(get(jsonifier::concepts::coreV))), get<1>(get(jsonifier::concepts::coreV)))... }); } } diff --git a/Include/jsonifier/ISA/AVX.hpp b/Include/jsonifier/ISA/AVX.hpp new file mode 100644 index 000000000..4e6e733bb --- /dev/null +++ b/Include/jsonifier/ISA/AVX.hpp @@ -0,0 +1,86 @@ +/* + MIT License + + Copyright (c) 2023 RealTimeChris + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ +/// https://github.com/RealTimeChris/jsonifier +/// Feb 3, 2023 +#pragma once + +#include + +namespace jsonifier_internal { + +#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) + + using avx_list = jsonifier::concepts::type_list::max()>>; + + using avx_integer_list = jsonifier::concepts::type_list, + jsonifier::concepts::type_holder<8, uint64_t, uint64_t, 8>, jsonifier::concepts::type_holder<1, uint8_t, uint8_t, 2>>; + + template JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(simd_int_t01&& value, simd_int_t02&& other) { + return static_cast( + _mm_movemask_epi8(_mm_cmpeq_epi8(std::forward(std::forward(value)), std::forward(other)))); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opShuffle(simd_int_t01&& value, simd_int_t02&& other) { + return _mm_shuffle_epi8(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAndNot(simd_int_t01&& value, simd_int_t02&& other) { + return _mm_andnot_si128(std::forward(other), std::forward(value)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAnd(simd_int_t01&& value, simd_int_t02&& other) { + return _mm_and_si128(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opXor(simd_int_t01&& value, simd_int_t02&& other) { + return _mm_xor_si128(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opOr(simd_int_t01&& value, simd_int_t02&& other) { + return _mm_or_si128(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::setLSB(simd_int_t01&& value, bool valueNew) { + jsonifier::concepts::unwrap mask = _mm_set_epi64x(0x00ll, 0x01ll); + return valueNew ? _mm_or_si128(value, mask) : _mm_andnot_si128(mask, value); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opNot(simd_int_t01&& value) { + return _mm_xor_si128(std::forward(value), _mm_set1_epi64x(0xFFFFFFFFFFFFFFFFll)); + } + + template JSONIFIER_INLINE bool simd_base::getMSB(simd_int_t01&& value) { + simd_int_t result = _mm_and_si128(std::forward(value), _mm_set_epi64x(0x8000000000000000ll, 0x00ll)); + return !_mm_testz_si128(result, result); + } + + template JSONIFIER_INLINE bool simd_base::opBool(simd_int_t01&& value) { + return !_mm_testz_si128(value, value); + } + + JSONIFIER_INLINE simd_int_t simd_base::reset() { + return _mm_setzero_si128(); + } + +#endif + +} \ No newline at end of file diff --git a/Include/jsonifier/ISA/AVX2.hpp b/Include/jsonifier/ISA/AVX2.hpp new file mode 100644 index 000000000..824631edc --- /dev/null +++ b/Include/jsonifier/ISA/AVX2.hpp @@ -0,0 +1,88 @@ +/* + MIT License + + Copyright (c) 2023 RealTimeChris + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ +/// https://github.com/RealTimeChris/jsonifier +/// Feb 3, 2023 +#pragma once + +#include + +namespace jsonifier_internal { + +#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) + + using avx_list = jsonifier::concepts::type_list::max()>, + jsonifier::concepts::type_holder<16, simd_int_128, uint16_t, std::numeric_limits::max()>>; + + using avx_integer_list = + jsonifier::concepts::type_list, jsonifier::concepts::type_holder<16, simd_int_128, uint16_t, 16>, + jsonifier::concepts::type_holder<8, uint64_t, uint64_t, 8>, jsonifier::concepts::type_holder<1, uint8_t, uint8_t, 2>>; + + template JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(simd_int_t01&& value, simd_int_t02&& other) { + return static_cast( + _mm256_movemask_epi8(_mm256_cmpeq_epi8(std::forward(std::forward(value)), std::forward(other)))); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opShuffle(simd_int_t01&& value, simd_int_t02&& other) { + return _mm256_shuffle_epi8(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAndNot(simd_int_t01&& value, simd_int_t02&& other) { + return _mm256_andnot_si256(std::forward(other), std::forward(value)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAnd(simd_int_t01&& value, simd_int_t02&& other) { + return _mm256_and_si256(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opXor(simd_int_t01&& value, simd_int_t02&& other) { + return _mm256_xor_si256(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opOr(simd_int_t01&& value, simd_int_t02&& other) { + return _mm256_or_si256(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::setLSB(simd_int_t01&& value, bool valueNew) { + jsonifier::concepts::unwrap mask = _mm256_set_epi64x(0x00ll, 0x00ll, 0x00ll, 0x01ll); + return valueNew ? _mm256_or_si256(value, mask) : _mm256_andnot_si256(mask, value); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opNot(simd_int_t01&& value) { + return _mm256_xor_si256(std::forward(value), _mm256_set1_epi64x(0xFFFFFFFFFFFFFFFFll)); + } + + template JSONIFIER_INLINE bool simd_base::getMSB(simd_int_t01&& value) { + simd_int_t result = _mm256_and_si256(std::forward(value), _mm256_set_epi64x(0x8000000000000000ll, 0x00ll, 0x00ll, 0x00ll)); + return !_mm256_testz_si256(result, result); + } + + template JSONIFIER_INLINE bool simd_base::opBool(simd_int_t01&& value) { + return !_mm256_testz_si256(value, value); + } + + JSONIFIER_INLINE simd_int_t simd_base::reset() { + return _mm256_setzero_si256(); + } + +#endif + +} \ No newline at end of file diff --git a/Include/jsonifier/ISA/AVX512.hpp b/Include/jsonifier/ISA/AVX512.hpp new file mode 100644 index 000000000..49392dbfe --- /dev/null +++ b/Include/jsonifier/ISA/AVX512.hpp @@ -0,0 +1,88 @@ +/* + MIT License + + Copyright (c) 2023 RealTimeChris + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ +/// https://github.com/RealTimeChris/jsonifier +/// Feb 3, 2023 +#pragma once + +#include + +namespace jsonifier_internal { + +#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) + + using avx_list = jsonifier::concepts::type_list::max()>, + jsonifier::concepts::type_holder<32, simd_int_512, uint32_t, std::numeric_limits::max()>, + jsonifier::concepts::type_holder<16, simd_int_128, uint16_t, std::numeric_limits::max()>>; + + using avx_integer_list = jsonifier::concepts::type_list::max()>, + jsonifier::concepts::type_holder<32, simd_int_512, uint32_t, 32>, jsonifier::concepts::type_holder<16, simd_int_128, uint16_t, 16>, + jsonifier::concepts::type_holder<8, uint64_t, uint64_t, 8>, jsonifier::concepts::type_holder<1, uint8_t, uint8_t, 2>>; + + template JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(simd_int_t01&& value, simd_int_t02&& other) { + return static_cast(_mm512_cmpeq_epi8_mask(value, other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opShuffle(simd_int_t01&& value, simd_int_t02&& other) { + return _mm512_shuffle_epi8(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAndNot(simd_int_t01&& value, simd_int_t02&& other) { + return _mm512_andnot_si512(std::forward(other), std::forward(value)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAnd(simd_int_t01&& value, simd_int_t02&& other) { + return _mm512_and_si512(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opXor(simd_int_t01&& value, simd_int_t02&& other) { + return _mm512_xor_si512(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opOr(simd_int_t01&& value, simd_int_t02&& other) { + return _mm512_or_si512(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::setLSB(simd_int_t01&& value, bool valueNew) { + jsonifier::concepts::unwrap mask = _mm512_set_epi64(0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x01ll); + return valueNew ? _mm512_or_si512(value, mask) : _mm512_andnot_si512(mask, value); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opNot(simd_int_t01&& value) { + return _mm512_xor_si512(std::forward(value), _mm512_set1_epi64(0xFFFFFFFFFFFFFFFFll)); + } + + template JSONIFIER_INLINE bool simd_base::getMSB(simd_int_t01&& value) { + simd_int_t result = _mm512_and_si512(value, _mm512_set_epi64(0x8000000000000000ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll)); + return _mm512_test_epi64_mask(result, result); + } + + template JSONIFIER_INLINE bool simd_base::opBool(simd_int_t01&& value) { + return _mm512_test_epi64_mask(value, value); + } + + JSONIFIER_INLINE simd_int_t simd_base::reset() { + return _mm512_setzero_si512(); + } + +#endif + +} \ No newline at end of file diff --git a/Include/jsonifier/ISADetection/Bmi.hpp b/Include/jsonifier/ISA/Bmi.hpp similarity index 69% rename from Include/jsonifier/ISADetection/Bmi.hpp rename to Include/jsonifier/ISA/Bmi.hpp index 71206cd8e..bbc89d862 100644 --- a/Include/jsonifier/ISADetection/Bmi.hpp +++ b/Include/jsonifier/ISA/Bmi.hpp @@ -23,7 +23,7 @@ /// Feb 3, 2023 #pragma once -#include +#include namespace jsonifier_internal { @@ -31,19 +31,23 @@ namespace jsonifier_internal { #include - template JSONIFIER_INLINE value_type blsr(value_type value) { - return static_cast(_blsr_u32(static_cast(value))); - } - - template JSONIFIER_INLINE value_type blsr(value_type value) { + template JSONIFIER_INLINE value_type blsr(value_type value) { return _blsr_u32(value); } - template JSONIFIER_INLINE value_type blsr(value_type value) { + template JSONIFIER_INLINE value_type blsr(value_type value) { return _blsr_u64(value); } - template JSONIFIER_INLINE value_type tzcnt(value_type value) { + template JSONIFIER_INLINE value_type tzcnt(value_type value) { + #if defined(__linux__) + return static_cast(__tzcnt_u16(static_cast(value))); + #else + return static_cast(_tzcnt_u16(static_cast(value))); + #endif + } + + template JSONIFIER_INLINE value_type tzcnt(value_type value) { #if defined(__linux__) return __tzcnt_u16(value); #else @@ -51,11 +55,11 @@ namespace jsonifier_internal { #endif } - template JSONIFIER_INLINE value_type tzcnt(value_type value) { + template JSONIFIER_INLINE value_type tzcnt(value_type value) { return _tzcnt_u32(value); } - template JSONIFIER_INLINE value_type tzcnt(value_type value) { + template JSONIFIER_INLINE value_type tzcnt(value_type value) { return _tzcnt_u64(value); } diff --git a/Include/jsonifier/ISADetection/Bmi2.hpp b/Include/jsonifier/ISA/Bmi2.hpp similarity index 89% rename from Include/jsonifier/ISADetection/Bmi2.hpp rename to Include/jsonifier/ISA/Bmi2.hpp index 4845fe32d..fa5c4c67e 100644 --- a/Include/jsonifier/ISADetection/Bmi2.hpp +++ b/Include/jsonifier/ISA/Bmi2.hpp @@ -23,7 +23,7 @@ /// Feb 3, 2023 #pragma once -#include +#include namespace jsonifier_internal { @@ -33,7 +33,7 @@ namespace jsonifier_internal { #else - template JSONIFIER_INLINE value_type pdep(value_type src, value_type mask) { + template JSONIFIER_INLINE value_type pdep(value_type src, value_type mask) { value_type result = 0; value_type src_bit = 1; diff --git a/Include/jsonifier/ISA/Fallback.hpp b/Include/jsonifier/ISA/Fallback.hpp new file mode 100644 index 000000000..6fa1f8954 --- /dev/null +++ b/Include/jsonifier/ISA/Fallback.hpp @@ -0,0 +1,159 @@ +/* + MIT License + + Copyright (c) 2023 RealTimeChris + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ +/// https://github.com/RealTimeChris/jsonifier +/// Feb 3, 2023 +#pragma once + +#include + +namespace jsonifier_internal { + +#if !JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) && !JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) && !JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) + + using avx_list = jsonifier::concepts::type_list::max()>>; + + using avx_integer_list = jsonifier::concepts::type_list, + jsonifier::concepts::type_holder<8, uint64_t, uint64_t, 8>, jsonifier::concepts::type_holder<1, uint8_t, uint8_t, 2>>; + + template JSONIFIER_INLINE string_parsing_type _mm128_movemask_epi8(simd_int_t01&& a, std::index_sequence&&) { + string_parsing_type mask{ 0 }; + ((mask |= (a.m128x_int8[indices] & 0x80) ? (1 << indices) : 0), ...); + return mask; + } + + template JSONIFIER_INLINE simd_int_t _mm128_or_si128(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + simd_int_t value{}; + memcpy(value.m128x_uint64, valOne.m128x_uint64, sizeof(value)); + value.m128x_uint64[0] |= valTwo.m128x_uint64[0]; + value.m128x_uint64[1] |= valTwo.m128x_uint64[1]; + return value; + } + + template JSONIFIER_INLINE simd_int_t _mm128_and_si128(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + simd_int_t value{}; + memcpy(value.m128x_uint64, valOne.m128x_uint64, sizeof(value)); + value.m128x_uint64[0] &= valTwo.m128x_uint64[0]; + value.m128x_uint64[1] &= valTwo.m128x_uint64[1]; + return value; + } + + template JSONIFIER_INLINE simd_int_t _mm128_andnot_si128(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + simd_int_t value{}; + memcpy(value.m128x_uint64, valTwo.m128x_uint64, sizeof(value)); + value.m128x_uint64[0] &= ~valOne.m128x_uint64[0]; + value.m128x_uint64[1] &= ~valOne.m128x_uint64[1]; + return value; + } + + template JSONIFIER_INLINE simd_int_t _mm128_xor_si128(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + simd_int_t value{}; + memcpy(value.m128x_uint64, valOne.m128x_uint64, sizeof(value)); + value.m128x_uint64[0] ^= valTwo.m128x_uint64[0]; + value.m128x_uint64[1] ^= valTwo.m128x_uint64[1]; + return value; + } + + template + JSONIFIER_INLINE simd_int_t _mm128_cmpeq_epi8(simd_int_t01&& a, simd_int_t02&& b, std::index_sequence&&) { + simd_int_t result{}; + ((result.m128x_int8[indices] = (a.m128x_int8[indices] == b.m128x_int8[indices]) ? 0xFF : 0), ...); + return result; + } + + JSONIFIER_INLINE bool _mm128_testz_si128(simd_int_t& valOne, simd_int_t& valTwo) { + valOne.m128x_uint64[0] &= valTwo.m128x_uint64[0]; + valOne.m128x_uint64[1] &= valTwo.m128x_uint64[1]; + return valOne.m128x_uint64[0] == 0 && valOne.m128x_uint64[1] == 0; + } + + JSONIFIER_INLINE simd_int_t _mm128_set_epi64x(uint64_t argOne, uint64_t argTwo) { + simd_int_t returnValue{}; + std::memcpy(&returnValue.m128x_uint64[0], &argTwo, sizeof(uint64_t)); + std::memcpy(&returnValue.m128x_uint64[1], &argOne, sizeof(uint64_t)); + return returnValue; + } + + JSONIFIER_INLINE simd_int_t _mm128_set1_epi64x(uint64_t argOne) { + simd_int_t returnValue{}; + std::memcpy(&returnValue.m128x_uint64[0], &argOne, sizeof(uint64_t)); + std::memcpy(&returnValue.m128x_uint64[1], &argOne, sizeof(uint64_t)); + return returnValue; + } + + template + JSONIFIER_INLINE simd_int_t _mm128_shuffle_epi8(simd_int_t01&& a, simd_int_t02&& b, std::index_sequence) { + simd_int_t result{}; + uint64_t index{}; + (((index = b.m128x_uint8[indices] & 0x0F), (result.m128x_uint8[indices] = a.m128x_uint8[index])), ...); + return result; + } + + template JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(simd_int_t01&& value, simd_int_t02&& other) { + return static_cast(_mm128_movemask_epi8( + _mm128_cmpeq_epi8(std::forward(value), std::forward(other), std::make_index_sequence<16>{}), std::make_index_sequence<16>{})); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opShuffle(simd_int_t01&& value, simd_int_t02&& other) { + return _mm128_shuffle_epi8(std::forward(value), std::forward(other), std::make_index_sequence<16>{}); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAndNot(simd_int_t01&& value, simd_int_t02&& other) { + return _mm128_andnot_si128(std::forward(other), std::forward(value)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opAnd(simd_int_t01&& value, simd_int_t02&& other) { + return _mm128_and_si128(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opXor(simd_int_t01&& value, simd_int_t02&& other) { + return _mm128_xor_si128(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opOr(simd_int_t01&& value, simd_int_t02&& other) { + return _mm128_or_si128(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE simd_int_t simd_base::setLSB(simd_int_t01&& value, bool valueNew) { + jsonifier::concepts::unwrap mask = _mm128_set_epi64x(0x00ll, 0x01ll); + return valueNew ? _mm128_or_si128(value, mask) : _mm128_andnot_si128(mask, value); + } + + template JSONIFIER_INLINE simd_int_t simd_base::opNot(simd_int_t01&& value) { + return _mm128_xor_si128(std::forward(value), _mm128_set1_epi64x(0xFFFFFFFFFFFFFFFFll)); + } + + template JSONIFIER_INLINE bool simd_base::getMSB(simd_int_t01&& value) { + simd_int_t result = _mm128_and_si128(std::forward(value), _mm128_set_epi64x(0x8000000000000000ll, 0x00ll)); + return !_mm128_testz_si128(result, result); + } + + template JSONIFIER_INLINE bool simd_base::opBool(simd_int_t01&& value) { + return !_mm128_testz_si128(value, value); + } + + JSONIFIER_INLINE simd_int_t simd_base::reset() { + return simd_int_t{}; + } + +#endif + +} \ No newline at end of file diff --git a/Include/jsonifier/ISA/ISADetectionBase.hpp b/Include/jsonifier/ISA/ISADetectionBase.hpp new file mode 100644 index 000000000..1e20619d8 --- /dev/null +++ b/Include/jsonifier/ISA/ISADetectionBase.hpp @@ -0,0 +1,450 @@ +/* + MIT License + + Copyright (c) 2023 RealTimeChris + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ +/// https://github.com/RealTimeChris/jsonifier +/// Feb 3, 2023 +#pragma once + +#if !defined(__GNUC__) + #pragma warning(disable : 4820) + #pragma warning(disable : 5045) + #pragma warning(disable : 5246) +#endif + +#if defined(__clang__) && defined(NDEBUG) && !defined(JSONIFIER_INLINE) + #define JSONIFIER_INLINE inline __attribute__((always_inline)) +#elif !defined(JSONIFIER_INLINE) + #define JSONIFIER_INLINE inline +#endif + +#if !defined(JSONIFIER_CPU_INSTRUCTIONS) + #define JSONIFIER_CPU_INSTRUCTIONS 0 +#endif + +#if !defined JSONIFIER_ALIGN + #define JSONIFIER_ALIGN alignas(BytesPerStep) +#endif + +#if !defined(JSONIFIER_CHECK_FOR_INSTRUCTION) + #define JSONIFIER_CHECK_FOR_INSTRUCTION(x) (JSONIFIER_CPU_INSTRUCTIONS & x) +#endif + +#if !defined(JSONIFIER_CHECK_FOR_AVX) + #define JSONIFIER_CHECK_FOR_AVX(x) (JSONIFIER_CPU_INSTRUCTIONS >= x) +#endif + +#if !defined(JSONIFIER_POPCNT) + #define JSONIFIER_POPCNT (1 << 0) +#endif +#if !defined(JSONIFIER_LZCNT) + #define JSONIFIER_LZCNT (1 << 1) +#endif +#if !defined(JSONIFIER_BMI) + #define JSONIFIER_BMI (1 << 2) +#endif +#if !defined(JSONIFIER_BMI2) + #define JSONIFIER_BMI2 (1 << 3) +#endif +#if !defined(JSONIFIER_AVX) + #define JSONIFIER_AVX (1 << 4) +#endif +#if !defined(JSONIFIER_AVX2) + #define JSONIFIER_AVX2 (1 << 5) +#endif +#if !defined(JSONIFIER_AVX512) + #define JSONIFIER_AVX512 (1 << 6) +#endif + +#if !defined(JSONIFIER_ANY) + #define JSONIFIER_ANY (JSONIFIER_AVX | JSONIFIER_AVX2 | JSONIFIER_AVX512 | JSONIFIER_POPCNT | JSONIFIER_BMI | JSONIFIER_BMI2 | JSONIFIER_LZCNT) +#endif + +#if !defined(JSONIFIER_ANY_AVX) + #define JSONIFIER_ANY_AVX (JSONIFIER_AVX | JSONIFIER_AVX2 | JSONIFIER_AVX512) +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_ANY) + + #include + +#endif + +#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_ANY_AVX) + +using simd_int_512 = __m512i; +using simd_int_256 = __m256i; +using simd_int_128 = __m128i; +using simd_float_512 = __m512d; +using simd_float_256 = __m256d; +using simd_float_128 = __m128d; + +#else + +union __m128x { + #if defined(_WIN32) + int8_t m128x_int8[16]{}; + int16_t m128x_int16[8]; + int32_t m128x_int32[4]; + int64_t m128x_int64[2]; + uint8_t m128x_uint8[16]; + int16_t m128x_uint16[8]; + int32_t m128x_uint32[4]; + uint64_t m128x_uint64[2]; + #else + int64_t m128x_int64[2]; + int8_t m128x_int8[16]{}; + int16_t m128x_int16[8]; + int32_t m128x_int32[4]; + uint8_t m128x_uint8[16]; + int16_t m128x_uint16[8]; + int32_t m128x_uint32[4]; + uint64_t m128x_uint64[2]; + #endif +}; + +using simd_int_128 = __m128x; +using simd_int_512 = int64_t; +using simd_int_256 = int32_t; + +#endif + +#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) + +constexpr uint64_t BitsPerStep{ 512 }; +using string_parsing_type = uint64_t; +using simd_int_t = simd_int_512; +template +concept simd_int_type = std::same_as>; + +#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) + +constexpr uint64_t BitsPerStep{ 256 }; +using string_parsing_type = uint32_t; +using simd_int_t = simd_int_256; +template +concept simd_int_type = std::same_as>; + +#else + +constexpr uint64_t BitsPerStep{ 128 }; +using string_parsing_type = uint16_t; +using simd_int_t = simd_int_128; +template +concept simd_int_type = std::same_as>; + +#endif + +constexpr uint64_t BytesPerStep{ BitsPerStep / 8 }; +constexpr uint64_t SixtyFourBitsPerStep{ BitsPerStep / 64 }; +constexpr uint64_t StridesPerStep{ BitsPerStep / BytesPerStep }; + +namespace jsonifier_internal { + + template + constexpr return_type createArray(const value_type (&newArray)[N], std::index_sequence) { + return return_type{ newArray[indices % N]... }; + } + + template constexpr return_type simdFromValue(uint8_t value) { +#if defined(_WIN32) + constexpr uint64_t valueSize{ sizeof(char) }; + char newArray[16]{}; + std::fill(newArray, newArray + 16, value); +#else + constexpr uint64_t valueSize{ sizeof(uint64_t) }; + int64_t newArray[16 / sizeof(int64_t)]{}; + for (size_t x = 0; x < 16; ++x) { + newArray[x / sizeof(int64_t)] |= static_cast(value) << ((x % 8) * 8); + } +#endif + return_type returnValue{ createArray(newArray, std::make_index_sequence{}) }; + return returnValue; + } + + template constexpr return_type simdFromTable(const uint8_t (&valuesNew01)[16]) { +#if defined(_WIN32) + constexpr uint64_t valueSize{ sizeof(char) }; + char newArray[16]{}; + std::copy(valuesNew01, valuesNew01 + std::size(newArray), newArray); +#else + constexpr uint64_t valueSize{ sizeof(uint64_t) }; + int64_t newArray[16 / sizeof(int64_t)]{}; + for (size_t x = 0; x < 16; ++x) { + newArray[x / sizeof(int64_t)] |= static_cast(valuesNew01[x % 16]) << ((x % 8) * 8); + } +#endif + return_type returnValue{ createArray(newArray, std::make_index_sequence{}) }; + return returnValue; + } + + template JSONIFIER_INLINE const simd_type& printBits(const simd_type& value, const std::string& valuesTitle) noexcept; + + template JSONIFIER_INLINE std::string printBits(const simd_type& value) noexcept; + + JSONIFIER_INLINE void printBits(uint64_t values, const std::string& valuesTitle); + + using string_view_ptr = const uint8_t*; + using structural_index = string_view_ptr; + using string_buffer_ptr = uint8_t*; + + template + concept simd_int_128_t = std::same_as, simd_int_128>; + + template + concept simd_int_256_t = std::same_as, simd_int_256>; + + template + concept simd_int_512_t = std::same_as, simd_int_512>; + +#if JSONIFIER_CHECK_FOR_AVX(JSONIFIER_AVX) + + template JSONIFIER_INLINE simd_int_type_new gatherValues(char_type* str) { + return _mm_load_si128(reinterpret_cast(str)); + } + + template JSONIFIER_INLINE simd_int_type_new gatherValuesU(char_type* str) { + return _mm_loadu_si128(reinterpret_cast(str)); + } + + template JSONIFIER_INLINE simd_int_type_new gatherValue(char_type str) { + return _mm_set1_epi8(str); + } + + template JSONIFIER_INLINE void store(const simd_int_type_new& value, char_type* storageLocation) { + _mm_store_si128(reinterpret_cast<__m128i*>(storageLocation), value); + } + + #if JSONIFIER_CHECK_FOR_AVX(JSONIFIER_AVX2) + + template JSONIFIER_INLINE simd_int_type_new gatherValues(char_type* str) { + return _mm256_load_si256(reinterpret_cast(str)); + } + + template JSONIFIER_INLINE simd_int_type_new gatherValuesU(char_type* str) { + return _mm256_loadu_si256(reinterpret_cast(str)); + } + + template JSONIFIER_INLINE simd_int_type_new gatherValue(char_type str) { + return _mm256_set1_epi8(str); + } + + template JSONIFIER_INLINE void store(const simd_int_type_new& value, char_type* storageLocation) { + _mm256_store_si256(reinterpret_cast<__m256i*>(storageLocation), value); + } + + #if JSONIFIER_CHECK_FOR_AVX(JSONIFIER_AVX512) + + template JSONIFIER_INLINE simd_int_type_new gatherValues(char_type* str) { + return _mm512_load_si512(str); + } + + template JSONIFIER_INLINE simd_int_type_new gatherValuesU(char_type* str) { + return _mm512_loadu_si512(reinterpret_cast(str)); + } + + template JSONIFIER_INLINE simd_int_type_new gatherValue(char_type str) { + return _mm512_set1_epi8(str); + } + + template JSONIFIER_INLINE void store(const simd_int_type_new& value, char_type* storageLocation) { + _mm512_store_si512(storageLocation, value); + } + + #endif + + #endif + +#else + + template JSONIFIER_INLINE simd_int_type_new gatherValues(char_type* str) { + simd_int_t returnValue{}; + std::memcpy(&returnValue, str, sizeof(simd_int_t)); + return returnValue; + } + + template JSONIFIER_INLINE simd_int_type_new gatherValuesU(char_type* str) { + simd_int_t returnValue{}; + std::memcpy(&returnValue, str, sizeof(simd_int_t)); + return returnValue; + } + + template JSONIFIER_INLINE simd_int_type_new gatherValue(char_type str) { + simd_int_t returnValue{}; + std::memset(&returnValue, str, sizeof(simd_int_t)); + return returnValue; + } + + template JSONIFIER_INLINE void store(const simd_int_t& value, char_type* storageLocation) { + std::memcpy(storageLocation, &value, sizeof(simd_int_t)); + } + +#endif + + static constexpr uint8_t escapeableArray00[]{ 0x00u, 0x00u, 0x22u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x08u, 0x00u, 0x00u, 0x00u, 0x0Cu, 0x0Du, 0x00u, 0x00u }; + static constexpr uint8_t escapeableArray01[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x09u, 0x0Au, 0x00u, 0x5Cu, 0x00u, 0x00u, 0x00u }; + static constexpr uint8_t whitespaceArray[]{ 0x20u, 0x64u, 0x64u, 0x64u, 0x11u, 0x64u, 0x71u, 0x02u, 0x64u, 0x09u, 0x0Au, 0x70u, 0x64u, 0x0Du, 0x64u, 0x64u }; + static constexpr uint8_t opArray[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x3Au, 0x7Bu, 0x2Cu, 0x7Du, 0x00u, 0x00u }; + template static constexpr simd_type escapeableTable00{ simdFromTable(escapeableArray00) }; + template static constexpr simd_type escapeableTable01{ simdFromTable(escapeableArray01) }; + template static constexpr simd_type whitespaceTable{ simdFromTable(whitespaceArray) }; + template static constexpr simd_type backslashes{ simdFromValue(0x5Cu) }; + template static constexpr simd_type opTable{ simdFromTable(opArray) }; + template static constexpr simd_type quotes{ simdFromValue(0x22u) }; + template static constexpr simd_type chars{ simdFromValue(0x20u) }; + + class simd_base { + public: + template JSONIFIER_INLINE static string_parsing_type cmpeq(simd_int_t01&& value, simd_int_t02&& other); + + template JSONIFIER_INLINE static simd_int_t opShuffle(simd_int_t01&& value, simd_int_t02&& other); + + template JSONIFIER_INLINE static simd_int_t opAndNot(simd_int_t01&& value, simd_int_t02&& other); + + template JSONIFIER_INLINE static simd_int_t opAnd(simd_int_t01&& value, simd_int_t02&& other); + + template JSONIFIER_INLINE static simd_int_t opXor(simd_int_t01&& value, simd_int_t02&& other); + + template JSONIFIER_INLINE static simd_int_t opOr(simd_int_t01&& value, simd_int_t02&& other); + + template JSONIFIER_INLINE static simd_int_t setLSB(simd_int_t01&& value, bool valueNew); + + template JSONIFIER_INLINE static simd_int_t opNot(simd_int_t01&& value); + + template JSONIFIER_INLINE static bool getMSB(simd_int_t01&& value); + + template JSONIFIER_INLINE static bool opBool(simd_int_t01&& value); + + JSONIFIER_INLINE static simd_int_t reset(); + + template + JSONIFIER_INLINE static std::enable_if_t, simd_int_t>, simd_int_128> opShuffle(simd_int_t01&& value, + simd_int_t02&& other) { + return _mm_shuffle_epi8(std::forward(value), std::forward(other)); + } + + template + JSONIFIER_INLINE static std::enable_if_t, simd_int_t>, uint16_t> cmpeq(simd_int_t01&& value, simd_int_t02&& other) { + return static_cast(_mm_movemask_epi8(_mm_cmpeq_epi8(value, other))); + } + + template + JSONIFIER_INLINE static std::enable_if_t, simd_int_t>, simd_int_256> opShuffle(simd_int_t01&& value, + simd_int_t02&& other) { + return _mm256_shuffle_epi8(std::forward(value), std::forward(other)); + } + + template + JSONIFIER_INLINE static std::enable_if_t, simd_int_t>, uint32_t> cmpeq(simd_int_t01&& value, simd_int_t02&& other) { + return static_cast(_mm256_movemask_epi8(_mm256_cmpeq_epi8(value, other))); + } + + template JSONIFIER_INLINE static simd_int_t collectStructuralsAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { + JSONIFIER_ALIGN string_parsing_type valuesNew[StridesPerStep]{}; + ((valuesNew[indices] = cmpeq(opShuffle(opTable, values[indices]), opOr(chars, values[indices]))), ...); + return gatherValues(valuesNew); + } + + template JSONIFIER_INLINE static simd_int_t collectWhitespaceAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { + JSONIFIER_ALIGN string_parsing_type valuesNew[StridesPerStep]{}; + ((valuesNew[indices] = cmpeq(opShuffle(whitespaceTable, values[indices]), values[indices])), ...); + return gatherValues(valuesNew); + } + + template JSONIFIER_INLINE static simd_int_t collectBackslashesAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { + JSONIFIER_ALIGN string_parsing_type valuesNew[StridesPerStep]{}; + ((valuesNew[indices] = cmpeq(backslashes, values[indices])), ...); + return gatherValues(valuesNew); + } + + template JSONIFIER_INLINE static simd_int_t collectQuotesAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { + JSONIFIER_ALIGN string_parsing_type valuesNew[StridesPerStep]{}; + ((valuesNew[indices] = cmpeq(quotes, values[indices])), ...); + return gatherValues(valuesNew); + } + + static constexpr size_t power(size_t base, size_t exponent) { + size_t result = 1; + while (exponent > 0) { + if (exponent & 1) { + result *= base; + } + base *= base; + exponent >>= 1; + } + return result; + } + + template JSONIFIER_INLINE static size_t prefixXorImpl(size_t prevInString) { + prevInString ^= prevInString << index; + return prevInString; + } + + template JSONIFIER_INLINE static size_t prefixXor(size_t prevInString, std::index_sequence) { + ((prevInString = prefixXorImpl(prevInString)), ...); + return prevInString; + } + + template + JSONIFIER_INLINE static simd_int_t carrylessMultiplication(simd_int_t01&& value, int64_t& prevInString, std::index_sequence) { + JSONIFIER_ALIGN uint64_t values[SixtyFourBitsPerStep]{}; + store(value, values); + ((values[indices] = prefixXor(values[indices], std::make_index_sequence<6>{}) ^ prevInString, prevInString = static_cast(values[indices]) >> 63), ...); + return gatherValues(values); + } + + template + JSONIFIER_INLINE static simd_int_t opSub(simd_int_t01&& value, simd_int_t01&& other, std::index_sequence) { + JSONIFIER_ALIGN uint64_t values01[SixtyFourBitsPerStep]{}; + JSONIFIER_ALIGN uint64_t values02[SixtyFourBitsPerStep]{}; + store(value, values01); + store(other, values02); + bool carryInNew{}; + ((values02[indices] = values01[indices] - values02[indices] - static_cast(carryInNew), carryInNew = values02[indices] > values01[indices]), ...); + return gatherValues(values02); + } + + template JSONIFIER_INLINE static simd_int_t shl(simd_int_t01&& value, std::index_sequence) { + JSONIFIER_ALIGN uint64_t values01[SixtyFourBitsPerStep]{}; + JSONIFIER_ALIGN uint64_t values02[SixtyFourBitsPerStep]{}; + static constexpr uint64_t shiftAmount{ 64 - amount }; + store(value, values01); + values02[0] = values01[0] << amount; + ((values02[indices + 1] = values01[indices + 1] << amount | values01[indices] >> (shiftAmount)), ...); + return gatherValues(values02); + } + + template JSONIFIER_INLINE static simd_int_t follows(simd_int_t01&& value, bool& overflow) { + bool oldOverflow = overflow; + overflow = getMSB(value); + return setLSB(shl<1>(value, std::make_index_sequence{}), oldOverflow); + } + }; + +} \ No newline at end of file diff --git a/Include/jsonifier/ISADetection/Lzcount.hpp b/Include/jsonifier/ISA/Lzcount.hpp similarity index 84% rename from Include/jsonifier/ISADetection/Lzcount.hpp rename to Include/jsonifier/ISA/Lzcount.hpp index 0b4a9c7cc..025930f07 100644 --- a/Include/jsonifier/ISADetection/Lzcount.hpp +++ b/Include/jsonifier/ISA/Lzcount.hpp @@ -23,19 +23,19 @@ /// Feb 3, 2023 #pragma once -#include +#include namespace jsonifier_internal { #if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_LZCNT) - template JSONIFIER_INLINE value_type lzcnt(value_type value) { + template JSONIFIER_INLINE value_type lzcnt(value_type value) { return _lzcnt_u32(value); } #else - template JSONIFIER_INLINE value_type lzcnt(value_type value) { + template JSONIFIER_INLINE value_type lzcnt(value_type value) { if (value == 0) { return sizeof(value_type) * 8; } diff --git a/Include/jsonifier/ISADetection/Popcount.hpp b/Include/jsonifier/ISA/Popcount.hpp similarity index 89% rename from Include/jsonifier/ISADetection/Popcount.hpp rename to Include/jsonifier/ISA/Popcount.hpp index f90d1b137..25859dd62 100644 --- a/Include/jsonifier/ISADetection/Popcount.hpp +++ b/Include/jsonifier/ISA/Popcount.hpp @@ -23,7 +23,7 @@ /// Feb 3, 2023 #pragma once -#include +#include namespace jsonifier_internal { @@ -33,7 +33,7 @@ namespace jsonifier_internal { #else - template JSONIFIER_INLINE value_type popcnt(value_type value) { + template JSONIFIER_INLINE value_type popcnt(value_type value) { value_type count{}; while (value > 0) { diff --git a/Include/jsonifier/ISA/SerialValues.hpp b/Include/jsonifier/ISA/SerialValues.hpp new file mode 100644 index 000000000..3674e5e05 --- /dev/null +++ b/Include/jsonifier/ISA/SerialValues.hpp @@ -0,0 +1,140 @@ +/* + MIT License + + Copyright (c) 2023 RealTimeChris + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ +/// https://github.com/RealTimeChris/jsonifier +/// Feb 3, 2023 +#pragma once + +#include + +namespace jsonifier_internal { + + template + JSONIFIER_INLINE string_parsing_type _mmx_movemask_epi8(simd_int_t01&& a, std::index_sequence&&) { + string_parsing_type mask{ 0 }; + ((mask |= (a.m128x_int8[indices] & 0x80) ? (1 << indices) : 0), ...); + return mask; + } + + template + JSONIFIER_INLINE simd_int_t01 _mmx_or_six(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + return valOne | valTwo; + } + + template + JSONIFIER_INLINE simd_int_t01 _mmx_and_six(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + return valOne & valTwo; + } + + template + JSONIFIER_INLINE simd_int_t01 _mmx_andnot_six(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + return valOne & ~valTwo; + } + + template + JSONIFIER_INLINE simd_int_t01 _mmx_xor_six(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + return valOne ^ valTwo; + } + + template + JSONIFIER_INLINE simd_int_t01 _mmx_cmpeq_epi8(simd_int_t01&& a, simd_int_t02&& b, std::index_sequence&&) { + simd_int_t01 result{}; + ((result.m128x_int8[indices] = (a.m128x_int8[indices] == b.m128x_int8[indices]) ? 0xFF : 0), ...); + return result; + } + + template + JSONIFIER_INLINE bool _mmx_testz_six(simd_int_t01&& valOne, simd_int_t02&& valTwo) { + valOne.m128x_uint64[0] &= valTwo.m128x_uint64[0]; + valOne.m128x_uint64[1] &= valTwo.m128x_uint64[1]; + return valOne.m128x_uint64[0] == 0 && valOne.m128x_uint64[1] == 0; + } + + template JSONIFIER_INLINE simd_int_t01 _mmx_set_epi64(simd_int_t01 argOne) { + simd_int_t01 returnValue{}; + std::memcpy(&returnValue.m128x_uint64[1], &argOne, sizeof(uint64_t)); + return returnValue; + } + + template JSONIFIER_INLINE simd_int_t01 _mmx_set1_epi64(simd_int_t01 argOne) { + simd_int_t01 returnValue{}; + std::memcpy(&returnValue.m128x_uint64[0], &argOne, sizeof(uint64_t)); + std::memcpy(&returnValue.m128x_uint64[1], &argOne, sizeof(uint64_t)); + return returnValue; + } + + template + JSONIFIER_INLINE simd_int_t01 _mmx_shuffle_epi8(simd_int_t01&& a, simd_int_t02&& b, std::index_sequence) { + simd_int_t01 result{}; + uint64_t index{}; + (((index = b.m128x_uint8[indices] & 0x0F), (result.m128x_uint8[indices] = a.m128x_uint8[index])), ...); + return result; + } + + template + JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(simd_int_t01&& value, simd_int_t02&& other) { + return static_cast(_mmx_cmpeq_epi8_mask(std::forward(value), std::forward(other))); + } + + template + JSONIFIER_INLINE simd_int_t01 simd_base::opShuffle(simd_int_t01&& value, simd_int_t02&& other) { + return _mmx_shuffle_epi8(std::forward(value), std::forward(other)); + } + + template + JSONIFIER_INLINE simd_int_t01 simd_base::opAndNot(simd_int_t01&& value, simd_int_t02&& other) { + return _mmx_andnot_six(std::forward(other), std::forward(value)); + } + + template + JSONIFIER_INLINE simd_int_t01 simd_base::opAnd(simd_int_t01&& value, simd_int_t02&& other) { + return _mmx_and_six(std::forward(value), std::forward(other)); + } + + template + JSONIFIER_INLINE simd_int_t01 simd_base::opXor(simd_int_t01&& value, simd_int_t02&& other) { + return _mmx_xor_six(std::forward(value), std::forward(other)); + } + + template + JSONIFIER_INLINE simd_int_t01 simd_base::opOr(simd_int_t01&& value, simd_int_t02&& other) { + return _mmx_or_six(std::forward(value), std::forward(other)); + } + + template JSONIFIER_INLINE integer_t_new simd_base::setLSB(integer_t_new&& value, bool valueNew) { + jsonifier::concepts::unwrap mask = _mmx_set_epi64(0x01ll); + return valueNew ? _mmx_or_six(value, mask) : _mmx_andnot_six(mask, value); + } + + template JSONIFIER_INLINE integer_t_new simd_base::opNot(integer_t_new&& value) { + return _mmx_xor_six(std::forward(value), _mmx_set1_epi64(0xFFFFFFFFFFFFFFFFll)); + } + + template JSONIFIER_INLINE bool simd_base::getMSB(integer_t_new&& value) { + integer_t_new result = _mmx_and_six(value, _mmx_set_epi64(0x8000000000000000l)); + return _mmx_test_epi64_mask(result, result); + } + + template JSONIFIER_INLINE bool simd_base::opBool(integer_t_new&& value) { + return _mmx_test_epi64_mask(value, value); + } + +} \ No newline at end of file diff --git a/Include/jsonifier/ISADetection.hpp b/Include/jsonifier/ISADetection.hpp index fe64768fa..8d42f40cf 100644 --- a/Include/jsonifier/ISADetection.hpp +++ b/Include/jsonifier/ISADetection.hpp @@ -23,17 +23,21 @@ /// Feb 3, 2023 #pragma once -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include namespace jsonifier_internal { + template constexpr value_type01 max(value_type01 value1, value_type02 value2) { + return static_cast(value1 > value2 ? value1 : value2); + } + JSONIFIER_INLINE void printBits(uint64_t values, const std::string& valuesTitle) { std::cout << valuesTitle; std::cout << std::bitset<64>{ values }; @@ -41,7 +45,7 @@ namespace jsonifier_internal { } template JSONIFIER_INLINE const simd_type& printBits(const simd_type& value, const std::string& valuesTitle) noexcept { - alignas(BytesPerStep) uint8_t values[sizeof(simd_type)]{}; + JSONIFIER_ALIGN uint8_t values[sizeof(simd_type)]{}; std::stringstream theStream{}; store(value, values); std::cout << valuesTitle; @@ -61,7 +65,7 @@ namespace jsonifier_internal { } template JSONIFIER_INLINE std::string printBits(const simd_type& value) noexcept { - alignas(BytesPerStep) uint8_t values[sizeof(simd_type)]{}; + JSONIFIER_ALIGN uint8_t values[sizeof(simd_type)]{}; std::stringstream theStream{}; store(value, values); for (uint64_t x = 0; x < BytesPerStep; ++x) { diff --git a/Include/jsonifier/ISADetection/AVX.hpp b/Include/jsonifier/ISADetection/AVX.hpp deleted file mode 100644 index bb4c28a1f..000000000 --- a/Include/jsonifier/ISADetection/AVX.hpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - MIT License - - Copyright (c) 2023 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 3, 2023 -#pragma once - -#include - -namespace jsonifier_internal { - -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) - - JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(const simd_int_t& value, const simd_int_t& other) { - return static_cast(_mm_movemask_epi8(_mm_cmpeq_epi8(value, other))); - } - - JSONIFIER_INLINE simd_int_t simd_base::opShuffle(const simd_int_t& value, const simd_int_t& other) { - return _mm_shuffle_epi8(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAndNot(const simd_int_t& value, const simd_int_t& other) { - return _mm_andnot_si128(other, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAnd(const simd_int_t& value, const simd_int_t& other) { - return _mm_and_si128(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opXor(const simd_int_t& value, const simd_int_t& other) { - return _mm_xor_si128(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opOr(const simd_int_t& value, const simd_int_t& other) { - return _mm_or_si128(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::setLSB(const simd_int_t& value, bool valueNew) { - if (valueNew) { - return _mm_or_si128(value, _mm_set_epi64x(0x00ll, 0x01ll)); - } else { - return _mm_andnot_si128(_mm_set_epi64x(0x00ll, 0x01ll), value); - } - } - - JSONIFIER_INLINE simd_int_t simd_base::opNot(const simd_int_t& value) { - return _mm_xor_si128(value, _mm_set1_epi64x(0xFFFFFFFFFFFFFFFFll)); - } - - JSONIFIER_INLINE bool simd_base::getMSB(const simd_int_t& value) { - simd_int_t result = _mm_and_si128(value, _mm_set_epi64x(0x8000000000000000ll, 0x00ll)); - return !_mm_testz_si128(result, result); - } - - JSONIFIER_INLINE bool simd_base::opBool(const simd_int_t& value) { - return !_mm_testz_si128(value, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::reset() { - return _mm_setzero_si128(); - } - -#endif - -} \ No newline at end of file diff --git a/Include/jsonifier/ISADetection/AVX2.hpp b/Include/jsonifier/ISADetection/AVX2.hpp deleted file mode 100644 index 2f8740808..000000000 --- a/Include/jsonifier/ISADetection/AVX2.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* - MIT License - - Copyright (c) 2023 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 3, 2023 -#pragma once - -#include - -namespace jsonifier_internal { - -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) - - JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(const simd_int_t& value, const simd_int_t& other) { - return static_cast(_mm256_movemask_epi8(_mm256_cmpeq_epi8(value, other))); - } - - JSONIFIER_INLINE simd_int_t simd_base::opShuffle(const simd_int_t& value, const simd_int_t& other) { - return _mm256_shuffle_epi8(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAndNot(const simd_int_t& value, const simd_int_t& other) { - return _mm256_andnot_si256(other, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAnd(const simd_int_t& value, const simd_int_t& other) { - return _mm256_and_si256(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opXor(const simd_int_t& value, const simd_int_t& other) { - return _mm256_xor_si256(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opOr(const simd_int_t& value, const simd_int_t& other) { - return _mm256_or_si256(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::setLSB(const simd_int_t& value, bool valueNew) { - simd_int_t mask = _mm256_set_epi64x(0x00ll, 0x00ll, 0x00ll, 0x01ll); - return valueNew ? _mm256_or_si256(value, mask) : _mm256_andnot_si256(mask, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::opNot(const simd_int_t& value) { - return _mm256_xor_si256(value, _mm256_set1_epi64x(0xFFFFFFFFFFFFFFFFll)); - } - - JSONIFIER_INLINE bool simd_base::getMSB(const simd_int_t& value) { - simd_int_t result = _mm256_and_si256(value, _mm256_set_epi64x(0x8000000000000000ll, 0x00ll, 0x00ll, 0x00ll)); - return !_mm256_testz_si256(result, result); - } - - JSONIFIER_INLINE bool simd_base::opBool(const simd_int_t& value) { - return !_mm256_testz_si256(value, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::reset() { - return _mm256_setzero_si256(); - } - -#endif - -} \ No newline at end of file diff --git a/Include/jsonifier/ISADetection/AVX512.hpp b/Include/jsonifier/ISADetection/AVX512.hpp deleted file mode 100644 index f8d256ed8..000000000 --- a/Include/jsonifier/ISADetection/AVX512.hpp +++ /dev/null @@ -1,83 +0,0 @@ -/* - MIT License - - Copyright (c) 2023 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 3, 2023 -#pragma once - -#include - -namespace jsonifier_internal { - -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - - JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(const simd_int_t& value, const simd_int_t& other) { - return static_cast(_mm512_cmpeq_epi8_mask(value, other)); - } - - JSONIFIER_INLINE simd_int_t simd_base::opShuffle(const simd_int_t& value, const simd_int_t& other) { - return _mm512_shuffle_epi8(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAndNot(const simd_int_t& value, const simd_int_t& other) { - return _mm512_andnot_si512(other, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAnd(const simd_int_t& value, const simd_int_t& other) { - return _mm512_and_si512(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opXor(const simd_int_t& value, const simd_int_t& other) { - return _mm512_xor_si512(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opOr(const simd_int_t& value, const simd_int_t& other) { - return _mm512_or_si512(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::setLSB(const simd_int_t& value, bool valueNew) { - if (valueNew) { - return _mm512_or_si512(value, _mm512_set_epi64(0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x01ll)); - } else { - return _mm512_andnot_si512(_mm512_set_epi64(0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x01ll), value); - } - } - - JSONIFIER_INLINE simd_int_t simd_base::opNot(const simd_int_t& value) { - return _mm512_xor_si512(value, _mm512_set1_epi64(0xFFFFFFFFFFFFFFFFll)); - } - - JSONIFIER_INLINE bool simd_base::getMSB(const simd_int_t& value) { - simd_int_t result = _mm512_and_si512(value, _mm512_set_epi64(0x8000000000000000ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll, 0x00ll)); - return _mm512_test_epi64_mask(result, result); - } - - JSONIFIER_INLINE bool simd_base::opBool(const simd_int_t& value) { - return _mm512_test_epi64_mask(value, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::reset() { - return _mm512_setzero_si512(); - } - -#endif - -} \ No newline at end of file diff --git a/Include/jsonifier/ISADetection/Fallback.hpp b/Include/jsonifier/ISADetection/Fallback.hpp deleted file mode 100644 index 45f1fd683..000000000 --- a/Include/jsonifier/ISADetection/Fallback.hpp +++ /dev/null @@ -1,176 +0,0 @@ -/* - MIT License - - Copyright (c) 2023 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 3, 2023 -#pragma once - -#include - -namespace jsonifier_internal { - -#if !JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX) && !JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) && !JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - - template JSONIFIER_INLINE void _mm128_movemask_epi8_helper00(const simd_int_t& a, int16_t& result, std::index_sequence) { - int16_t mask{}; - uint8_t value{}; - uint64_t newIndex01{}; - uint64_t newIndex02{}; - (((newIndex01 = index * 8), (newIndex02 = indices * 8), (value = (a.m128x_uint64[index] >> (newIndex02)) & 0xFF, (mask = (value >> 7) & 1)), - (result |= mask << (newIndex01 + indices))), - ...); - } - - template JSONIFIER_INLINE int16_t _mm128_movemask_epi8(const simd_int_t& a, std::index_sequence) { - int16_t result{}; - ((_mm128_movemask_epi8_helper00(a, result, std::make_index_sequence<8>{})), ...); - return result; - } - - JSONIFIER_INLINE simd_int_t _mm128_or_si128(const simd_int_t& valOne, const simd_int_t& valTwo) { - simd_int_t value{}; - value.m128x_uint64[0] = valOne.m128x_uint64[0] | valTwo.m128x_uint64[0]; - value.m128x_uint64[1] = valOne.m128x_uint64[1] | valTwo.m128x_uint64[1]; - return value; - } - - JSONIFIER_INLINE simd_int_t _mm128_and_si128(const simd_int_t& valOne, const simd_int_t& valTwo) { - simd_int_t value{}; - value.m128x_uint64[0] = valOne.m128x_uint64[0] & valTwo.m128x_uint64[0]; - value.m128x_uint64[1] = valOne.m128x_uint64[1] & valTwo.m128x_uint64[1]; - return value; - } - - JSONIFIER_INLINE simd_int_t _mm128_andnot_si128(const simd_int_t& valOne, const simd_int_t& valTwo) { - simd_int_t result{}; - result.m128x_uint64[0] = valTwo.m128x_uint64[0] & (~valOne.m128x_uint64[0]); - result.m128x_uint64[1] = valTwo.m128x_uint64[1] & (~valOne.m128x_uint64[1]); - return result; - } - - JSONIFIER_INLINE simd_int_t _mm128_xor_si128(const simd_int_t& valOne, const simd_int_t& valTwo) { - simd_int_t value{}; - value.m128x_uint64[0] = valOne.m128x_uint64[0] ^ valTwo.m128x_uint64[0]; - value.m128x_uint64[1] = valOne.m128x_uint64[1] ^ valTwo.m128x_uint64[1]; - return value; - } - - template - JSONIFIER_INLINE void _mm128_cmpeq_epi8_helper(simd_int_t& result, const simd_int_t& a, const simd_int_t& b, std::index_sequence) { - uint8_t a8{}; - uint8_t b8{}; - (((a8 = (a.m128x_uint64[index02] >> (indices * 8)) & 0xFF), (b8 = (b.m128x_uint64[index02] >> (indices * 8)) & 0xFF), - (result.m128x_uint64[index02] |= (a8 == b8 ? 0xFFull : 0) << (indices * 8))), - ...); - } - - template JSONIFIER_INLINE simd_int_t _mm128_cmpeq_epi8(const simd_int_t& a, const simd_int_t& b, std::index_sequence) { - simd_int_t result{}; - (((_mm128_cmpeq_epi8_helper(result, a, b, std::make_index_sequence<8>{})), - (result = _mm128_or_si128(result, _mm128_cmpeq_epi8(a, b, std::make_index_sequence{})))), - ...); - return result; - } - - JSONIFIER_INLINE bool _mm128_testz_si128(const simd_int_t& valOne, const simd_int_t& valTwo) { - simd_int_t result{}; - result.m128x_uint64[0] = valOne.m128x_uint64[0] & valTwo.m128x_uint64[0]; - result.m128x_uint64[1] = valOne.m128x_uint64[1] & valTwo.m128x_uint64[1]; - return result.m128x_uint64[0] == 0 && result.m128x_uint64[1] == 0; - } - - JSONIFIER_INLINE simd_int_t _mm128_set_epi64x(uint64_t argOne, uint64_t argTwo) { - simd_int_t returnValue{}; - returnValue.m128x_uint64[0] = argTwo; - returnValue.m128x_uint64[1] = argOne; - return returnValue; - } - - JSONIFIER_INLINE simd_int_t _mm128_set1_epi64x(uint64_t argOne) { - simd_int_t returnValue{}; - returnValue.m128x_uint64[0] = argOne; - returnValue.m128x_uint64[1] = argOne; - return returnValue; - } - - template JSONIFIER_INLINE simd_int_t _mm128_shuffle_epi8(const simd_int_t& a, const simd_int_t& b, std::index_sequence) { - simd_int_t result{}; - int32_t index{}; - (((index = b.m128x_uint8[indices] & 0x0F), (result.m128x_uint8[indices] = a.m128x_uint8[index])), ...); - return result; - } - - JSONIFIER_INLINE simd_int_t _mm128_setzero_si128() { - return simd_int_t{}; - } - - JSONIFIER_INLINE string_parsing_type simd_base::cmpeq(const simd_int_t& value, const simd_int_t& other) { - return static_cast(_mm128_movemask_epi8(_mm128_cmpeq_epi8(value, other, std::make_index_sequence<2>{}), std::make_index_sequence<2>{})); - } - - JSONIFIER_INLINE simd_int_t simd_base::opShuffle(const simd_int_t& value, const simd_int_t& other) { - return _mm128_shuffle_epi8(value, other, std::make_index_sequence<16>{}); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAndNot(const simd_int_t& value, const simd_int_t& other) { - return _mm128_andnot_si128(other, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::opAnd(const simd_int_t& value, const simd_int_t& other) { - return _mm128_and_si128(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opXor(const simd_int_t& value, const simd_int_t& other) { - return _mm128_xor_si128(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::opOr(const simd_int_t& value, const simd_int_t& other) { - return _mm128_or_si128(value, other); - } - - JSONIFIER_INLINE simd_int_t simd_base::setLSB(const simd_int_t& value, bool valueNew) { - if (valueNew) { - return _mm128_or_si128(value, _mm128_set_epi64x(0x00ll, 0x01ll)); - } else { - return _mm128_andnot_si128(_mm128_set_epi64x(0x00ll, 0x01ll), value); - } - } - - JSONIFIER_INLINE simd_int_t simd_base::opNot(const simd_int_t& value) { - return _mm128_xor_si128(value, _mm128_set1_epi64x(0xFFFFFFFFFFFFFFFFll)); - } - - JSONIFIER_INLINE bool simd_base::getMSB(const simd_int_t& value) { - simd_int_t result = _mm128_and_si128(value, _mm128_set_epi64x(0x8000000000000000ll, 0x00ll)); - return !_mm128_testz_si128(result, result); - } - - JSONIFIER_INLINE bool simd_base::opBool(const simd_int_t& value) { - return !_mm128_testz_si128(value, value); - } - - JSONIFIER_INLINE simd_int_t simd_base::reset() { - return _mm128_setzero_si128(); - } - -#endif - -} \ No newline at end of file diff --git a/Include/jsonifier/ISADetection/ISADetectionBase.hpp b/Include/jsonifier/ISADetection/ISADetectionBase.hpp deleted file mode 100644 index 27790a17f..000000000 --- a/Include/jsonifier/ISADetection/ISADetectionBase.hpp +++ /dev/null @@ -1,442 +0,0 @@ -/* - MIT License - - Copyright (c) 2023 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 3, 2023 -#pragma once - -#if !defined(__GNUC__) - #pragma warning(disable : 4820) - #pragma warning(disable : 5045) - #pragma warning(disable : 5246) -#endif - -#if defined(__clang__) || defined(__GNUC__) - #if !defined(JSONIFIER_USE_ALWAYS_INLINE) - #define JSONIFIER_USE_ALWAYS_INLINE - #endif -#endif - -#if defined(JSONIFIER_USE_ALWAYS_INLINE) && defined(NDEBUG) - #if !defined(JSONIFIER_INLINE) - #if defined(__clang__) - #define JSONIFIER_INLINE inline __attribute__((always_inline)) - #else - #define JSONIFIER_INLINE inline - #endif - #endif -#endif - -#if !defined(JSONIFIER_INLINE) - #define JSONIFIER_INLINE inline -#endif - -#if !defined(JSONIFIER_CPU_INSTRUCTIONS) - #define JSONIFIER_CPU_INSTRUCTIONS 0 -#endif - -#if !defined(JSONIFIER_CHECK_FOR_INSTRUCTION) - #define JSONIFIER_CHECK_FOR_INSTRUCTION(x) (JSONIFIER_CPU_INSTRUCTIONS & x) -#endif - -#if !defined(JSONIFIER_CHECK_FOR_AVX) - #define JSONIFIER_CHECK_FOR_AVX(x) (JSONIFIER_CPU_INSTRUCTIONS >= x) -#endif - -#if !defined(JSONIFIER_POPCNT) - #define JSONIFIER_POPCNT (1 << 0) -#endif -#if !defined(JSONIFIER_LZCNT) - #define JSONIFIER_LZCNT (1 << 1) -#endif -#if !defined(JSONIFIER_BMI) - #define JSONIFIER_BMI (1 << 2) -#endif -#if !defined(JSONIFIER_BMI2) - #define JSONIFIER_BMI2 (1 << 3) -#endif -#if !defined(JSONIFIER_AVX) - #define JSONIFIER_AVX (1 << 4) -#endif -#if !defined(JSONIFIER_AVX2) - #define JSONIFIER_AVX2 (1 << 5) -#endif -#if !defined(JSONIFIER_AVX512) - #define JSONIFIER_AVX512 (1 << 6) -#endif - -#if !defined(JSONIFIER_ANY) - #define JSONIFIER_ANY (JSONIFIER_AVX | JSONIFIER_AVX2 | JSONIFIER_AVX512 | JSONIFIER_POPCNT | JSONIFIER_BMI | JSONIFIER_BMI2 | JSONIFIER_LZCNT) -#endif - -#if !defined(JSONIFIER_ANY_AVX) - #define JSONIFIER_ANY_AVX (JSONIFIER_AVX | JSONIFIER_AVX2 | JSONIFIER_AVX512) -#endif - -#include -#include -#include -#include -#include -#include -#include - -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_ANY) - - #include - -#endif - -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_ANY_AVX) - -using simd_int_512 = __m512i; -using simd_int_256 = __m256i; -using simd_int_128 = __m128i; -using simd_float_512 = __m512d; -using simd_float_256 = __m256d; -using simd_float_128 = __m128d; - -#else - -union __m128x { - int8_t m128x_int8[16]{}; - int16_t m128x_int16[8]; - int32_t m128x_int32[4]; - int64_t m128x_int64[2]; - uint8_t m128x_uint8[16]; - int16_t m128x_uint16[8]; - int32_t m128x_uint32[4]; - uint64_t m128x_uint64[2]; -}; - -using simd_int_128 = __m128x; - -#endif - -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX512) - -constexpr uint64_t BitsPerStep{ 512 }; -using string_parsing_type = uint64_t; -using simd_int_t = simd_int_512; - -#elif JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_AVX2) - -constexpr uint64_t BitsPerStep{ 256 }; -using string_parsing_type = uint32_t; -using simd_int_t = simd_int_256; - -#else - -constexpr uint64_t BitsPerStep{ 128 }; -using string_parsing_type = uint16_t; -using simd_int_t = simd_int_128; - -#endif - -constexpr uint64_t BytesPerStep{ BitsPerStep / 8 }; -constexpr uint64_t SixtyFourBitsPerStep{ BitsPerStep / 64 }; -constexpr uint64_t StridesPerStep{ BitsPerStep / BytesPerStep }; - -namespace jsonifier_internal { - - template - constexpr return_type createArray(const value_type (&newArray)[N], std::index_sequence) { - return return_type{ newArray[indices % N]... }; - } - - template constexpr return_type simdFromValue(uint8_t value) { -#if defined(_WIN32) - char newArray[16]{}; - std::fill(newArray, newArray + 16, value); -#else - int64_t newArray[16 / sizeof(int64_t)]{}; - for (size_t x = 0; x < 16; ++x) { - newArray[x / sizeof(int64_t)] |= static_cast(value) << ((x % 8) * 8); - } -#endif - return_type returnValue{ createArray(newArray, std::make_index_sequence{}) }; - return returnValue; - } - - template constexpr return_type simdFromTable(const uint8_t (&valuesNew01)[16]) { -#if defined(_WIN32) - char newArray[16]{}; - std::copy(valuesNew01, valuesNew01 + std::size(newArray), newArray); -#else - int64_t newArray[16 / sizeof(int64_t)]{}; - for (size_t x = 0; x < 16; ++x) { - newArray[x / sizeof(int64_t)] |= static_cast(valuesNew01[x % 16]) << ((x % 8) * 8); - } -#endif - return_type returnValue{ createArray(newArray, std::make_index_sequence{}) }; - return returnValue; - } - - template JSONIFIER_INLINE const simd_type& printBits(const simd_type& value, const std::string& valuesTitle) noexcept; - - template JSONIFIER_INLINE std::string printBits(const simd_type& value) noexcept; - - JSONIFIER_INLINE void printBits(uint64_t values, const std::string& valuesTitle); - - using string_view_ptr = const uint8_t*; - using structural_index = string_view_ptr; - using string_buffer_ptr = uint8_t*; - -#if JSONIFIER_CHECK_FOR_AVX(JSONIFIER_AVX) - - template - concept simd_int_128_t = std::same_as, simd_int_128>; - - template - concept simd_float_128_t = std::same_as, simd_float_128>; - - template JSONIFIER_INLINE simd_type gatherValues(char_type* str) { - return _mm_load_si128(reinterpret_cast(str)); - } - - template JSONIFIER_INLINE simd_type gatherValuesU(char_type* str) { - return _mm_loadu_si128(reinterpret_cast(str)); - } - - template JSONIFIER_INLINE simd_type gatherValues(char_type* str) { - return _mm_loadu_pd(str); - } - - template JSONIFIER_INLINE void storeu(const simd_int_128& value, char_type* storageLocation) { - _mm_storeu_si128(reinterpret_cast<__m128i*>(storageLocation), value); - } - - template JSONIFIER_INLINE void store(const simd_int_128& value, char_type* storageLocation) { - _mm_store_si128(reinterpret_cast<__m128i*>(storageLocation), value); - } - - #if JSONIFIER_CHECK_FOR_AVX(JSONIFIER_AVX2) - - template - concept simd_int_256_t = std::same_as, simd_int_256>; - - template - concept simd_float_256_t = std::same_as, simd_float_256>; - - template JSONIFIER_INLINE simd_type gatherValues(char_type* str) { - return _mm256_load_si256(reinterpret_cast(str)); - } - - template JSONIFIER_INLINE simd_type gatherValuesU(char_type* str) { - return _mm256_loadu_si256(reinterpret_cast(str)); - } - - template JSONIFIER_INLINE simd_type gatherValues(char_type* str) { - return _mm256_loadu_pd(str); - } - - template JSONIFIER_INLINE void storeu(const simd_int_256& value, char_type* storageLocation) { - _mm256_storeu_si256(reinterpret_cast<__m256i*>(storageLocation), value); - } - - template JSONIFIER_INLINE void store(const simd_int_256& value, char_type* storageLocation) { - _mm256_store_si256(reinterpret_cast<__m256i*>(storageLocation), value); - } - - #if JSONIFIER_CHECK_FOR_AVX(JSONIFIER_AVX512) - - template - concept simd_int_512_t = std::same_as, simd_int_512>; - - template - concept simd_float_512_t = std::same_as, simd_float_512>; - - template JSONIFIER_INLINE simd_type gatherValues(char_type* str) { - return _mm512_load_si512(str); - } - - template JSONIFIER_INLINE simd_type gatherValuesU(char_type* str) { - return _mm512_loadu_si512(str); - } - - template JSONIFIER_INLINE simd_type gatherValues(char_type* str) { - return _mm512_loadu_pd(str); - } - - template JSONIFIER_INLINE void storeu(const simd_int_512& value, char_type* storageLocation) { - _mm512_storeu_si512(storageLocation, value); - } - - template JSONIFIER_INLINE void store(const simd_int_512& value, char_type* storageLocation) { - _mm512_store_si512(storageLocation, value); - } - - #endif - - #endif - -#else - - template - concept simd_int_128_t = std::same_as, simd_int_128>; - - template JSONIFIER_INLINE simd_type gatherValues(char_type* str) { - simd_type returnValue{}; - std::memcpy(&returnValue, str, sizeof(simd_type)); - return returnValue; - } - - template JSONIFIER_INLINE simd_type gatherValuesU(char_type* str) { - simd_type returnValue{}; - std::memcpy(&returnValue, str, sizeof(simd_type)); - return returnValue; - } - - template JSONIFIER_INLINE void storeu(const simd_int_128& value, char_type* storageLocation) { - std::memcpy(storageLocation, &value, sizeof(simd_int_t)); - } - - template JSONIFIER_INLINE void store(const simd_int_128& value, char_type* storageLocation) { - std::memcpy(storageLocation, &value, sizeof(simd_int_t)); - } - -#endif - - class simd_base { - public: - static constexpr uint8_t whitespaceArray[]{ 0x20u, 0x64u, 0x64u, 0x64u, 0x11u, 0x64u, 0x71u, 0x02u, 0x64u, 0x09u, 0x0Au, 0x70u, 0x64u, 0x0Du, 0x64u, 0x64u }; - static constexpr uint8_t opArray[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x3Au, 0x7Bu, 0x2Cu, 0x7Du, 0x00u, 0x00u }; - static constexpr uint8_t escapeableArray01[]{ 0x00u, 0x00u, 0x22u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x08u, 0x09u, 0x0Au, 0x00u, 0x0Cu, 0x0Du, 0x00u, 0x00u }; - static constexpr uint8_t escapeableArray02[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x5Cu, 0x00u, 0x00u, 0x00u }; - static constexpr simd_int_t whitespaceTable{ simdFromTable(whitespaceArray) }; - static constexpr simd_int_t opTableVal{ simdFromTable(opArray) }; - static constexpr simd_int_t backslashes{ simdFromValue(0x5Cu) }; - static constexpr simd_int_t quotes{ simdFromValue(0x22u) }; - static constexpr simd_int_t chars{ simdFromValue(0x20u) }; - - JSONIFIER_INLINE static string_parsing_type cmpeq(const simd_int_t& value, const simd_int_t& other); - - JSONIFIER_INLINE static simd_int_t opShuffle(const simd_int_t& value, const simd_int_t& other); - - JSONIFIER_INLINE static simd_int_t opAndNot(const simd_int_t& value, const simd_int_t& other); - - JSONIFIER_INLINE static simd_int_t opAnd(const simd_int_t& value, const simd_int_t& other); - - JSONIFIER_INLINE static simd_int_t opXor(const simd_int_t& value, const simd_int_t& other); - - JSONIFIER_INLINE static simd_int_t opOr(const simd_int_t& value, const simd_int_t& other); - - JSONIFIER_INLINE static simd_int_t setLSB(const simd_int_t& value, bool valueNew); - - JSONIFIER_INLINE static simd_int_t opNot(const simd_int_t& value); - - JSONIFIER_INLINE static bool getMSB(const simd_int_t& value); - - JSONIFIER_INLINE static bool opBool(const simd_int_t& value); - - JSONIFIER_INLINE static simd_int_t reset(); - - template - JSONIFIER_INLINE static std::enable_if_t, simd_int_128> opShuffle(const simd_type& value, const simd_type& other) { - return _mm_shuffle_epi8(value, other); - } - - template - JSONIFIER_INLINE static std::enable_if_t, uint16_t> cmpeq(const simd_type& value, const simd_type& other) { - return static_cast(_mm_movemask_epi8(_mm_cmpeq_epi8(value, other))); - } - - template JSONIFIER_INLINE static simd_int_t collectStructuralsAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { - alignas(BytesPerStep) string_parsing_type valuesNew[StridesPerStep]{}; - ((valuesNew[indices] = cmpeq(opShuffle(opTableVal, values[indices]), opOr(chars, values[indices]))), ...); - return gatherValues(valuesNew); - } - - template JSONIFIER_INLINE static simd_int_t collectWhitespaceAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { - alignas(BytesPerStep) string_parsing_type valuesNew[StridesPerStep]{}; - ((valuesNew[indices] = cmpeq(opShuffle(whitespaceTable, values[indices]), values[indices])), ...); - return gatherValues(valuesNew); - } - - template JSONIFIER_INLINE static simd_int_t collectBackslashesAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { - alignas(BytesPerStep) string_parsing_type valuesNew[StridesPerStep]{}; - ((valuesNew[indices] = cmpeq(backslashes, values[indices])), ...); - return gatherValues(valuesNew); - } - - template JSONIFIER_INLINE static simd_int_t collectQuotesAsSimdBase(const simd_int_t (&values)[StridesPerStep], std::index_sequence) { - alignas(BytesPerStep) string_parsing_type valuesNew[StridesPerStep]{}; - ((valuesNew[indices] = cmpeq(quotes, values[indices])), ...); - return gatherValues(valuesNew); - } - - constexpr static uint64_t power(size_t base, size_t exponent) { - uint64_t result = 1; - while (exponent > 0) { - if (exponent & 1) { - result *= base; - } - base *= base; - exponent >>= 1; - } - return result; - } - - template JSONIFIER_INLINE static uint64_t prefixXorHelper(uint64_t prevInString) { - prevInString ^= prevInString << index; - return prevInString; - } - - template JSONIFIER_INLINE static uint64_t prefixXor(uint64_t prevInString, std::index_sequence) { - ((prevInString = prefixXorHelper(prevInString)), ...); - return prevInString; - } - - template JSONIFIER_INLINE static simd_int_t carrylessMultiplication(const simd_int_t& value, int64_t& prevInString, std::index_sequence) { - alignas(BytesPerStep) uint64_t values[SixtyFourBitsPerStep]{}; - store(value, values); - ((values[indices] = prefixXor(values[indices], std::make_index_sequence<6>{}) ^ prevInString, prevInString = static_cast(values[indices]) >> 63), ...); - return gatherValues(values); - } - - template JSONIFIER_INLINE static simd_int_t opSub(const simd_int_t& value, const simd_int_t& other, std::index_sequence) { - alignas(BytesPerStep) uint64_t values01[SixtyFourBitsPerStep]{}; - alignas(BytesPerStep) uint64_t values02[SixtyFourBitsPerStep]{}; - store(value, values01); - store(other, values02); - bool carryInNew{}; - ((values02[indices] = values01[indices] - values02[indices] - static_cast(carryInNew), carryInNew = values02[indices] > values01[indices]), ...); - return gatherValues(values02); - } - - template JSONIFIER_INLINE static simd_int_t shl(const simd_int_t& value, std::index_sequence) { - alignas(BytesPerStep) uint64_t values01[SixtyFourBitsPerStep]{}; - alignas(BytesPerStep) uint64_t values02[SixtyFourBitsPerStep]{}; - static constexpr uint64_t shiftAmount{ 64 - amount }; - store(value, values01); - values02[0] = values01[0] << amount; - ((values02[indices + 1] = values01[indices + 1] << amount | values01[indices] >> (shiftAmount)), ...); - return gatherValues(values02); - } - - JSONIFIER_INLINE static simd_int_t follows(const simd_int_t& value, bool& overflow) { - bool oldOverflow = overflow; - overflow = getMSB(value); - return setLSB(shl<1>(value, std::make_index_sequence{}), oldOverflow); - } - }; - -} \ No newline at end of file diff --git a/Include/jsonifier/IToStr.hpp b/Include/jsonifier/IToStr.hpp index 2bc5f6d5a..38d64ba54 100644 --- a/Include/jsonifier/IToStr.hpp +++ b/Include/jsonifier/IToStr.hpp @@ -130,9 +130,9 @@ namespace jsonifier_internal { } } - template JSONIFIER_INLINE char_type* toChars(char_type* buf, value_type01 val) noexcept { + template JSONIFIER_INLINE char_type* toChars(char_type* buf, value_type01 val) noexcept { if (val < 100000000) { - buf = toCharsU64Len18(buf, static_cast(val)); + buf = toCharsU64Len18(buf, val); return buf; } else if (val < 100000000ull * 100000000ull) { const uint64_t hgh = static_cast(val) / 100000000ull; @@ -152,9 +152,9 @@ namespace jsonifier_internal { } } - template JSONIFIER_INLINE char_type* toChars(char_type* buf, value_type01 val) noexcept { + template JSONIFIER_INLINE char_type* toChars(char_type* buf, value_type01 val) noexcept { *buf = 0x2Du; - return toChars(buf + (static_cast(val) < 0), uint64_t(static_cast(val) ^ (static_cast(val) >> 63)) - (static_cast(val) >> 63)); + return toChars(buf + (val < 0), uint64_t(val ^ (val >> 63)) - (val >> 63)); } }// namespace jsonifier_internal diff --git a/Include/jsonifier/Index.hpp b/Include/jsonifier/Index.hpp index e7b2f5aa3..818ef12a1 100644 --- a/Include/jsonifier/Index.hpp +++ b/Include/jsonifier/Index.hpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/Include/jsonifier/Iterator.hpp b/Include/jsonifier/Iterator.hpp index 762ddc9b8..6f07440bb 100644 --- a/Include/jsonifier/Iterator.hpp +++ b/Include/jsonifier/Iterator.hpp @@ -119,7 +119,7 @@ namespace jsonifier_internal { return ptr <=> right.ptr; } - private: + protected: pointer ptr{}; }; diff --git a/Include/jsonifier/JsonifierCore.hpp b/Include/jsonifier/JsonifierCore.hpp index 222e00710..c97d2665c 100644 --- a/Include/jsonifier/JsonifierCore.hpp +++ b/Include/jsonifier/JsonifierCore.hpp @@ -29,25 +29,24 @@ namespace jsonifier { - class jsonifier_core : public jsonifier_internal::serializer, public jsonifier_internal::parser { + template class jsonifier_core : public jsonifier_internal::serializer>, + public jsonifier_internal::parser, doWeUseInitialBuffer> { public: - friend class jsonifier_internal::serialization_iterator, jsonifier_core>; - friend class jsonifier_internal::simd_structural_iterator, jsonifier_core>; - friend class serializer; - friend class parser; + using serializer = jsonifier_internal::serializer>; + using parser = jsonifier_internal::parser, doWeUseInitialBuffer>; - using serializer = jsonifier_internal::serializer; - using parser = jsonifier_internal::parser; + friend class jsonifier_internal::simd_structural_iterator, doWeUseInitialBuffer>; + friend class jsonifier_internal::serializer>; + friend class jsonifier_internal::parser, doWeUseInitialBuffer>; JSONIFIER_INLINE jsonifier_core() noexcept = default; JSONIFIER_INLINE jsonifier_core& operator=(jsonifier_core&& other) noexcept { - stringBuffer = std::move(other.stringBuffer); - section = std::move(other.section); - currentIndex = other.currentIndex; - currentSize = other.currentSize; - rootIndex = other.rootIndex; - errors = other.errors; + if (this != &other) [[likely]] { + stringBuffer = std::move(other.stringBuffer); + parser::section = std::move(other.parser::section); + errors = std::move(other.errors); + } return *this; } @@ -56,12 +55,11 @@ namespace jsonifier { } JSONIFIER_INLINE jsonifier_core& operator=(const jsonifier_core& other) { - stringBuffer = other.stringBuffer; - currentIndex = other.currentIndex; - currentSize = other.currentSize; - rootIndex = other.rootIndex; - section = other.section; - errors = other.errors; + if (this != &other) [[likely]] { + stringBuffer = other.stringBuffer; + parser::section = other.parser::section; + errors = other.errors; + } return *this; } @@ -76,7 +74,7 @@ namespace jsonifier { JSONIFIER_INLINE ~jsonifier_core() noexcept = default; protected: - jsonifier_internal::buffer_string stringBuffer{}; + string_base stringBuffer{}; jsonifier::vector errors{}; }; diff --git a/Include/jsonifier/NumberUtils.hpp b/Include/jsonifier/NumberUtils.hpp index a68bbc515..1cc006400 100644 --- a/Include/jsonifier/NumberUtils.hpp +++ b/Include/jsonifier/NumberUtils.hpp @@ -37,14 +37,24 @@ namespace jsonifier { template JSONIFIER_INLINE jsonifier::string_base toString(const value_type01& value) { string_base returnstring{}; returnstring.resize(64); - auto newPtr = jsonifier_internal::toChars(returnstring.data(), value); - returnstring.resize(static_cast(newPtr - returnstring.data())); + if constexpr (jsonifier::concepts::unsigned_t && sizeof(value) < 8) { + uint64_t newValue{ static_cast(value) }; + auto newPtr = jsonifier_internal::toChars(returnstring.data(), newValue); + returnstring.resize(static_cast(newPtr - returnstring.data())); + } else if constexpr (jsonifier::concepts::signed_t && sizeof(value) < 8) { + int64_t newValue{ static_cast(value) }; + auto newPtr = jsonifier_internal::toChars(returnstring.data(), newValue); + returnstring.resize(static_cast(newPtr - returnstring.data())); + } else { + auto newPtr = jsonifier_internal::toChars(returnstring.data(), value); + returnstring.resize(static_cast(newPtr - returnstring.data())); + } return returnstring; } template JSONIFIER_INLINE double strToDouble(const jsonifier::string& string) { double newValue{}; - if (string.size() > 0) { + if (string.size() > 0) [[likely]] { jsonifier_internal::parseNumber(newValue, string.data()); } return newValue; @@ -52,7 +62,7 @@ namespace jsonifier { template<> JSONIFIER_INLINE double strToDouble<16>(const jsonifier::string& string) { double newValue{}; - if (string.size() > 0) { + if (string.size() > 0) [[likely]] { newValue = std::strtod(string.data(), nullptr); } return newValue; @@ -60,7 +70,7 @@ namespace jsonifier { template JSONIFIER_INLINE int64_t strToInt64(const jsonifier::string& string) { int64_t newValue{}; - if (string.size() > 0) { + if (string.size() > 0) [[likely]] { jsonifier_internal::parseNumber(newValue, string.data()); } return newValue; @@ -68,7 +78,7 @@ namespace jsonifier { template<> JSONIFIER_INLINE int64_t strToInt64<16>(const jsonifier::string& string) { int64_t newValue{}; - if (string.size() > 0) { + if (string.size() > 0) [[likely]] { newValue = std::strtoll(string.data(), nullptr, 16); } return newValue; @@ -76,7 +86,7 @@ namespace jsonifier { template JSONIFIER_INLINE uint64_t strToUint64(const jsonifier::string& string) { uint64_t newValue{}; - if (string.size() > 0) { + if (string.size() > 0) [[likely]] { jsonifier_internal::parseNumber(newValue, string.data()); } return newValue; @@ -84,7 +94,7 @@ namespace jsonifier { template<> JSONIFIER_INLINE uint64_t strToUint64<16>(const jsonifier::string& string) { uint64_t newValue{}; - if (string.size() > 0) { + if (string.size() > 0) [[likely]] { newValue = std::strtoull(string.data(), nullptr, 16); } return newValue; diff --git a/Include/jsonifier/Parse_Impl.hpp b/Include/jsonifier/Parse_Impl.hpp index a09903587..c455d671d 100644 --- a/Include/jsonifier/Parse_Impl.hpp +++ b/Include/jsonifier/Parse_Impl.hpp @@ -33,11 +33,11 @@ namespace jsonifier_internal { template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { auto newPtr = iter.operator->(); - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); return; } @@ -46,36 +46,36 @@ namespace jsonifier_internal { }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { auto newPtr = iter.operator->(); - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); return; } - if (!parseNumber(value, newPtr)) { - iter.template createError(); + if (!parseNumber(value, newPtr)) [[unlikely]] { + iter.template createError(); } } }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { uint64_t newValue{}; auto newValueOld = static_cast(value); - parse::template op(newValue, std::forward(iter)); + parse::op(newValue, iter); newValue |= newValueOld; value = static_cast(newValue); } }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); return; } @@ -83,64 +83,49 @@ namespace jsonifier_internal { }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { - value = std::make_unique(); - parse::template op(*value, std::forward(iter)); + parse::op(*value, iter); } }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { auto newPtr = iter.operator->(); - switch (*iter) { - case 0x22u: { - derailleur::skipValue(iter); - int64_t newSize = (iter.operator->() - newPtr) - 1; - if (newSize > 0) { - value.resize(static_cast(newSize)); - std::memcpy(value.data(), newPtr, static_cast(newSize)); - } - break; - } - default: { - derailleur::skipValue(iter); - int64_t newSize = iter.operator->() - newPtr; - if (newSize > 0) { - value.resize(static_cast(newSize)); - std::memcpy(value.data(), newPtr, static_cast(newSize)); - } - break; - } + derailleur::skipValue(iter); + int64_t newSize = iter.operator->() - newPtr; + if (newSize > 0) [[likely]] { + value.resize(static_cast(newSize)); + std::memcpy(value.data(), newPtr, static_cast(newSize)); } return; } }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { auto newPtr = iter.operator->(); - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); return; } - auto newSize = static_cast(roundUpToMultiple(static_cast(iter.operator->() - newPtr))); - if (newSize * 2 > static_cast(iter.size())) { - iter.resize(static_cast(newSize * 2)); + auto newSize = roundUpToMultiple((iter.operator->() - newPtr)); + if (newSize > static_cast(iter.size())) [[unlikely]] { + iter.resize(static_cast(newSize)); } - newSize = parseString(newPtr + 1, iter.data(), static_cast(newSize)) - iter.data(); - if (newSize > 0) { + newSize = parseString(newPtr + 1, iter.data(), static_cast(newSize)) - iter.data(); + if (newSize > 0) [[likely]] { value.resize(static_cast(newSize)); std::memcpy(value.data(), iter.data(), static_cast(newSize)); } } }; - template struct parse_impl { - template + template struct parse_impl { + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { value = static_cast(*iter.operator->() + 1); ++iter; @@ -148,23 +133,23 @@ namespace jsonifier_internal { }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); return; } - if (derailleur::template checkForMatchOpen(iter)) [[unlikely]] { + if (derailleur::checkForMatchOpen(iter)) [[unlikely]] { return; } - static constexpr auto n = std::size(value); + auto n = std::size(value); for (uint64_t x = 0; x < n; ++x) { - parse::template op(value[x], std::forward(iter)); - if (!derailleur::template checkForMatchOpen(iter)) [[likely]] { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + parse::op(value[x], iter); + if (!derailleur::checkForMatchOpen(iter)) [[unlikely]] { + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); } return; @@ -174,34 +159,38 @@ namespace jsonifier_internal { }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); return; } - if (derailleur::template checkForMatchOpen(iter)) [[unlikely]] { + if (derailleur::checkForMatchOpen(iter)) [[unlikely]] { return; } - const auto m = value.size(); - - for (uint64_t x = 0; x < m; ++x) { - parse::template op(value[x], iter); - if (!derailleur::template checkForMatchOpen(iter)) [[likely]] { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + auto newPtr = value.begin(); + auto endPtr = value.end(); + for (; newPtr < endPtr; ++newPtr) { + parse::op(*newPtr, iter); + if (!derailleur::checkForMatchOpen(iter)) [[unlikely]] { + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); } return; } } - if constexpr (jsonifier::concepts::has_emplace_back) { - while (iter != iter) { - parse::template op(value.emplace_back(), iter); - if (!derailleur::template checkForMatchOpen(iter)) [[likely]] { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if constexpr (jsonifier::concepts::has_resize) { + auto oldSize = value.size(); + value.resize(value.size() + derailleur::countValueElements(iter)); + newPtr = value.begin() + static_cast(oldSize); + endPtr = value.end(); + for (; newPtr < endPtr; ++newPtr) { + parse::op(*newPtr, iter); + if (!derailleur::checkForMatchOpen(iter)) [[unlikely]] { + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipValue(iter); } return; @@ -212,120 +201,102 @@ namespace jsonifier_internal { }; template struct parse_impl { - template + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipToEndOfObject(iter); return; } bool first{ true }; - while (iter != iter) { - if (derailleur::template checkForMatchOpen(iter)) [[unlikely]] { + while (iter) { + if (derailleur::checkForMatchOpen(iter)) [[unlikely]] { return; } else if (first) [[unlikely]] { first = false; } else [[likely]] { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipToEndOfObject(iter); return; } } - if (derailleur::template checkForMatchOpen(iter)) [[unlikely]] { + if (derailleur::checkForMatchOpen(iter)) [[unlikely]] { continue; } static thread_local typename value_type_new::key_type keyNew{}; - parse::template op(keyNew, iter); - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + parse::op(keyNew, iter); + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipToEndOfObject(iter); return; } - parse::template op(value[keyNew], iter); + parse::op(value[keyNew], iter); } } }; - template struct parse_impl { - template + template struct parse_impl { + template JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); - derailleur::skipToEndOfArray(iter); - return; - } static constexpr auto size{ std::tuple_size_v> }; - - forEach([&](auto I) { - auto& newMember = getMember(value, get(jsonifier::concepts::coreV)); - parse::template op(newMember, std::forward(iter)); - if (iter == iter) { - return; - } - if (!derailleur::template checkForMatchOpen(iter)) [[likely]] { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); - derailleur::skipToEndOfArray(iter); - } - return; - } - }); + if constexpr (size > 0) { + parse::op(getMember(value, get<0>(jsonifier::concepts::coreV)), iter); + } } }; - template struct parse_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter, key_type&&... excludedKeys) { - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); + template struct parse_impl { + template + JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter, key_type&... excludedKeys) { + if (!derailleur::checkForMatchClosed(iter)) [[unlikely]] { + iter.template createError(); derailleur::skipToEndOfObject(iter); return; } bool first{ true }; - while (iter != iter) { - if (derailleur::template checkForMatchOpen(iter)) [[unlikely]] { + while (iter) { + if (derailleur::checkForMatchOpen(iter)) [[unlikely]] { return; } else if (first) [[unlikely]] { first = false; - } else if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); - derailleur::skipToEndOfObject(iter); - return; + } else if (!derailleur::checkForMatchClosed(iter)) [[likely]] { + iter.template createError(); + derailleur::skipToNextValue(iter); + continue; } auto start = iter.operator->(); - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); - derailleur::skipToEndOfObject(iter); - return; + if (!derailleur::checkForMatchClosed(iter)) [[likely]] { + iter.template createError(); + derailleur::skipToNextValue(iter); + continue; } const jsonifier::string_view_base key{ start + 1, static_cast(iter.operator->() - (start + 2)) }; if constexpr ((( !std::is_void_v ) || ...)) { - if (((excludedKeys.find(static_cast::key_type>(key)) != excludedKeys.end()) && ...)) { + if (((excludedKeys.find(static_cast::key_type>(key)) != excludedKeys.end()) & ...)) [[unlikely]] { derailleur::skipToNextValue(iter); continue; } } - if (!derailleur::template checkForMatchClosed(iter)) [[unlikely]] { - iter.template createError(); - derailleur::skipToEndOfObject(iter); - return; + if (!derailleur::checkForMatchClosed(iter)) [[likely]] { + iter.template createError(); + derailleur::skipToNextValue(iter); + continue; } static constexpr auto frozenMap = makeMap(); const auto& memberIt = frozenMap.find(key); - if (derailleur::template checkForMatchOpen(iter)) [[unlikely]] { + if (derailleur::checkForMatchOpen(iter)) [[unlikely]] { continue; } else if (memberIt != frozenMap.end()) [[likely]] { - if constexpr (std::variant_size_vsecond)> > 0) { + using member_ptr_t = decltype(memberIt->second); + if constexpr (std::variant_size_v > 0) { std::visit( - [&](auto& memberPtr) { - auto& newMember = getMember(value, memberPtr); - parse::template op(newMember, iter); + [&](auto&& memberPtr) { + parse::op(getMember(value, std::forward(memberPtr)), iter); }, - memberIt->second); + std::move(memberIt->second)); } } else [[unlikely]] { derailleur::skipValue(iter); diff --git a/Include/jsonifier/Parser.hpp b/Include/jsonifier/Parser.hpp index c8ec7a898..8a218e72e 100644 --- a/Include/jsonifier/Parser.hpp +++ b/Include/jsonifier/Parser.hpp @@ -29,52 +29,53 @@ #include #include +namespace jsonifier { + + template class jsonifier_core; +} + namespace jsonifier_internal { template struct parse_impl; struct parse { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { + template + JSONIFIER_INLINE static void op(value_type&& data, iterator_type&& iter) { if constexpr (jsonifier::concepts::has_excluded_keys) { - parse_impl>::template op(std::forward(value), std::forward(iter), - value.jsonifierExcludedKeys); + parse_impl>::op(std::forward(data), std::forward(iter), data.jsonifierExcludedKeys); } else { - parse_impl>::template op(std::forward(value), std::forward(iter)); + parse_impl>::op(std::forward(data), std::forward(iter)); } } }; - template class parser : protected simd_structural_iterator, derived_type> { + template class parser { public: - using iterator_type = simd_structural_iterator, derived_type>; + using iterator_type = simd_structural_iterator, derived_type, doWeUseInitialBuffer>; template friend struct parse_impl; JSONIFIER_INLINE parser& operator=(const parser& other) = delete; JSONIFIER_INLINE parser(const parser& other) = delete; - template + template JSONIFIER_INLINE void parseJson(value_type&& data, buffer_type&& stringNew) { derivedRef.errors.clear(); - section.reset(stringNew.data(), stringNew.size()); - iterator_type::reset(section.begin()); - if (!iterator_type::operator->()) { - return; - } - parse::template op(std::forward(data), std::forward(*this)); + section.template reset(stringNew.data(), stringNew.size()); + iterator_type iter{ section.begin(), derivedRef.stringBuffer, derivedRef.errors }; + parse::op(std::forward(data), iter); } protected: + simd_string_reader section{}; derived_type& derivedRef{ initializeSelfRef() }; - simd_string_reader section{}; JSONIFIER_INLINE parser() noexcept : derivedRef{ initializeSelfRef() } {}; - JSONIFIER_INLINE ~parser() noexcept = default; - JSONIFIER_INLINE derived_type& initializeSelfRef() { return *static_cast(this); } + + JSONIFIER_INLINE ~parser() noexcept = default; }; }; diff --git a/Include/jsonifier/Prettify.hpp b/Include/jsonifier/Prettify.hpp new file mode 100644 index 000000000..f123407a8 --- /dev/null +++ b/Include/jsonifier/Prettify.hpp @@ -0,0 +1,133 @@ +/* + MIT License + + Copyright (c) 2023 RealTimeChris + + Permission is hereby granted, free of charge, to any person obtaining a copy of this + software and associated documentation files (the "Software"), to deal in the Software + without restriction, including without limitation the rights to use, copy, modify, merge, + publish, distribute, sublicense, and/or sell copies of the Software, and to permit + persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, + INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. +*/ +/// Note: Most of the code in this header was sampled from Glaze library: https://github.com/stephenberry/glaze +/// https://github.com/RealTimeChris/jsonifier +/// Feb 3, 2023 +#pragma once + +namespace jsonifier_internal { + + enum class general_state : uint32_t { Normal, Escaped, String }; + + template + JSONIFIER_INLINE void prettifyImpl(const char c, string_type& out, uint32_t& indent, function_type newLine, general_state& state) noexcept { + switch (state) { + case general_state::Escaped: { + state = general_state::String; + out += c; + break; + } + case general_state::String: { + if (c == '\\') { + state = general_state::Escaped; + } else if (c == '"') { + state = general_state::Normal; + } + out += c; + break; + } + case general_state::Normal: { + switch (c) { + case ',': { + out += c; + newLine(); + break; + } + case '[': { + ++indent; + out += c; + newLine(); + break; + } + case ']': { + --indent; + newLine(); + out += c; + break; + } + case '{': { + ++indent; + out += c; + newLine(); + break; + } + case '}': { + --indent; + newLine(); + out += c; + break; + } + case '\"': { + out += c; + state = general_state::String; + break; + } + case '/': + [[fallthrough]]; + case ':': + [[fallthrough]]; + case ' ': + [[fallthrough]]; + case '\n': + [[fallthrough]]; + case '\r': + [[fallthrough]]; + case '\t': + [[fallthrough]]; + default: { + out += c; + break; + } + } + break; + } + default: + out += c; + break; + } + } +} + +namespace jsonifier { + + template JSONIFIER_INLINE string_type prettify(const string_type& in, const bool tabs = false, const uint32_t indentSize = 3) noexcept { + uint32_t indent{}; + string_type out{}; + out.reserve(in.size()); + + auto newLine = [&]() { + out += "\n"; + + for (uint32_t i = 0; i < indent * (tabs ? 1 : indentSize); i++) { + out += tabs ? "\t" : " "; + } + }; + + jsonifier_internal::general_state state{ jsonifier_internal::general_state::Normal }; + + for (auto& c: in) { + jsonifier_internal::prettifyImpl(c, out, indent, newLine, state); + } + return out; + } + +}// namespace jsonifier_internal diff --git a/Include/jsonifier/RawJsonData.hpp b/Include/jsonifier/RawJsonData.hpp index c4700738d..a118bcc34 100644 --- a/Include/jsonifier/RawJsonData.hpp +++ b/Include/jsonifier/RawJsonData.hpp @@ -29,9 +29,9 @@ namespace std { - template<> struct hash { - JSONIFIER_INLINE uint64_t operator()(const jsonifier::string& string) const { - return jsonifier_internal::fnv1aHash(string); + template struct hash { + JSONIFIER_INLINE uint64_t operator()(const string_type& string) const { + return jsonifier_internal::fnv1aHash(string, 0); } }; @@ -188,7 +188,7 @@ namespace jsonifier { JSONIFIER_INLINE explicit operator string_view() { if (jsonData.size() > 0) { - return { jsonData.data() + 1, jsonData.size() - 1 }; + return { jsonData.data() + 1, jsonData.size() - 2 }; } else { return {}; } @@ -196,7 +196,7 @@ namespace jsonifier { JSONIFIER_INLINE explicit operator string() const { if (jsonData.size() > 0) { - return { jsonData.data() + 1, jsonData.size() - 1 }; + return { jsonData.data() + 1, jsonData.size() - 2 }; } else { return {}; } @@ -251,4 +251,4 @@ namespace jsonifier { return os; } -} +} \ No newline at end of file diff --git a/Include/jsonifier/SerializationIterator.hpp b/Include/jsonifier/SerializationIterator.hpp deleted file mode 100644 index 1ba17ec23..000000000 --- a/Include/jsonifier/SerializationIterator.hpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - MIT License - - Copyright (c) 2023 RealTimeChris - - Permission is hereby granted, free of charge, to any person obtaining a copy of this - software and associated documentation files (the "Software"), to deal in the Software - without restriction, including without limitation the rights to use, copy, modify, merge, - publish, distribute, sublicense, and/or sell copies of the Software, and to permit - persons to whom the Software is furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all copies or - substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR - PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE - FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR - OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - DEALINGS IN THE SOFTWARE. -*/ -/// https://github.com/RealTimeChris/jsonifier -/// Feb 3, 2023 -#pragma once - -#include -#include -#include -#include -#include - -namespace jsonifier_internal { - - template class serialization_iterator { - public: - friend class derailleur; - - using iterator_concept = std::forward_iterator_tag; - using iterator_category = std::forward_iterator_tag; - using value_type = uint64_t; - using pointer = uint8_t*; - using difference_type = std::ptrdiff_t; - using size_type = uint64_t; - - size_type currentSize{}; - - JSONIFIER_INLINE serialization_iterator() noexcept : selfRef{ initializeSelfRef() } {}; - - JSONIFIER_INLINE serialization_iterator& operator=(const serialization_iterator& other) noexcept { - if (this != &other) { - serialization_iterator{ other }.swap(*this); - } - return *this; - }; - - JSONIFIER_INLINE serialization_iterator(const serialization_iterator& other) noexcept : selfRef{ initializeSelfRef() }, currentSize{ other.currentSize } {}; - - JSONIFIER_INLINE value_type operator*() const { - return 0; - } - - JSONIFIER_INLINE pointer operator->() const { - return &selfRef.stringBuffer[currentSize]; - } - - JSONIFIER_INLINE void potentiallyResize(size_type sizeNew) { - if (currentSize + sizeNew >= selfRef.stringBuffer.size()) { - selfRef.stringBuffer.resize((currentSize + sizeNew) * 2); - } - } - - template JSONIFIER_INLINE void writeCharacter() { - if (currentSize + 1 >= selfRef.stringBuffer.size()) { - selfRef.stringBuffer.resize((currentSize + 1) * 2); - } - selfRef.stringBuffer[currentSize++] = static_cast(c); - } - - template JSONIFIER_INLINE void writeCharacter(char_type c) { - if (currentSize + 1 >= selfRef.stringBuffer.size()) { - selfRef.stringBuffer.resize((currentSize + 1) * 2); - } - selfRef.stringBuffer[currentSize++] = static_cast(c); - } - - template JSONIFIER_INLINE void writeCharacterUnchecked(char_type c) { - selfRef.stringBuffer[currentSize++] = static_cast(c); - } - - template JSONIFIER_INLINE void writeCharacters() { - constexpr auto n = str.size(); - if (currentSize + n >= selfRef.stringBuffer.size()) { - selfRef.stringBuffer.resize((currentSize + n) * 2); - } - std::memcpy(selfRef.stringBuffer.data() + currentSize, str.data(), n); - currentSize += n; - } - - template JSONIFIER_INLINE void writeCharacters(const char (&str)[size]) { - constexpr auto n = size - 1; - if (currentSize + n >= selfRef.stringBuffer.size()) { - selfRef.stringBuffer.resize((currentSize + n) * 2); - } - std::memcpy(selfRef.stringBuffer.data() + currentSize, str, n); - currentSize += n; - } - - template JSONIFIER_INLINE void writeCharacterUnchecked() { - selfRef.stringBuffer[currentSize++] = static_cast(c); - } - - template JSONIFIER_INLINE void writeCharactersUnchecked(const char (&str)[size]) { - std::memcpy(selfRef.stringBuffer.data() + currentSize, str, size - 1); - currentSize += size - 1; - } - - JSONIFIER_INLINE void resize(size_type sizeNew) { - selfRef.stringBuffer.resize(sizeNew); - } - - JSONIFIER_INLINE pointer data() const { - return selfRef.stringBuffer.data(); - } - - JSONIFIER_INLINE void reset() { - currentSize = 0; - } - - JSONIFIER_INLINE serialization_iterator& operator++() { - ++currentSize; - return *this; - } - - JSONIFIER_INLINE serialization_iterator operator++(int32_t) { - serialization_iterator temp{ *this }; - ++(*this); - return temp; - } - - JSONIFIER_INLINE uint8_t& operator[](uint64_t index) const { - return selfRef.stringBuffer[index]; - } - - JSONIFIER_INLINE bool operator==(const serialization_iterator& other) const { - return currentSize == other.currentSize; - } - - JSONIFIER_INLINE size_type size() const { - return selfRef.stringBuffer.size(); - } - - JSONIFIER_INLINE void swap(serialization_iterator& other) { - std::swap(currentSize, other.currentSize); - } - - protected: - second_derived_type& selfRef{ initializeSelfRef() }; - - second_derived_type& initializeSelfRef() { - return *static_cast(this); - } - }; -} \ No newline at end of file diff --git a/Include/jsonifier/Serialize_Impl.hpp b/Include/jsonifier/Serialize_Impl.hpp index 4cedac5f7..ee84fc3a6 100644 --- a/Include/jsonifier/Serialize_Impl.hpp +++ b/Include/jsonifier/Serialize_Impl.hpp @@ -30,250 +30,279 @@ namespace jsonifier_internal { + template + JSONIFIER_INLINE void writeCharacter(buffer_type&& buffer, index_type&& index, const char_type c) noexcept { + const auto k = index + 1; + if (k >= buffer.size()) [[unlikely]] { + buffer.resize(max(buffer.size() * 2, k)); + } + + buffer[index] = static_cast::value_type>(c); + ++index; + } + + template + JSONIFIER_INLINE void writeCharacterUnchecked(buffer_type&& buffer, index_type&& index, const char_type c) noexcept { + buffer[index] = static_cast::value_type>(c); + ++index; + } + + template + JSONIFIER_INLINE void writeCharacter(buffer_type&& buffer, index_type&& index) noexcept { + const auto k = index + 1; + if (k >= buffer.size()) [[unlikely]] { + buffer.resize(max(buffer.size() * 2, k)); + } + + buffer[index] = static_cast::value_type>(c); + ++index; + } + + template + JSONIFIER_INLINE void writeCharacters(buffer_type&& buffer, index_type&& index, const char_type (&str)[size]) noexcept { + static constexpr auto sizeNew = size - 1; + auto k = index + sizeNew; + if (k >= buffer.size()) [[unlikely]] { + buffer.resize(max(buffer.size() * 2, k)); + } + std::memcpy(buffer.data() + std::forward(index), str, sizeNew); + index += sizeNew; + } + + template + JSONIFIER_INLINE void writeCharacters(buffer_type&& buffer, index_type&& index) noexcept { + const auto sizeNew = str.size(); + const auto k = index + sizeNew; + if (k >= buffer.size()) [[unlikely]] { + buffer.resize(max(buffer.size() * 2, k)); + } + std::memcpy(buffer.data() + std::forward(index), str.data(), sizeNew); + index += sizeNew; + } + template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&&, iterator_type&& buffer) { - buffer.writeCharacters("null"); + template + JSONIFIER_INLINE static void op(value_type&&, buffer_type&& buffer, index_type&& index) { + writeCharacters(buffer, std::forward(index), "null"); + } + }; + + template struct serialize_impl { + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + serialize::op(*value, buffer, index); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - value ? buffer.writeCharacters("true") : buffer.writeCharacters("false"); + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + value ? writeCharacters(buffer, std::forward(index), "true") : writeCharacters(buffer, std::forward(index), "false"); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - buffer.potentiallyResize(32); - auto end = toChars(buffer.data() + buffer.currentSize, value); - buffer.currentSize += end - (buffer.data() + buffer.currentSize); + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + const auto k = index + 32; + if (k >= buffer.size()) [[unlikely]] { + buffer.resize(max(buffer.size() * 2, k)); + } + if constexpr (jsonifier::concepts::unsigned_t && sizeof(value) < 8) { + uint64_t newValue{ static_cast(value) }; + auto end = toChars(buffer.data() + std::forward(index), newValue); + index += end - (buffer.data() + index); + } else if constexpr (jsonifier::concepts::signed_t && sizeof(value) < 8) { + int64_t newValue{ static_cast(value) }; + auto end = toChars(buffer.data() + std::forward(index), newValue); + index += end - (buffer.data() + index); + } else { + auto end = toChars(buffer.data() + std::forward(index), value); + index += end - (buffer.data() + index); + } } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - buffer.potentiallyResize(32); - auto end = toChars(buffer.data() + buffer.currentSize, static_cast(value)); - buffer.currentSize += end - (buffer.data() + buffer.currentSize); + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + const auto k = index + 32; + if (k >= buffer.size()) [[unlikely]] { + buffer.resize(max(buffer.size() * 2, k)); + } + auto end = toChars(buffer.data() + std::forward(index), static_cast(value)); + index += end - (buffer.data() + index); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - buffer.template writeCharacter(); + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + writeCharacter(buffer, index); switch (value) { - case 0x08u: { - buffer.writeCharacters("\\b"); + [[unlikely]] case 0x08u : { + writeCharacters(buffer, std::forward(index), "\\b"); break; } - case 0x09u: { - buffer.writeCharacters("\\t"); + [[unlikely]] case 0x09u : { + writeCharacters(buffer, std::forward(index), "\\t"); break; } - case 0x0Au: { - buffer.writeCharacters("\\n"); + [[unlikely]] case 0x0Au : { + writeCharacters(buffer, std::forward(index), "\\n"); break; } - case 0x0Cu: { - buffer.writeCharacters("\\f"); + [[unlikely]] case 0x0Cu : { + writeCharacters(buffer, std::forward(index), "\\f"); break; } - case 0x0Du: { - buffer.writeCharacters("\\r"); + [[unlikely]] case 0x0Du : { + writeCharacters(buffer, std::forward(index), "\\r"); break; } - case 0x22u: { - buffer.writeCharacters("\\\""); + [[unlikely]] case 0x22u : { + writeCharacters(buffer, std::forward(index), "\\\""); break; } - case 0x5CU: { - buffer.writeCharacters("\\\\"); + [[unlikely]] case 0x5CU : { + writeCharacters(buffer, std::forward(index), "\\\\"); break; } - default: { - buffer.writeCharacter(value); - } + [[likely]] default : { + writeCharacter(buffer, std::forward(index), value); + } } - buffer.template writeCharacter(); + writeCharacter(buffer, index); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - auto n = static_cast(value.size()); - - buffer.potentiallyResize(buffer.currentSize + (4 * n)); - buffer.template writeCharacterUnchecked(); - - n = 0; - - auto newPtr = serializeString(value.data(), buffer.data() + buffer.currentSize, value.size(), n); - - buffer.currentSize += n; - - n = static_cast(newPtr - value.data()); - for (; n < value.size(); ++n) { - switch (value[n]) { - case 0x08u: { - buffer.writeCharactersUnchecked("\\b"); - break; - } - case 0x09u: { - buffer.writeCharactersUnchecked("\\t"); - break; - } - case 0x0Au: { - buffer.writeCharactersUnchecked("\\n"); - break; - } - case 0x0Cu: { - buffer.writeCharactersUnchecked("\\f"); - break; - } - case 0x0Du: { - buffer.writeCharactersUnchecked("\\r"); - break; - } - case 0x22u: { - buffer.writeCharactersUnchecked("\\\""); - break; - } - case 0x5CU: { - buffer.writeCharactersUnchecked("\\\\"); - break; - } - default: { - buffer.writeCharacterUnchecked(value[n]); - } - } + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + const auto k = index + 10 + value.size() * 2; + if (k >= buffer.size()) [[unlikely]] { + buffer.resize(max(buffer.size() * 2, k)); } + writeCharacter(buffer, index); + + serializeString(value.data(), buffer.data() + std::forward(index), value.size(), index); - buffer.template writeCharacterUnchecked(); + writeCharacter(buffer, index); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - serialize::template op(static_cast(value), buffer); + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + serialize_impl::op(static_cast(value), buffer, index); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type& value, iterator_type&& buffer) { + template + JSONIFIER_INLINE static void op(value_type& value, buffer_type&& buffer, index_type&& index) { static constexpr auto n = std::size(value); - buffer.template writeCharacter(); + writeCharacter(buffer, index); if constexpr (n > 0) { - serialize::template op(value[0], buffer); - for (uint64_t x = 0; x < n; ++x) { - buffer.template writeCharacter(); - serialize::template op(value[x], buffer); + serialize::op(value[0], buffer, index); + for (uint64_t x = 1; x < n; ++x) { + writeCharacter(buffer, index); + serialize::op(value[x], buffer, index); } } - buffer.template writeCharacter(); + writeCharacter(buffer, index); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - buffer.template writeCharacter(); - - if (value.size() > 0) { - auto iter = value.begin(); - serialize::template op(*iter, buffer); - ++iter; - for (; iter != value.end(); ++iter) { - buffer.template writeCharacter(); - serialize::template op(*iter, buffer); + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + auto n = value.size(); + writeCharacter(buffer, index); + if (n > 0) [[likely]] { + serialize::op(value[0], buffer, index); + for (uint64_t x = 1; x < n; ++x) { + writeCharacter(buffer, index); + serialize::op(value[x], buffer, index); } } - buffer.template writeCharacter(); + writeCharacter(buffer, index); } }; template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { - buffer.template writeCharacter(); - bool first{ true }; - auto setToFalseLambda = [&]() { - first = false; - }; - if (value.size() > 0) { - for (auto& [key, valueNew]: value) { - first ? setToFalseLambda() : buffer.template writeCharacter(); - serialize::template op(key, buffer); - buffer.template writeCharacter(); - serialize::template op(valueNew, buffer); + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { + writeCharacter(buffer, index); + + if (value.size() > 0) [[likely]] { + auto iter = value.begin(); + serialize::op(iter->first, buffer, index); + writeCharacter(buffer, index); + serialize::op(iter->second, buffer, index); + ++iter; + for (; iter != value.end(); ++iter) { + writeCharacter(buffer, index); + serialize::op(iter->first, buffer, index); + writeCharacter(buffer, index); + serialize::op(iter->second, buffer, index); } } - buffer.template writeCharacter(); + writeCharacter(buffer, index); } }; - template struct serialize_impl { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer) { + template struct serialize_impl { + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { static constexpr auto size{ std::tuple_size_v> }; - - buffer.template writeCharacter(); if constexpr (size > 0) { - auto& newMember = getMember(value, get<0>(jsonifier::concepts::coreV)); - serialize::template op(newMember, buffer); - forEach([&](auto x) { - buffer.template writeCharacter(); - auto& newMember = getMember(value, get(jsonifier::concepts::coreV)); - serialize::template op(newMember, buffer); - }); + serialize::op(getMember(value, get<0>(jsonifier::concepts::coreV)), buffer, index); } - - buffer.template writeCharacter(); } }; - template struct serialize_impl { - template + void serializeObjects(value_type&& value, buffer_type&& buffer, index_type&& index, key_type&&... excludedKeys) { + static constexpr auto& item = get(jsonifier::concepts::coreV>); + + static constexpr jsonifier::string_view key = get<0>(item); + if constexpr ((( !std::is_void_v ) || ...)) { + constexpr jsonifier::string_view keyNew = key; + if (((excludedKeys.find(static_cast::key_type>(keyNew)) != excludedKeys.end()) && ...)) [[unlikely]] { + if constexpr (indexNew < n - 1 && areWeFirst) { + serializeObjects(value, buffer, index, excludedKeys...); + } else if constexpr (indexNew < n - 1) { + serializeObjects(value, buffer, index, excludedKeys...); + } + return; + } + } + if constexpr (indexNew > 0 && !areWeFirst) { + writeCharacter(buffer, index); + } + writeCharacters(buffer, std::forward(index), "\""); + writeCharacters(buffer, index); + writeCharacters(buffer, std::forward(index), "\":"); + + serialize::op(getMember(value, get<1>(item)), buffer, index); + if constexpr (indexNew < n - 1) { + serializeObjects(value, buffer, index, excludedKeys...); + } + } + + template struct serialize_impl { + template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& buffer, key_type&&... excludedKeys) { - buffer.template writeCharacter(); + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index, key_type&&... excludedKeys) { static constexpr auto n = std::tuple_size_v>; - bool first{ true }; - auto setToFalseLambda = [&]() { - first = false; - }; - forEach([&](auto x) { - static constexpr auto& item = get(jsonifier::concepts::coreV); - using item_type = jsonifier::concepts::unwrap; - using member_ptr_t = std::tuple_element_t<1, item_type>; - using value_type_newer = member_t; - - static constexpr jsonifier::string_view key = get<0>(item); - if constexpr ((( !std::is_void_v ) || ...)) { - constexpr jsonifier::string_view keyNew{ key }; - if (((excludedKeys.find(static_cast::key_type>(keyNew)) != excludedKeys.end()) && ...)) { - return; - } - } - first ? setToFalseLambda() : buffer.template writeCharacter(); - buffer.writeCharacters("\""); - buffer.template writeCharacters(); - buffer.writeCharacters("\":"); - - auto& newMember = getMember(value, get<1>(item)); - serialize::template op(newMember, buffer); - }); - buffer.template writeCharacter(); + writeCharacter(buffer, index); + serializeObjects(value, buffer, index, excludedKeys...); + writeCharacter(buffer, index); } }; } \ No newline at end of file diff --git a/Include/jsonifier/Serializer.hpp b/Include/jsonifier/Serializer.hpp index db67abfd5..887a23777 100644 --- a/Include/jsonifier/Serializer.hpp +++ b/Include/jsonifier/Serializer.hpp @@ -23,7 +23,6 @@ /// Feb 20, 2023 #pragma once -#include #include #include #include @@ -33,39 +32,36 @@ namespace jsonifier_internal { template struct serialize_impl; struct serialize { - template - JSONIFIER_INLINE static void op(value_type&& value, iterator_type&& iter) { + template + JSONIFIER_INLINE static void op(value_type&& value, buffer_type&& buffer, index_type&& index) { if constexpr (jsonifier::concepts::has_excluded_keys) { - serialize_impl>::template op(std::forward(value), std::forward(iter), + serialize_impl>::op(std::forward(value), std::forward(buffer), std::forward(index), value.jsonifierExcludedKeys); } else { - serialize_impl>::template op(std::forward(value), std::forward(iter)); + serialize_impl>::op(std::forward(value), std::forward(buffer), std::forward(index)); } } }; - template class serializer : protected serialization_iterator, derived_type> { + template class serializer { public: - using iterator_type = serialization_iterator, derived_type>; - template friend struct serialize_impl; JSONIFIER_INLINE serializer& operator=(const serializer& other) = delete; JSONIFIER_INLINE serializer(const serializer& other) = delete; - template + template JSONIFIER_INLINE void serializeJson(value_type&& data, buffer_type&& iter) { - iterator_type::reset(); derivedRef.errors.clear(); - serialize::template op(std::forward(data), std::forward(*this)); - if (iter.size() != iterator_type::currentSize) [[unlikely]] { - iter.resize(iterator_type::currentSize); - } - std::memcpy(iter.data(), iterator_type::data(), iterator_type::currentSize); + index = 0; + serialize::op(std::forward(data), derivedRef.stringBuffer, index); + iter.resize(index); + std::memcpy(iter.data(), derivedRef.stringBuffer.data(), index); } protected: derived_type& derivedRef{ initializeSelfRef() }; + uint64_t index{}; JSONIFIER_INLINE serializer() noexcept : derivedRef{ initializeSelfRef() } {}; diff --git a/Include/jsonifier/Simd.hpp b/Include/jsonifier/Simd.hpp index ae5c6a541..57711c2a3 100644 --- a/Include/jsonifier/Simd.hpp +++ b/Include/jsonifier/Simd.hpp @@ -41,7 +41,7 @@ namespace jsonifier_internal { } JSONIFIER_INLINE uint64_t getRemainder(string_buffer_ptr dest) const noexcept { - if (length == index) { + if (length == index) [[unlikely]] { return 0; } std::memset(dest, 0x20, BitsPerStep); @@ -66,7 +66,7 @@ namespace jsonifier_internal { uint64_t index{}; }; - class simd_string_reader : public simd_base { + template class simd_string_reader { public: using size_type = uint64_t; using allocator = alloc_wrapper; @@ -75,11 +75,17 @@ namespace jsonifier_internal { template JSONIFIER_INLINE void reset(char_type* stringViewNew, size_type size) { if constexpr (refreshString) { currentParseBuffer = jsonifier::string_view_base{ reinterpret_cast(stringViewNew), size }; - structuralIndices.resize(roundUpToMultiple<8>(static_cast(static_cast(currentParseBuffer.size()) * multiplier))); + auto newSize = roundUpToMultiple(static_cast(static_cast(currentParseBuffer.size()) * multiplier)); + if (structuralIndices.size() < newSize) [[unlikely]] { + structuralIndices.resize(newSize); + } resetInternal(); - } else if (currentParseBuffer != stringViewNew) { + } else if (currentParseBuffer != stringViewNew) [[likely]] { currentParseBuffer = jsonifier::string_view_base{ reinterpret_cast(stringViewNew), size }; - structuralIndices.resize(roundUpToMultiple<8>(static_cast(static_cast(currentParseBuffer.size()) * multiplier))); + auto newSize = roundUpToMultiple(static_cast(static_cast(currentParseBuffer.size()) * multiplier)); + if (structuralIndices.size() < newSize) [[unlikely]] { + structuralIndices.resize(newSize); + } resetInternal(); } } @@ -92,19 +98,27 @@ namespace jsonifier_internal { } if constexpr (refreshString) { currentParseBuffer = { reinterpret_cast(stringViewNew), size }; - structuralIndices.resize(roundUpToMultiple<8>(static_cast(static_cast(currentParseBuffer.size()) * multiplier))); + auto newSize = roundUpToMultiple(static_cast(static_cast(currentParseBuffer.size()) * multiplier)); + if (structuralIndices.size() < newSize) { + structuralIndices.resize(newSize); + } return returnValue + resetInternalWithErrorPrintOut(errorIndex); } else if (currentParseBuffer != stringViewNew) { currentParseBuffer = { reinterpret_cast(stringViewNew), size }; - structuralIndices.resize(roundUpToMultiple<8>(static_cast(static_cast(currentParseBuffer.size()) * multiplier))); + auto newSize = roundUpToMultiple(static_cast(static_cast(currentParseBuffer.size()) * multiplier)); + if (structuralIndices.size() < newSize) { + structuralIndices.resize(newSize); + } return returnValue + resetInternalWithErrorPrintOut(errorIndex); } } JSONIFIER_INLINE void resetInternal() { stringBlockReader.reset(currentParseBuffer.data(), currentParseBuffer.size()); - stringIndex = 0; - tapeIndex = 0; + overflow = false; + prevInString = 0; + stringIndex = 0; + tapeIndex = 0; generateJsonIndices(); } @@ -130,12 +144,12 @@ namespace jsonifier_internal { simd_int_t escaped{}; simd_int_t quotes{}; simd_int_t op{}; - alignas(BytesPerStep) size_type newBits[SixtyFourBitsPerStep]{}; + jsonifier::vector structuralIndices{}; + JSONIFIER_ALIGN size_type newBits[SixtyFourBitsPerStep]{}; jsonifier::string_view_base currentParseBuffer{}; - int64_t prevInString{}; - structural_index_vector structuralIndices{}; string_block_reader stringBlockReader{}; size_type stringIndex{}; + int64_t prevInString{}; size_type tapeIndex{}; bool overflow{}; @@ -144,12 +158,12 @@ namespace jsonifier_internal { generateStructurals(stringBlockReader.fullBlock()); } uint8_t block[BitsPerStep]{}; - if (stringBlockReader.getRemainder(block) > 0) { + if (stringBlockReader.getRemainder(block) > 0) [[likely]] { generateStructurals(block); } } - JSONIFIER_INLINE size_type getTapeLength() { + JSONIFIER_INLINE size_type getTapeLength() const { return tapeIndex - 1; } @@ -167,10 +181,10 @@ namespace jsonifier_internal { JSONIFIER_INLINE void generateStructurals(string_view_ptr values) { collectStringValues(values, std::make_index_sequence{}); - whitespace = collectWhitespaceAsSimdBase(newPtr, std::make_index_sequence{}); - backslashes = collectBackslashesAsSimdBase(newPtr, std::make_index_sequence{}); - op = collectStructuralsAsSimdBase(newPtr, std::make_index_sequence{}); - quotes = collectQuotesAsSimdBase(newPtr, std::make_index_sequence{}); + whitespace = simd_base::collectWhitespaceAsSimdBase(newPtr, std::make_index_sequence{}); + backslashes = simd_base::collectBackslashesAsSimdBase(newPtr, std::make_index_sequence{}); + op = simd_base::collectStructuralsAsSimdBase(newPtr, std::make_index_sequence{}); + quotes = simd_base::collectQuotesAsSimdBase(newPtr, std::make_index_sequence{}); collectStructurals(); addTapeValues(std::make_index_sequence{}); stringIndex += BitsPerStep; @@ -178,11 +192,11 @@ namespace jsonifier_internal { template JSONIFIER_INLINE void addTapeValues(std::index_sequence) { store(structurals, newBits); - (addTapeValuesHelper(), ...); + (addTapeValuesImpl(), ...); } - template JSONIFIER_INLINE void addTapeValuesHelper() { - if (!newBits[index]) { + template JSONIFIER_INLINE void addTapeValuesImpl() { + if (!newBits[index]) [[unlikely]] { return; } auto cnt = popcnt(newBits[index]); @@ -194,13 +208,13 @@ namespace jsonifier_internal { } JSONIFIER_INLINE void collectNonEmptyEscaped() noexcept { - simd_int_t potentialEscape = opAndNot(backslashes, nextIsEscaped); - simd_int_t maybeEscaped = shl<1>(potentialEscape, std::make_index_sequence{}); - simd_int_t maybeEscapedAndOddBits = opOr(maybeEscaped, oddBitsVal); - simd_int_t evenSeriesCodesAndOddBits = opSub(maybeEscapedAndOddBits, potentialEscape, std::make_index_sequence{}); - simd_int_t escapeAndTerminalCode = opXor(evenSeriesCodesAndOddBits, oddBitsVal); - escaped = opXor(escapeAndTerminalCode, opOr(backslashes, nextIsEscaped)); - nextIsEscaped = setLSB(nextIsEscaped, getMSB(opAnd(escapeAndTerminalCode, backslashes))); + simd_int_t potentialEscape = simd_base::opAndNot(backslashes, nextIsEscaped); + simd_int_t maybeEscaped = simd_base::shl<1>(potentialEscape, std::make_index_sequence{}); + simd_int_t maybeEscapedAndOddBits = simd_base::opOr(maybeEscaped, oddBitsVal); + simd_int_t evenSeriesCodesAndOddBits = simd_base::opSub(maybeEscapedAndOddBits, potentialEscape, std::make_index_sequence{}); + simd_int_t escapeAndTerminalCode = simd_base::opXor(evenSeriesCodesAndOddBits, oddBitsVal); + escaped = simd_base::opXor(escapeAndTerminalCode, simd_base::opOr(backslashes, nextIsEscaped)); + nextIsEscaped = simd_base::setLSB(nextIsEscaped, simd_base::getMSB(simd_base::opAnd(escapeAndTerminalCode, backslashes))); } JSONIFIER_INLINE void collectEmptyEscaped() { @@ -210,24 +224,24 @@ namespace jsonifier_internal { } JSONIFIER_INLINE void collectEscapedCharacters() { - return opBool(backslashes) ? collectNonEmptyEscaped() : collectEmptyEscaped(); + return simd_base::opBool(backslashes) ? collectNonEmptyEscaped() : collectEmptyEscaped(); } JSONIFIER_INLINE void collectStructurals() { collectEscapedCharacters(); - quotes = opAndNot(quotes, escaped); - simd_int_t inString = carrylessMultiplication(quotes, prevInString, std::make_index_sequence{}); - simd_int_t stringTail = opXor(inString, quotes); - simd_int_t scalar = opNot(opOr(op, whitespace)); - simd_int_t nonQuoteScalar = opAndNot(scalar, quotes); - simd_int_t followsNonQuoteScalar = follows(nonQuoteScalar, overflow); - simd_int_t potentialScalarStart = opAndNot(scalar, followsNonQuoteScalar); - simd_int_t porentialStructuralStart = opOr(op, potentialScalarStart); - structurals = opAndNot(porentialStructuralStart, stringTail); + quotes = simd_base::opAndNot(quotes, escaped); + simd_int_t inString = simd_base::carrylessMultiplication(quotes, prevInString, std::make_index_sequence{}); + simd_int_t stringTail = simd_base::opXor(inString, quotes); + simd_int_t scalar = simd_base::opNot(simd_base::opOr(op, whitespace)); + simd_int_t nonQuoteScalar = simd_base::opAndNot(scalar, quotes); + simd_int_t followsNonQuoteScalar = simd_base::follows(nonQuoteScalar, overflow); + simd_int_t potentialScalarStart = simd_base::opAndNot(scalar, followsNonQuoteScalar); + simd_int_t porentialStructuralStart = simd_base::opOr(op, potentialScalarStart); + structurals = simd_base::opAndNot(porentialStructuralStart, stringTail); } JSONIFIER_INLINE std::string collectEscapedCharactersWithErrorPrintOut(size_type errorIndex) { - if (opBool(backslashes)) { + if (simd_base::opBool(backslashes)) { return collectNonEmptyEscapedWithErrorPrintOut(errorIndex); } else { collectEmptyEscaped(); @@ -250,10 +264,10 @@ namespace jsonifier_internal { JSONIFIER_INLINE std::string generateStructuralsWithErrorPrintOut(string_view_ptr values, size_type errorIndex) { std::stringstream returnValue{}; collectStringValues(values, std::make_index_sequence{}); - whitespace = collectWhitespaceAsSimdBase(newPtr, std::make_index_sequence{}); - backslashes = collectBackslashesAsSimdBase(newPtr, std::make_index_sequence{}); - op = collectStructuralsAsSimdBase(newPtr, std::make_index_sequence{}); - quotes = collectQuotesAsSimdBase(newPtr, std::make_index_sequence{}); + whitespace = simd_base::collectWhitespaceAsSimdBase(newPtr, std::make_index_sequence{}); + backslashes = simd_base::collectBackslashesAsSimdBase(newPtr, std::make_index_sequence{}); + op = simd_base::collectStructuralsAsSimdBase(newPtr, std::make_index_sequence{}); + quotes = simd_base::collectQuotesAsSimdBase(newPtr, std::make_index_sequence{}); if (stringIndex == errorIndex) { returnValue << "Whitespace Bits, for Index: " + std::to_string(stringIndex) + ": "; returnValue << printBits(whitespace).data(); @@ -275,13 +289,13 @@ namespace jsonifier_internal { JSONIFIER_INLINE std::string collectNonEmptyEscapedWithErrorPrintOut(size_type errorIndex) noexcept { std::stringstream returnValue{}; - simd_int_t potentialEscape = opAndNot(backslashes, nextIsEscaped); - simd_int_t maybeEscaped = shl<1>(potentialEscape, std::make_index_sequence{}); - simd_int_t maybeEscapedAndOddBits = opOr(maybeEscaped, oddBitsVal); - simd_int_t evenSeriesCodesAndOddBits = opSub(maybeEscapedAndOddBits, potentialEscape, std::make_index_sequence{}); - simd_int_t escapeAndTerminalCode = opXor(evenSeriesCodesAndOddBits, oddBitsVal); - escaped = opXor(escapeAndTerminalCode, opOr(backslashes, nextIsEscaped)); - nextIsEscaped = setLSB(nextIsEscaped, getMSB(opAnd(escapeAndTerminalCode, backslashes))); + simd_int_t potentialEscape = simd_base::opAndNot(backslashes, nextIsEscaped); + simd_int_t maybeEscaped = simd_base::shl<1>(potentialEscape, std::make_index_sequence{}); + simd_int_t maybeEscapedAndOddBits = simd_base::opOr(maybeEscaped, oddBitsVal); + simd_int_t evenSeriesCodesAndOddBits = simd_base::opSub(maybeEscapedAndOddBits, potentialEscape, std::make_index_sequence{}); + simd_int_t escapeAndTerminalCode = simd_base::opXor(evenSeriesCodesAndOddBits, oddBitsVal); + escaped = simd_base::opXor(escapeAndTerminalCode, simd_base::opOr(backslashes, nextIsEscaped)); + nextIsEscaped = simd_base::setLSB(nextIsEscaped, simd_base::getMSB(simd_base::opAnd(escapeAndTerminalCode, backslashes))); if (stringIndex == errorIndex) { returnValue << "Potential Escape Bits, for Index: " + std::to_string(stringIndex) + ": "; returnValue << printBits(potentialEscape).data(); @@ -302,15 +316,15 @@ namespace jsonifier_internal { JSONIFIER_INLINE std::string collectStructuralsWithErrorPrintOut(size_type errorIndex) { std::stringstream returnValue{}; std::string returnValueNew = collectEscapedCharactersWithErrorPrintOut(errorIndex); - quotes = opAndNot(quotes, escaped); - simd_int_t inString = carrylessMultiplication(quotes, prevInString, std::make_index_sequence{}); - simd_int_t stringTail = opXor(inString, quotes); - simd_int_t scalar = opNot(opOr(op, whitespace)); - simd_int_t nonQuoteScalar = opAndNot(scalar, quotes); - simd_int_t followsNonQuoteScalar = follows(nonQuoteScalar, overflow); - simd_int_t potentialScalarStart = opAndNot(scalar, followsNonQuoteScalar); - simd_int_t porentialStructuralStart = opOr(op, potentialScalarStart); - structurals = opAndNot(porentialStructuralStart, stringTail); + quotes = simd_base::opAndNot(quotes, escaped); + simd_int_t inString = simd_base::carrylessMultiplication(quotes, prevInString, std::make_index_sequence{}); + simd_int_t stringTail = simd_base::opXor(inString, quotes); + simd_int_t scalar = simd_base::opNot(simd_base::opOr(op, whitespace)); + simd_int_t nonQuoteScalar = simd_base::opAndNot(scalar, quotes); + simd_int_t followsNonQuoteScalar = simd_base::follows(nonQuoteScalar, overflow); + simd_int_t potentialScalarStart = simd_base::opAndNot(scalar, followsNonQuoteScalar); + simd_int_t porentialStructuralStart = simd_base::opOr(op, potentialScalarStart); + structurals = simd_base::opAndNot(porentialStructuralStart, stringTail); if (stringIndex == errorIndex) { returnValue << returnValueNew; returnValue << "Escaped Bits, for Index: " + std::to_string(stringIndex) + ": "; diff --git a/Include/jsonifier/SimdStructuralIterator.hpp b/Include/jsonifier/SimdStructuralIterator.hpp index 1a112d7ac..25bc68a6d 100644 --- a/Include/jsonifier/SimdStructuralIterator.hpp +++ b/Include/jsonifier/SimdStructuralIterator.hpp @@ -28,7 +28,7 @@ namespace jsonifier_internal { - template class simd_structural_iterator { + template class simd_structural_iterator { public: friend class derailleur; @@ -40,7 +40,11 @@ namespace jsonifier_internal { using difference_type = std::ptrdiff_t; using size_type = uint64_t; - JSONIFIER_INLINE simd_structural_iterator() noexcept : selfRef{ initializeSelfRef() } {}; + JSONIFIER_INLINE simd_structural_iterator() noexcept {}; + + JSONIFIER_INLINE simd_structural_iterator(structural_index* sectionNew, jsonifier::string_base& bufferStringNew, + jsonifier::vector& errorsNew) noexcept + : stringBuffer{ &bufferStringNew }, errors{ &errorsNew }, rootIndex{ sectionNew } {}; JSONIFIER_INLINE simd_structural_iterator& operator=(const simd_structural_iterator& other) noexcept { if (this != &other) { @@ -50,84 +54,84 @@ namespace jsonifier_internal { }; JSONIFIER_INLINE simd_structural_iterator(const simd_structural_iterator& other) noexcept - : selfRef{ initializeSelfRef() }, currentIndex(other.currentIndex), rootIndex(other.rootIndex) { - selfRef = *static_cast(this); - } + : stringBuffer{ other.stringBuffer }, errors{ other.errors }, rootIndex{ other.rootIndex }, currentIndex{ other.currentIndex } {}; JSONIFIER_INLINE value_type operator*() const { - return (*currentIndex) ? **currentIndex : defaultValue; + return (rootIndex[currentIndex]) ? *rootIndex[currentIndex] : defaultValue; } JSONIFIER_INLINE pointer operator->() const { - return *currentIndex; + return rootIndex[currentIndex]; } - JSONIFIER_INLINE simd_structural_iterator& operator++() { + JSONIFIER_INLINE simd_structural_iterator& operator++() { ++currentIndex; return *this; } template JSONIFIER_INLINE void createError(std::source_location location = std::source_location::current()) { - selfRef.errors.emplace_back(jsonifier_internal::createError(*this, location)); + errors->emplace_back(jsonifier_internal::createError(*this, location)); } - JSONIFIER_INLINE simd_structural_iterator operator++(int32_t) { - simd_structural_iterator temp{ *this }; + JSONIFIER_INLINE simd_structural_iterator operator++(int32_t) { + simd_structural_iterator temp{ *this }; ++(*this); return temp; } JSONIFIER_INLINE pointer getEndPtr() const { - auto newIndex = currentIndex; + auto newIndex = rootIndex + currentIndex; while (*(newIndex + 1) != nullptr) { ++newIndex; } return *newIndex; } - JSONIFIER_INLINE void reset(structural_index* rootIndexNew) { - currentIndex = rootIndexNew; - rootIndex = rootIndexNew; - } - - JSONIFIER_INLINE pointer getRootPtr() const { - return *rootIndex; + JSONIFIER_INLINE size_type size() const { + return stringBuffer->size(); } - JSONIFIER_INLINE typename jsonifier::string_base::pointer data() const { - return selfRef.stringBuffer.data(); + JSONIFIER_INLINE void resize(size_type newSize) const { + return stringBuffer->resize(newSize); } - JSONIFIER_INLINE void resize(size_type newSize) { - selfRef.stringBuffer.resize(newSize); + JSONIFIER_INLINE uint8_t* data() { + return stringBuffer->data(); } - JSONIFIER_INLINE size_type size() const { - return selfRef.stringBuffer.size(); + JSONIFIER_INLINE pointer getRootPtr() const { + return *rootIndex; } - JSONIFIER_INLINE buffer_string& getCurrentString() { - return selfRef.stringBuffer; + JSONIFIER_INLINE jsonifier::string_base& getCurrentString() { + return *stringBuffer; } JSONIFIER_INLINE size_type getCurrentStringIndex() const { - return static_cast((*currentIndex) - (*rootIndex)); + return currentIndex; } JSONIFIER_INLINE bool operator==(const simd_structural_iterator&) const { - return !(*currentIndex); + return !(rootIndex[currentIndex]); + } + + JSONIFIER_INLINE operator bool() const { + return *(rootIndex + currentIndex) != nullptr; } JSONIFIER_INLINE void swap(simd_structural_iterator& other) { + std::swap(stringBuffer, other.stringBuffer); std::swap(currentIndex, other.currentIndex); std::swap(rootIndex, other.rootIndex); + std::swap(errors, other.errors); } protected: - second_derived_type& selfRef{ *static_cast(this) }; + jsonifier::string_base* stringBuffer{}; static constexpr value_type defaultValue{ 0x00ll }; - pointer_internal currentIndex{}; + jsonifier::vector* errors{}; pointer_internal rootIndex{}; + uint64_t currentIndex{}; second_derived_type& initializeSelfRef() { return *static_cast(this); diff --git a/Include/jsonifier/StrToD.hpp b/Include/jsonifier/StrToD.hpp index 5aa6f4974..2ed54afe8 100644 --- a/Include/jsonifier/StrToD.hpp +++ b/Include/jsonifier/StrToD.hpp @@ -39,7 +39,7 @@ namespace jsonifier_internal { // https://stackoverflow.com/questions/28868367/getting-the-high-part-of-64-bit-integer-multiplication -#if defined(__SIZEOF_INT128__) +#ifdef __SIZEOF_INT128__ JSONIFIER_INLINE uint64_t mulhi64(uint64_t a, uint64_t b) { #if defined(__GNUC__) || defined(__GNUG__) #pragma GCC diagnostic push @@ -63,18 +63,18 @@ namespace jsonifier_internal { uint64_t axbMid = aHi * bLo; uint64_t bxaMid = bHi * aLo; uint64_t axbLo = aLo * bLo; - uint64_t carryBit = axbMid + bxaMid + (axbLo >> 32) >> 32; + uint64_t carryBit = (axbMid + bxaMid + (axbLo >> 32)) >> 32; uint64_t multhi = axbHi + (axbMid >> 32) + (bxaMid >> 32) + carryBit; return multhi; } #endif - constexpr int64_t pow10SigTableMinExp = -343; - constexpr int64_t pow10SigTableMaxExp = 324; - constexpr int64_t pow10SigTableMinExact = 0; - constexpr int64_t pow10SigTableMaxExact = 27; + constexpr auto pow10SigTableMinExp{ -343 }; + constexpr auto pow10SigTableMaxExp{ 324 }; + constexpr auto pow10SigTableMinExact{ 0 }; + constexpr auto pow10SigTableMaxExact{ 27 }; - JSONIFIER_INLINE uint64_t sig2FromExp10(uint64_t exp10) noexcept { + JSONIFIER_INLINE uint64_t sig2FromExp10(int64_t exp10) noexcept { return pow10SigTable[exp10 - pow10SigTableMinExp]; } @@ -84,26 +84,25 @@ namespace jsonifier_internal { constexpr uint8_t digiTypeZero = 1 << 0; constexpr uint8_t digiTypeNonZero = 1 << 1; - constexpr uint8_t digiTypeNeg = 1 << 3; constexpr uint8_t digiTypeDot = 1 << 4; constexpr uint8_t digiTypeExp = 1 << 5; - JSONIFIER_INLINE bool digiIsType(uint8_t d, uint8_t type) noexcept { - return (digiTable[d] & type) != 0; + template JSONIFIER_INLINE bool digiIsType(value_type d, value_type type) noexcept { + return (static_cast(digiTable[d]) & type) != 0; } - JSONIFIER_INLINE bool digiIsFp(uint8_t d) noexcept { - return digiIsType(d, uint8_t(digiTypeDot | digiTypeExp)); + template JSONIFIER_INLINE bool digiIsFp(value_type d) noexcept { + return digiIsType(d, value_type(digiTypeDot | digiTypeExp)); } - JSONIFIER_INLINE bool digiIsDigitOrFp(uint8_t d) noexcept { - return digiIsType(d, uint8_t(digiTypeZero | digiTypeNonZero | digiTypeDot | digiTypeExp)); + template JSONIFIER_INLINE bool digiIsDigitOrFp(value_type d) noexcept { + return digiIsType(d, value_type(digiTypeZero | digiTypeNonZero | digiTypeDot | digiTypeExp)); } #define repeat_in_1_18(x) \ { x(1) x(2) x(3) x(4) x(5) x(6) x(7) x(8) x(9) x(10) x(11) x(12) x(13) x(14) x(15) x(16) x(17) x(18) } - constexpr uint8_t eBit = static_cast(0x45u ^ 0x65u); + constexpr auto eBit = static_cast(0x45u ^ 0x65u); constexpr int64_t f64MaxDecExp = 308; constexpr int64_t f64MinDecExp = (-324); @@ -114,31 +113,31 @@ namespace jsonifier_internal { struct big_int_t final { std::vector data = {}; - big_int_t(uint64_t num) noexcept { - uint64_t lowerWord = num; - uint64_t upperWord = num >> 32; - if (upperWord > 0) { - data = { lowerWord, upperWord }; + JSONIFIER_INLINE big_int_t(uint64_t num) noexcept { + uint64_t lower_word = uint64_t(num); + uint64_t upper_word = uint64_t(num >> 32); + if (upper_word > 0) { + data = { lower_word, upper_word }; } else { - data = { lowerWord }; + data = { lower_word }; } } - void mulU32(uint64_t num) noexcept { + JSONIFIER_INLINE void mulU32(uint64_t num) noexcept { uint64_t carry = 0; - for (std::size_t x = 0; x < data.size(); x++) { - uint64_t res = data[x] * num + carry; - uint64_t lowerWord = res; - uint64_t upperWord = res >> 32; - data[x] = lowerWord; - carry = upperWord; + for (std::size_t i = 0; i < data.size(); i++) { + uint64_t res = uint64_t(data[i]) * uint64_t(num) + uint64_t(carry); + uint64_t lower_word = uint64_t(res); + uint64_t upper_word = uint64_t(res >> 32); + data[i] = lower_word; + carry = upper_word; } if (carry != 0) { data.emplace_back(carry); } } - void mulPow10(uint64_t pow10) noexcept { + JSONIFIER_INLINE void mulPow10(uint64_t pow10) noexcept { for (; pow10 >= 9; pow10 -= 9) { mulU32(static_cast(powersOfTenInt[9])); } @@ -147,7 +146,7 @@ namespace jsonifier_internal { } } - void mulPow2(uint64_t exp) noexcept { + JSONIFIER_INLINE void mulPow2(uint64_t exp) noexcept { uint64_t shft = exp % 32; uint64_t move = exp / 32; uint64_t idx = static_cast(data.size()) - 1; @@ -174,55 +173,66 @@ namespace jsonifier_internal { } } - auto operator<=>(const big_int_t& rhs) const noexcept { + JSONIFIER_INLINE auto operator<=>(const big_int_t& rhs) const noexcept { if (data.size() < rhs.data.size()) return -1; if (data.size() > rhs.data.size()) return 1; - for (auto x = data.size() - 1; x > 0; --x) { + for (auto i = data.size() - 1; i > 0; --i) { ; - if (data[x] < rhs.data[x]) + if (data[i] < rhs.data[i]) return -1; - if (data[x] > rhs.data[x]) + if (data[i] > rhs.data[i]) return 1; } return 0; } }; - template JSONIFIER_INLINE bool parseNumber(value_type01& value, char_type* cur) noexcept { - [[maybe_unused]] const char_type* sigEnd{}; - const char_type *tmp{}, *sigCut{}, *dotPos{}, *hdr{ cur }; - uint64_t fracZeros{}, numTmp{}, sig{}; - int64_t exp{}, expSig{}, expLit{}; - bool sign{ (*hdr == 0x2Du) }, expSign{}; + template + requires(sizeof(value_type) <= 8) + JSONIFIER_INLINE bool parseNumber(value_type& val, const char_type* cur) noexcept { + const char_type* sig_cut = nullptr; + [[maybe_unused]] const char_type* sig_end = nullptr; + const char_type* dot_pos = nullptr; + uint64_t frac_zeros = 0; + uint64_t sig = 0; + int64_t exp = 0; + bool exp_sign; + int64_t exp_sig = 0; + int64_t exp_lit = 0; + uint64_t num_tmp; + const char_type* tmp; + const char_type* hdr = cur; + bool sign = (*hdr == 0x2Du); cur += sign; - auto applySign = [&](auto&& value) -> value_type01 { - return sign ? -static_cast(value) : static_cast(value); + auto apply_sign = [&](auto&& val) -> value_type { + return sign ? -static_cast(val) : static_cast(val); }; - - sig = static_cast(asciiToValueTable[static_cast(*cur)]); + sig = uint64_t(*cur - 0x30u); if (sig > 9) { - if (*cur == 0x6Eu && cur[1] == 0x75u && cur[2] == 0x6Cu && cur[3] == 0x6Cu) { + if constexpr (std::integral) { + return false; + } else if (*cur == 0x6Eu && cur[1] == 0x75u && cur[2] == 0x6Cu && cur[3] == 0x6Cu) { cur += 4; - value = 0; + val = std::numeric_limits::quiet_NaN(); return true; } else if ((*cur | eBit) == 0x6Eu && (cur[1] | eBit) == 0x61u && (cur[2] | eBit) == 0x6Eu) { cur += 3; - value = sign ? -std::numeric_limits::quiet_NaN() : std::numeric_limits::quiet_NaN(); + val = sign ? -std::numeric_limits::quiet_NaN() : std::numeric_limits::quiet_NaN(); return true; } else { return false; } } - constexpr auto zero = static_cast(0x30u); -#define expr_intg(x) \ - if ((numTmp = static_cast(asciiToValueTable[static_cast(cur[x])])) <= 9) [[likely]] \ - sig = numTmp + sig * 10; \ + constexpr auto zero = static_cast(0x30u); +#define expr_intg(i) \ + if (num_tmp = static_cast(asciiToValueTable[static_cast(cur[i])]); num_tmp <= 9) [[likely]] \ + sig = num_tmp + sig * 10; \ else { \ if (*cur == zero) \ return false; \ - goto digi_sepr_##x; \ + goto digi_sepr_##i; \ } repeat_in_1_18(expr_intg); #undef expr_intg @@ -230,222 +240,220 @@ namespace jsonifier_internal { return false; } cur += 19; - if (!digiIsDigitOrFp(static_cast(*cur))) { - value = static_cast(sig); - if constexpr (!std::unsigned_integral) { - value *= sign ? -1 : 1; + if (!digiIsDigitOrFp(*cur)) { + val = static_cast(sig); + if constexpr (!std::is_unsigned_v) { + val *= sign ? -1 : 1; } return true; } goto digi_intg_more; -#define expr_sepr(x) \ - digi_sepr_##x : if ((!digiIsFp(static_cast(cur[x])))) [[likely]] { \ - cur += x; \ - value = applySign(sig); \ +#define expr_sepr(i) \ + digi_sepr_##i : if ((!digiIsFp(cur[i]))) [[likely]] { \ + cur += i; \ + val = apply_sign(sig); \ return true; \ } \ - dotPos = cur + x; \ - if ((cur[x] == 0x2Eu)) [[likely]] { \ + dot_pos = cur + i; \ + if ((cur[i] == 0x2Eu)) [[likely]] { \ if (sig == 0) \ - while (cur[fracZeros + x + 1] == zero) \ - ++fracZeros; \ - goto digi_frac_##x; \ + while (cur[frac_zeros + i + 1] == zero) \ + ++frac_zeros; \ + goto digi_frac_##i; \ } \ - cur += x; \ - sigEnd = cur; \ + cur += i; \ + sig_end = cur; \ goto digi_exp_more; repeat_in_1_18(expr_sepr) #undef expr_sepr -#define expr_frac(x) \ - digi_frac_##x : if (numTmp = static_cast(asciiToValueTable[cur[x + 1 + fracZeros]]); numTmp <= 9) [[likely]] sig = numTmp + sig * 10; \ +#define expr_frac(i) \ + digi_frac_##i : if (((num_tmp = static_cast(asciiToValueTable[cur[i + 1 + frac_zeros]]))); num_tmp <= 9) [[likely]] sig = num_tmp + sig * 10; \ else { \ - goto digi_stop_##x; \ + goto digi_stop_##i; \ } repeat_in_1_18(expr_frac) #undef expr_frac - cur += 20ull + fracZeros; - if (asciiToValueTable[static_cast(*cur)] > 9) + cur += 20 + frac_zeros; + if (char_type(asciiToValueTable[static_cast(*cur)]) > 9) goto digi_frac_end; goto digi_frac_more; -#define expr_stop(x) \ - digi_stop_##x : cur += x + 1 + fracZeros; \ +#define expr_stop(i) \ + digi_stop_##i : cur += i + 1 + frac_zeros; \ goto digi_frac_end; repeat_in_1_18(expr_stop) #undef expr_stop - digi_intg_more : static constexpr uint64_t u64Max = (std::numeric_limits::max)(); - if (numTmp = static_cast(asciiToValueTable[static_cast(*cur)]); numTmp < 10) { - if (!digiIsDigitOrFp(static_cast(cur[1]))) { - if ((sig < (u64Max / 10)) || (sig == (u64Max / 10) && numTmp <= (u64Max % 10))) { - sig = numTmp + sig * 10; + digi_intg_more : static constexpr uint64_t U64_MAX = (std::numeric_limits::max)();// todo + if ((num_tmp = static_cast(asciiToValueTable[static_cast(*cur)])) < 10) { + if (!digiIsDigitOrFp(cur[1])) { + if ((sig < (U64_MAX / 10)) || (sig == (U64_MAX / 10) && num_tmp <= (U64_MAX % 10))) { + sig = num_tmp + sig * 10; cur++; - value = static_cast(sig); - if constexpr (!std::unsigned_integral) { - value *= sign ? -1 : 1; + val = static_cast(sig); + if constexpr (!std::is_unsigned_v) { + val *= sign ? -1 : 1; } return true; } } } if ((eBit | *cur) == 0x65u) { - dotPos = cur; + dot_pos = cur; goto digi_exp_more; } if (*cur == 0x2Eu) { - dotPos = cur++; - if (asciiToValueTable[static_cast(*cur)] > 9) { + dot_pos = cur++; + if (char_type(asciiToValueTable[static_cast(*cur)]) > 9) { return false; } } digi_frac_more: - sigCut = cur; + sig_cut = cur; sig += (*cur >= 0x35u); - while (asciiToValueTable[*++cur] < 10) { + while (asciiToValueTable[static_cast(*++cur)] < 10) { } - if (!dotPos) { - dotPos = cur; + if (!dot_pos) { + dot_pos = cur; if (*cur == 0x2Eu) { - if (asciiToValueTable[*++cur] > 9) { + if (asciiToValueTable[static_cast(*++cur)] > 9) { return false; } - while (asciiToValueTable[*++cur] < 10) { + while (asciiToValueTable[static_cast(*++cur)] < 10) { } } } - expSig = static_cast(dotPos - sigCut); - expSig += (dotPos < sigCut); + exp_sig = static_cast(dot_pos - sig_cut); + exp_sig += (dot_pos < sig_cut); tmp = cur - 1; while (*tmp == 0x30u || *tmp == 0x2Eu) { --tmp; } - if (tmp < sigCut) { - sigCut = nullptr; + if (tmp < sig_cut) { + sig_cut = nullptr; } else { - sigEnd = cur; + sig_end = cur; } if ((eBit | *cur) == 0x65u) goto digi_exp_more; goto digi_exp_finish; digi_frac_end: - sigEnd = cur; - expSig = -int64_t((cur - dotPos) - 1); - if (expSig == 0) { + sig_end = cur; + exp_sig = -int64_t((cur - dot_pos) - 1); + if (exp_sig == 0) return false; - } if ((eBit | *cur) != 0x65u) [[likely]] { - if (expSig < f64MinDecExp - 19) [[unlikely]] { - value = applySign(0); + if ((exp_sig < f64MinDecExp - 19)) [[unlikely]] { + val = apply_sign(0); return true; } - exp = expSig; + exp = exp_sig; goto digi_finish; } else { goto digi_exp_more; } - digi_exp_more : { - expSign = (*++cur == 0x2Du); + digi_exp_more: + exp_sign = (*++cur == 0x2Du); cur += (*cur == 0x2Bu || *cur == 0x2Du); - if (asciiToValueTable[static_cast(*cur)] > 9) [[unlikely]] { + if (char_type(asciiToValueTable[static_cast(*cur)]) > 9) [[unlikely]] { return false; } while (*cur == 0x30u) { ++cur; } tmp = cur; - uint8_t c{}; - while (c < 10) { - c = static_cast(asciiToValueTable[static_cast(*cur)]); + char_type c; + while (char_type(c = asciiToValueTable[static_cast(*cur)]) < 10) { ++cur; - expLit = c + int64_t(expLit) * 10; + exp_lit = static_cast(c + uint64_t(exp_lit) * 10); } - if (cur - tmp >= 6) [[unlikely]] { - if (sig == 0 || expSign) { - value = applySign(0); - value = static_cast(sig); + if ((cur - tmp >= 6)) [[unlikely]] { + if (sig == 0 || exp_sign) { + val = apply_sign(0); + val = static_cast(sig); return true; } else { - value = applySign(std::numeric_limits::infinity()); + val = apply_sign(std::numeric_limits::infinity()); return true; } } - expSig += expSign ? -expLit : expLit; - } + exp_sig += exp_sign ? -exp_lit : exp_lit; digi_exp_finish: if (sig == 0) { - value = (sign ? -value_type01{ 0 } : value_type01{ 0 }); + val = (sign ? -value_type{ 0 } : value_type{ 0 }); return true; } - if (expSig < f64MinDecExp - 19) [[unlikely]] { - value = (sign ? -value_type01{ 0 } : value_type01{ 0 }); + if ((exp_sig < f64MinDecExp - 19)) [[unlikely]] { + val = (sign ? -value_type{ 0 } : value_type{ 0 }); return true; - } else if (expSig > f64MaxDecExp) [[unlikely]] { - value = sign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); + } else if ((exp_sig > f64MaxDecExp)) [[unlikely]] { + val = sign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); return true; } - exp = expSig; + exp = exp_sig; digi_finish: - if constexpr (std::same_as) { + if constexpr (std::is_same_v) { if (sig < (uint64_t(1) << 53) && std::abs(exp) <= 22) { - value = static_cast(sig); - if constexpr (!std::unsigned_integral) { - value *= sign ? -1 : 1; + val = static_cast(sig); + if constexpr (!std::is_unsigned_v) { + val *= sign ? -1 : 1; } if (exp >= 0 && exp < 23) { - value *= static_cast(powersOfTenFloat[exp]); - } else if (-exp < 23) { - value /= static_cast(powersOfTenFloat[-exp]); + val *= powersOfTenFloat[exp]; + } else if (auto newValue = -exp; exp < 0 && newValue < 23) { + val /= powersOfTenFloat[newValue]; } return true; } } else { if (sig < (uint64_t(1) << 24) && std::abs(exp) <= 8) { - value = static_cast(sig); - if constexpr (!std::unsigned_integral) { - value *= sign ? -1 : 1; + val = static_cast(sig); + if constexpr (!std::is_unsigned_v) { + val *= sign ? -1 : 1; } if (exp >= 0 && exp < 23) { - value *= static_cast(powersOfTenFloat[exp]); - } else if (-exp < 23) { - value /= static_cast(powersOfTenFloat[-exp]); + val *= static_cast(powersOfTenFloat[exp]); + } else if (exp < 0 && -exp < 23) { + val /= static_cast(powersOfTenFloat[-exp]); } return true; } } if (sig == 0) [[unlikely]] { - value = value_type01(0); + val = value_type(0); return true; } - static_assert(std::numeric_limits::is_iec559); - static_assert(std::numeric_limits::radix == 2); - static_assert(std::same_as> || std::same_as>); + static_assert(std::numeric_limits::is_iec559); + static_assert(std::numeric_limits::radix == 2); + static_assert(std::is_same_v> || std::is_same_v>); static_assert(sizeof(float) == 4 && sizeof(double) == 8); - const auto sigLeadingZeros = std::countl_zero(sig); - const auto sigNorm = sig << sigLeadingZeros; - const auto sig2Norm = sig2FromExp10(static_cast(exp)); - const auto sigProduct = mulhi64(sigNorm, sig2Norm) + 1; - const auto sigProductStartsWith1 = sigProduct >> 63; - auto mantisa = sigProduct << (2 - sigProductStartsWith1); - constexpr uint64_t roundMask = uint64_t(1) << 63 >> (std::numeric_limits::digits - 1); - constexpr uint64_t exponentBits = ceillog2(std::numeric_limits::max_exponent - std::numeric_limits::min_exponent + 1); - constexpr uint64_t mantissaShift = exponentBits + 1 + 64 - 8 * sizeof(uint64_t); - int64_t exp2 = static_cast(exp2FromExp10(exp) + static_cast(-sigLeadingZeros + sigProductStartsWith1)); - - if (exp2 < std::numeric_limits::min_exponent - 1) [[unlikely]] { - value = sign ? -value_type01(0) : value_type01(0); + using raw_t = std::conditional_t>, uint64_t, uint64_t>; + const auto sig_leading_zeros = std::countl_zero(sig); + const auto sig_norm = sig << sig_leading_zeros; + const auto sig2_norm = sig2FromExp10(exp); + const auto sig_product = mulhi64(sig_norm, sig2_norm) + 1; + const auto sig_product_starts_with_1 = sig_product >> 63; + auto mantisa = sig_product << (2 - sig_product_starts_with_1); + constexpr uint64_t round_mask = uint64_t(1) << 63 >> (std::numeric_limits::digits - 1); + constexpr uint64_t exponent_bits = ceillog2(std::numeric_limits::max_exponent - std::numeric_limits::min_exponent + 1); + constexpr uint64_t mantisa_shift = exponent_bits + 1 + 64 - 8 * sizeof(raw_t); + int64_t exp2 = static_cast(exp2FromExp10(exp) + static_cast(-sig_leading_zeros + sig_product_starts_with_1)); + + if (exp2 < std::numeric_limits::min_exponent - 1) [[unlikely]] { + val = sign ? -value_type(0) : value_type(0); return true; - } else if (exp2 > std::numeric_limits::max_exponent - 1) [[unlikely]] { - value = sign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); + } else if (exp2 > std::numeric_limits::max_exponent - 1) [[unlikely]] { + val = sign ? -std::numeric_limits::infinity() : std::numeric_limits::infinity(); return true; } uint64_t round = 0; - if (roundMask & mantisa) { - if (mantisa << (std::numeric_limits::digits) == 0) { - auto sig_upper = (mantisa >> (mantissaShift - 1)) | (uint64_t(1) << 63 >> (mantissaShift - 2)) | 1; - int64_t exp2_upper = exp2 - std::numeric_limits::digits; + if (round_mask & mantisa) { + if (mantisa << (std::numeric_limits::digits) == 0) { + auto sig_upper = (mantisa >> (mantisa_shift - 1)) | (uint64_t(1) << 63 >> (mantisa_shift - 2)) | 1; + int64_t exp2_upper = exp2 - std::numeric_limits::digits; big_int_t big_comp{ sig_upper }; big_int_t big_full{ sig }; @@ -463,19 +471,19 @@ namespace jsonifier_internal { if (cmp != 0) [[likely]] { round = (cmp > 0); } else { - round = (mantisa & (roundMask << 1)) != 0; + round = (mantisa & (round_mask << 1)) != 0; } - } else if ((exp < pow10SigTableMinExact || exp > pow10SigTableMaxExact) || (mantisa & (roundMask << 1)) || - (static_cast(std::countr_zero(sigNorm)) + static_cast(std::countr_zero(sig2Norm)) < - 128 - std::numeric_limits::digits - (2 - sigProductStartsWith1))) { + } else if ((exp < pow10SigTableMinExact || exp > pow10SigTableMaxExact) || (mantisa & (round_mask << 1)) || + (static_cast(tzcnt(sig_norm) + tzcnt(sig2_norm)) < 128 - std::numeric_limits::digits - (2 - sig_product_starts_with_1))) { round = 1; } } - auto num = uint64_t(sign) << (sizeof(uint64_t) * 8 - 1) | uint64_t(mantisa >> mantissaShift) | - (uint64_t(exp2 + std::numeric_limits::max_exponent - 1) << (std::numeric_limits::digits - 1)); - num += uint64_t(round); - std::memcpy(&value, &num, sizeof(value_type01)); + auto num = raw_t(sign) << (sizeof(raw_t) * 8 - 1) | raw_t(mantisa >> mantisa_shift) | + (raw_t(exp2 + std::numeric_limits::max_exponent - 1) << (std::numeric_limits::digits - 1)); + num += raw_t(round); + std::memcpy(&val, &num, sizeof(value_type)); return true; } + } \ No newline at end of file diff --git a/Include/jsonifier/String.hpp b/Include/jsonifier/String.hpp index cd90e39f5..fc6f35d96 100644 --- a/Include/jsonifier/String.hpp +++ b/Include/jsonifier/String.hpp @@ -93,7 +93,7 @@ namespace jsonifier { template class string_view_base; - template class string_base : protected jsonifier_internal::alloc_wrapper { + template class string_base : protected jsonifier_internal::alloc_wrapper { public: using value_type = value_type_new; using pointer = value_type*; @@ -109,13 +109,17 @@ namespace jsonifier { using allocator = jsonifier_internal::alloc_wrapper; using traits_type = jsonifier_internal::char_traits; - JSONIFIER_INLINE string_base() : capacityVal{}, sizeVal{}, dataVal{} {}; + JSONIFIER_INLINE string_base() : capacityVal{}, sizeVal{}, dataVal{} { + if constexpr (doWeUseInitialBuffer) { + resize(1024 * 1024 * 4); + } + }; static constexpr size_type bufSize = 16 / sizeof(value_type) < 1 ? 1 : 16 / sizeof(value_type); static constexpr size_type npos{ std::numeric_limits::max() }; JSONIFIER_INLINE string_base& operator=(string_base&& other) noexcept { - if (this != &other) { + if (this != &other) [[likely]] { string_base{ other }.swap(*this); } return *this; @@ -126,7 +130,7 @@ namespace jsonifier { }; JSONIFIER_INLINE string_base& operator=(const string_base& other) { - if (this != &other) { + if (this != &other) [[likely]] { string_base{ other }.swap(*this); } return *this; @@ -134,11 +138,11 @@ namespace jsonifier { JSONIFIER_INLINE string_base(const string_base& other) : capacityVal{}, sizeVal{}, dataVal{} { size_type newSize = other.size(); - if (newSize > 0 && newSize < maxSize()) [[likely]] { + if (newSize > 0 && newSize < max_size()) [[likely]] { reserve(newSize); sizeVal = newSize; std::uninitialized_copy(other.data(), other.data() + newSize, dataVal); - allocator::construct(&(*this)[newSize], static_cast(0x00)); + allocator::construct(&(*this)[newSize], value_type{}); } } @@ -149,11 +153,11 @@ namespace jsonifier { template JSONIFIER_INLINE explicit string_base(const value_type_newer& other) : capacityVal{}, sizeVal{}, dataVal{} { size_type newSize = other.size() * (sizeof(typename jsonifier::concepts::unwrap::value_type) / sizeof(value_type)); - if (newSize > 0 && newSize < maxSize()) [[likely]] { + if (newSize > 0 && newSize < max_size()) [[likely]] { reserve(newSize); sizeVal = newSize; std::uninitialized_copy(other.data(), other.data() + newSize, dataVal); - allocator::construct(&(*this)[newSize], static_cast(0x00)); + allocator::construct(&(*this)[newSize], value_type{}); } } @@ -165,50 +169,50 @@ namespace jsonifier { template JSONIFIER_INLINE string_base(value_type_newer other) : capacityVal{}, sizeVal{}, dataVal{} { auto newSize = jsonifier_internal::char_traits>::length(other) * (sizeof(std::remove_pointer_t) / sizeof(value_type)); - if (newSize > 0 && newSize < maxSize()) [[likely]] { + if (newSize > 0 && newSize < max_size()) [[likely]] { reserve(newSize); sizeVal = newSize; std::uninitialized_copy(other, other + newSize, dataVal); - allocator::construct(&(*this)[newSize], static_cast(0x00)); + allocator::construct(&(*this)[newSize], value_type{}); } } - template JSONIFIER_INLINE string_base& operator=(value_type_newer other) { + template JSONIFIER_INLINE string_base& operator=(value_type_newer other) { pushBack(static_cast(other)); return *this; } - template JSONIFIER_INLINE string_base(value_type_newer other) : capacityVal{}, sizeVal{}, dataVal{} { + template JSONIFIER_INLINE string_base(value_type_newer other) : capacityVal{}, sizeVal{}, dataVal{} { *this = other; } JSONIFIER_INLINE string_base(const_pointer other, uint64_t newSize) : capacityVal{}, sizeVal{}, dataVal{} { - if (newSize > 0 && newSize < maxSize()) [[likely]] { + if (newSize > 0 && newSize < max_size()) [[likely]] { reserve(newSize); sizeVal = newSize; std::uninitialized_copy(other, other + newSize, dataVal); - allocator::construct(&(*this)[newSize], static_cast(0x00)); + allocator::construct(&(*this)[newSize], value_type{}); } } JSONIFIER_INLINE string_base substr(size_type position, size_type count = std::numeric_limits::max()) const { - if (position >= sizeVal) { + if (static_cast(position) >= static_cast(sizeVal)) [[unlikely]] { throw std::out_of_range("Substring position is out of range."); } count = std::min(count, sizeVal - position); string_base result{}; - if (count > 0) { + if (count > 0) [[likely]] { result.resize(count); std::memcpy(result.dataVal, dataVal + position, count * sizeof(value_type)); } return result; } - constexpr size_type maxSize() { - const size_type allocMax = allocator::maxSize(); - const size_type storageMax = std::max(allocMax, static_cast(bufSize)); + constexpr size_type max_size() { + const size_type allocMax = allocator::max_size(*this); + const size_type storageMax = jsonifier_internal::max(allocMax, static_cast(bufSize)); return std::min(static_cast((std::numeric_limits::max)()), storageMax - 1); } @@ -244,65 +248,45 @@ namespace jsonifier { return const_reverse_iterator{ begin() }; } - JSONIFIER_INLINE size_type find(const_pointer args, size_type position = 0) const { - auto newSize = traits_type::length(args); - if (position + newSize > sizeVal) { - return npos; - } - auto foundValue = jsonifier_internal::find(dataVal + position, sizeVal - position, args, newSize); - return foundValue == npos ? npos : foundValue + position; - } - - template JSONIFIER_INLINE size_type find(value_type_newer args, size_type position = 0) const { - value_type newValue{ static_cast(args) }; - if (position + 1 > sizeVal) { - return npos; - } - auto foundValue = jsonifier_internal::find(dataVal + position, sizeVal - position, &newValue, 1); - return foundValue == npos ? npos : foundValue + position; - } - - template JSONIFIER_INLINE size_type find(const value_type_newer& args, size_type position = 0) const { - if (position + args.size() > sizeVal) { - return npos; - } - auto foundValue = jsonifier_internal::find(dataVal + position, sizeVal - position, args.data(), args.size()); - return foundValue == npos ? npos : foundValue + position; + template JSONIFIER_INLINE size_type find(arg_types&&... args) const { + return operator std::basic_string_view().find(std::forward(args)...); } - template JSONIFIER_INLINE size_type findFirstOf(arg_types&&... args) const { + template constexpr size_type findFirstOf(arg_types&&... args) const { return operator std::basic_string_view().find_first_of(std::forward(args)...); } - template JSONIFIER_INLINE size_type findLastOf(arg_types&&... args) const { + template constexpr size_type findLastOf(arg_types&&... args) const { return operator std::basic_string_view().find_last_of(std::forward(args)...); } - template JSONIFIER_INLINE size_type findFirstNotOf(arg_types&&... args) const { + template constexpr size_type findFirstNotOf(arg_types&&... args) const { return operator std::basic_string_view().find_first_not_of(std::forward(args)...); } - template JSONIFIER_INLINE size_type findLastNotOf(arg_types&&... args) const { + template constexpr size_type findLastNotOf(arg_types&&... args) const { return operator std::basic_string_view().find_last_not_of(std::forward(args)...); } JSONIFIER_INLINE void append(const string_base& newSize) { - if (sizeVal + newSize.size() >= capacityVal) { + if (sizeVal + newSize.size() >= capacityVal) [[unlikely]] { reserve(sizeVal + newSize.size()); } - std::memcpy(dataVal + sizeVal, newSize.data(), newSize.size()); - sizeVal += newSize.size(); - allocator::construct(&dataVal[sizeVal], static_cast(0x00)); + if (newSize.size() > 0) [[likely]] { + std::memcpy(dataVal + sizeVal, newSize.data(), newSize.size()); + sizeVal += newSize.size(); + allocator::construct(&dataVal[sizeVal], value_type{}); + } } template JSONIFIER_INLINE void append(value_type_newer* values, uint64_t newSize) { - if (sizeVal + newSize >= capacityVal) { + if (sizeVal + newSize >= capacityVal) [[unlikely]] { resize(sizeVal + newSize); } - if (newSize > 0 && values) { + if (newSize > 0 && values) [[likely]] { std::memcpy(dataVal + sizeVal, values, newSize); sizeVal += newSize; - allocator::construct(&dataVal[sizeVal], static_cast(0x00)); + allocator::construct(&dataVal[sizeVal], value_type{}); } } @@ -310,23 +294,23 @@ namespace jsonifier { int64_t newSize = end - start; auto posNew = where.operator->() - dataVal; - if (newSize <= 0) { + if (newSize <= 0) [[unlikely]] { return; } - if (sizeVal + newSize >= capacityVal) { + if (sizeVal + newSize >= capacityVal) [[unlikely]] { reserve(sizeVal + newSize); } std::memmove(dataVal + posNew + newSize, dataVal + posNew, (sizeVal - posNew) * sizeof(value_type)); std::memcpy(dataVal + posNew, start.operator->(), newSize * sizeof(value_type)); sizeVal += newSize; - allocator::construct(&dataVal[sizeVal], static_cast(0x00)); + allocator::construct(&dataVal[sizeVal], value_type{}); } JSONIFIER_INLINE void insert(iterator values, value_type toInsert) { auto positionNew = values - begin(); - if (sizeVal + 1 >= capacityVal) { + if (sizeVal + 1 >= capacityVal) [[unlikely]] { reserve((sizeVal + 1) * 2); } auto newSize = sizeVal - positionNew; @@ -336,9 +320,9 @@ namespace jsonifier { } JSONIFIER_INLINE void erase(size_type count) { - if (count == 0) { + if (count == 0) [[unlikely]] { return; - } else if (count > sizeVal) { + } else if (count > sizeVal) [[likely]] { count = sizeVal; } traits_type::move(dataVal, dataVal + count, sizeVal - count); @@ -348,9 +332,9 @@ namespace jsonifier { JSONIFIER_INLINE void erase(iterator count) { auto newSize = count - dataVal; - if (newSize == 0) { + if (newSize == 0) [[unlikely]] { return; - } else if (newSize > static_cast(sizeVal)) { + } else if (newSize > static_cast(sizeVal)) [[unlikely]] { newSize = static_cast(sizeVal); } traits_type::move(dataVal, dataVal + newSize, sizeVal - newSize); @@ -359,22 +343,22 @@ namespace jsonifier { } JSONIFIER_INLINE void pushBack(value_type value) { - if (sizeVal + 1 >= capacityVal) { + if (sizeVal + 1 >= capacityVal) [[unlikely]] { reserve((sizeVal + 2) * 4); } allocator::construct(&dataVal[sizeVal++], value); - allocator::construct(&dataVal[sizeVal], static_cast(0x00)); + allocator::construct(&dataVal[sizeVal], value_type{}); } JSONIFIER_INLINE const_reference at(size_type index) const { - if (index >= sizeVal) { + if (index >= sizeVal) [[unlikely]] { throw std::runtime_error{ "Sorry, but that index is beyond the end of this string." }; } return dataVal[index]; } JSONIFIER_INLINE reference at(size_type index) { - if (index >= sizeVal) { + if (index >= sizeVal) [[unlikely]] { throw std::runtime_error{ "Sorry, but that index is beyond the end of this string." }; } return dataVal[index]; @@ -392,18 +376,18 @@ namespace jsonifier { return { dataVal, sizeVal }; } - template JSONIFIER_INLINE explicit operator std::basic_string() const { - std::basic_string returnValue{}; - if (sizeVal > 0) { + template JSONIFIER_INLINE explicit operator jsonifier::string_base() const { + jsonifier::string_base returnValue{}; + if (sizeVal > 0) [[likely]] { returnValue.resize(sizeVal); std::memcpy(returnValue.data(), data(), returnValue.size()); } return returnValue; } - template JSONIFIER_INLINE explicit operator string_base() const { - string_base returnValue{}; - if (sizeVal > 0) { + template JSONIFIER_INLINE explicit operator std::basic_string() const { + std::basic_string returnValue{}; + if (sizeVal > 0) [[likely]] { returnValue.resize(sizeVal); std::memcpy(returnValue.data(), data(), returnValue.size()); } @@ -411,7 +395,7 @@ namespace jsonifier { } virtual JSONIFIER_INLINE void clear() { - if (sizeVal > 0) { + if (sizeVal > 0) [[likely]] { allocator::construct(dataVal, static_cast(0x00u)); } sizeVal = 0; @@ -419,11 +403,11 @@ namespace jsonifier { JSONIFIER_INLINE void resize(size_type newSize) { if (newSize > 0) [[likely]] { - if (newSize > capacityVal) { + if (newSize > capacityVal) [[likely]] { pointer newPtr = allocator::allocate(newSize + 1); try { if (dataVal) [[likely]] { - if (sizeVal > 0) { + if (sizeVal > 0) [[likely]] { std::uninitialized_move(dataVal, dataVal + sizeVal, newPtr); } allocator::deallocate(dataVal, capacityVal + 1); @@ -434,14 +418,14 @@ namespace jsonifier { } capacityVal = newSize; dataVal = newPtr; + std::uninitialized_value_construct(dataVal + sizeVal, dataVal + capacityVal); allocator::construct(newPtr + newSize, value_type{}); sizeVal = newSize; - } else if (newSize > sizeVal) { - std::fill(dataVal + sizeVal, dataVal + newSize, value_type{}); + } else if (newSize > sizeVal) [[likely]] { + std::uninitialized_value_construct(dataVal + sizeVal, dataVal + capacityVal); allocator::construct(dataVal + newSize, value_type{}); sizeVal = newSize; - - } else if (newSize < sizeVal) { + } else if (newSize < sizeVal) [[likely]] { std::destroy(dataVal + newSize, dataVal + sizeVal); allocator::construct(dataVal + newSize, value_type{}); sizeVal = newSize; @@ -457,7 +441,7 @@ namespace jsonifier { pointer newPtr = allocator::allocate(capacityNew + 1); try { if (dataVal) [[likely]] { - if (sizeVal > 0) { + if (sizeVal > 0) [[likely]] { std::uninitialized_move(dataVal, dataVal + sizeVal, newPtr); } allocator::deallocate(dataVal, capacityVal + 1); @@ -468,7 +452,7 @@ namespace jsonifier { } capacityVal = capacityNew; dataVal = newPtr; - allocator::construct(&dataVal[sizeVal], static_cast(0x00)); + allocator::construct(&dataVal[sizeVal], value_type{}); } } @@ -484,28 +468,22 @@ namespace jsonifier { return sizeVal == 0; } - constexpr pointer data() const { + JSONIFIER_INLINE pointer data() const { return dataVal; } - constexpr pointer data() { + JSONIFIER_INLINE pointer data() { return dataVal; } template JSONIFIER_INLINE friend std::enable_if_t, bool> operator==(const string_base& lhs, const value_type_newer& rhs) { auto rhsLength = traits_type::length(rhs); - if (lhs.size() != rhsLength) { - return false; - } - return jsonifier_internal::jsonifier_core_internal::compare(rhs, lhs.data(), rhsLength); + return rhsLength == lhs.size() && jsonifier_internal::jsonifier_core_internal::compare(lhs.data(), rhs, rhsLength); } template JSONIFIER_INLINE friend bool operator==(const string_base& lhs, const value_type_newer& rhs) { - if (rhs.size() != lhs.size()) { - return false; - } - return jsonifier_internal::jsonifier_core_internal::compare(rhs.data(), lhs.data(), rhs.size()); + return rhs.size() == lhs.size() && jsonifier_internal::jsonifier_core_internal::compare(lhs.data(), rhs.data(), rhs.size()); } template JSONIFIER_INLINE void swap(string_base_new&& other) { @@ -594,8 +572,8 @@ namespace jsonifier { pointer dataVal{}; JSONIFIER_INLINE void reset() { - if (dataVal && capacityVal) { - if (sizeVal) { + if (dataVal && capacityVal) [[likely]] { + if (sizeVal) [[likely]] { std::destroy(dataVal, dataVal + sizeVal); sizeVal = 0; } @@ -613,42 +591,3 @@ namespace jsonifier { return os; } }// namespace jsonifier - -namespace jsonifier_internal { - - template class buffer_string : public jsonifier::string_base { - public: - using base = jsonifier::string_base; - using value_type = base::value_type; - using pointer = base::pointer; - using const_pointer = base::const_pointer; - using reference = base::reference; - using const_reference = base::const_reference; - using difference_type = base::difference_type; - using iterator = base::iterator; - using const_iterator = base::const_iterator; - using reverse_iterator = base::reverse_iterator; - using const_reverse_iterator = base::const_reverse_iterator; - using size_type = base::size_type; - using allocator = base::allocator; - using traits_type = base::traits_type; - - JSONIFIER_INLINE buffer_string() { - base::resize(16384); - }; - - JSONIFIER_INLINE void clear() override { - base::sizeVal = 0; - } - }; - - template struct hash> { - JSONIFIER_INLINE uint64_t operator()(const buffer_string& value, uint64_t seed) const { - return fnv1aHash(value, seed); - } - - JSONIFIER_INLINE uint64_t operator()(const buffer_string& value, uint64_t seed) const { - return fnv1aHash(value, seed); - } - }; -} \ No newline at end of file diff --git a/Include/jsonifier/StringUtils.hpp b/Include/jsonifier/StringUtils.hpp index 28fbc93c6..befe28ebf 100644 --- a/Include/jsonifier/StringUtils.hpp +++ b/Include/jsonifier/StringUtils.hpp @@ -21,7 +21,7 @@ */ /// https://github.com/RealTimeChris/jsonifier /// Feb 3, 2023 -/// A lot of the code in this header was sampled from simdjson - https://github.com/simdjson +/// Most of the code in this header was sampled from simdjson - https://github.com/simdjson #pragma once #include @@ -31,210 +31,204 @@ namespace jsonifier_internal { - template class backslash_and_quote; - - template<> class backslash_and_quote { - public: - template JSONIFIER_INLINE static string_parsing_type copyAndFind(const char_type01* source, char_type02* dest) { - simd_int_t values(gatherValuesU(source)); - storeu(values, dest); - return static_cast(simd_base::cmpeq(values, simd_base::backslashes) | simd_base::cmpeq(values, simd_base::quotes)); - } - }; - - template<> class backslash_and_quote { - public: - template JSONIFIER_INLINE static uint16_t copyAndFind(const char_type01* source, char_type02* dest) { - simd_int_128 values(gatherValuesU(source)); - storeu(values, dest); - return static_cast(simd_base::cmpeq(values, backslashes128) | simd_base::cmpeq(values, quotes128)); - } - - protected: - static constexpr simd_int_128 backslashes128{ simdFromValue(0x5Cu) }; - static constexpr simd_int_128 quotes128{ simdFromValue(0x22u) }; - }; - - template class escapeable; - - template<> class escapeable { - public: - template JSONIFIER_INLINE static string_parsing_type copyAndFind(const char_type01* source, char_type02* dest) { - simd_int_t values(gatherValuesU(source)); - storeu(values, dest); - return static_cast( - simd_base::cmpeq(simd_base::opShuffle(escapeableChars01, values), values) | simd_base::cmpeq(simd_base::opShuffle(escapeableChars03, values), values)); - } - - protected: - static constexpr uint8_t escapeableChars00[]{ 0x00u, 0x00u, 0x22u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x08u, 0x00u, 0x00u, 0x00u, 0x0Cu, 0x0Du, 0x00u, 0x00u }; - static constexpr uint8_t escapeableChars02[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x09u, 0x0Au, 0x00u, 0x5Cu, 0x00u, 0x00u, 0x00u }; - static constexpr simd_int_t escapeableChars01{ simdFromTable(escapeableChars00) }; - static constexpr simd_int_t escapeableChars03{ simdFromTable(escapeableChars02) }; - }; - - template<> class escapeable { - public: - template JSONIFIER_INLINE static uint16_t copyAndFind(const char_type01* source, char_type02* dest) { - simd_int_128 values(gatherValuesU(source)); - storeu(values, dest); - return static_cast( - simd_base::cmpeq(simd_base::opShuffle(escapeableChars01, values), values) | simd_base::cmpeq(simd_base::opShuffle(escapeableChars03, values), values)); - } - - protected: - static constexpr uint8_t escapeableChars00[]{ 0x00u, 0x00u, 0x22u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x08u, 0x00u, 0x00u, 0x00u, 0x0Cu, 0x0Du, 0x00u, 0x00u }; - static constexpr uint8_t escapeableChars02[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x09u, 0x0Au, 0x00u, 0x5Cu, 0x00u, 0x00u, 0x00u }; - static constexpr simd_int_128 escapeableChars01{ simdFromTable(escapeableChars00) }; - static constexpr simd_int_128 escapeableChars03{ simdFromTable(escapeableChars02) }; - }; - - template JSONIFIER_INLINE uint32_t hexToU32NoCheck(const char_type* source) { - uint32_t v1 = digitToVal32[630 + source[0]]; - uint32_t v2 = digitToVal32[420 + source[1]]; - uint32_t v3 = digitToVal32[210 + source[2]]; - uint32_t v4 = digitToVal32[0 + source[3]]; + template JSONIFIER_INLINE static uint32_t hexToU32NoCheck(const value_type* string1) { + uint32_t v1 = digitToVal32[630 + string1[0]]; + uint32_t v2 = digitToVal32[420 + string1[1]]; + uint32_t v3 = digitToVal32[210 + string1[2]]; + uint32_t v4 = digitToVal32[0 + string1[3]]; return v1 | v2 | v3 | v4; } - template JSONIFIER_INLINE uint32_t codePointToUtf8(uint32_t codePoint, char_type* c) { + template JSONIFIER_INLINE static uint32_t codePointToUtf8(uint32_t codePoint, value_type* c) { if (codePoint <= 0x7F) { - c[0] = static_cast(codePoint); + c[0] = value_type(codePoint); return 1; } - uint32_t leadingZeros = lzcnt(codePoint); + uint32_t leading_zeros = lzcnt(codePoint); - if (leadingZeros >= 11) { - uint32_t pattern = pdep(0x3F00u, codePoint); + if (leading_zeros >= 11) { + uint32_t pattern = pdep(0x3F00U, codePoint); pattern |= 0xC0ull; - c[0] = static_cast(pattern >> 8); - c[1] = static_cast(pattern & 0xFFu); + c[0] = static_cast(pattern >> 8); + c[1] = static_cast(pattern & 0xFFu); return 2; - } else if (leadingZeros >= 16) { - uint32_t pattern = pdep(0x0F0800u, codePoint); + } else if (leading_zeros >= 16) { + uint32_t pattern = pdep(0x0F0800U, codePoint); pattern |= 0xE0ull; - c[0] = static_cast(pattern >> 16); - c[1] = static_cast(pattern >> 8); - c[2] = static_cast(pattern & 0xFFu); + c[0] = static_cast(pattern >> 16); + c[1] = static_cast(pattern >> 8); + c[2] = static_cast(pattern & 0xFFu); return 3; - } else if (leadingZeros >= 21) { - uint32_t pattern = pdep(0x01020400u, codePoint); + } else if (leading_zeros >= 21) { + uint32_t pattern = pdep(0x01020400U, codePoint); pattern |= 0xF0ull; - c[0] = static_cast(pattern >> 24); - c[1] = static_cast(pattern >> 16); - c[2] = static_cast(pattern >> 8); - c[3] = static_cast(pattern & 0xFFu); + c[0] = static_cast(pattern >> 24); + c[1] = static_cast(pattern >> 16); + c[2] = static_cast(pattern >> 8); + c[3] = static_cast(pattern & 0xFFu); return 4; } return 0; } - template JSONIFIER_INLINE bool handleUnicodeCodePoint(char_type01* srcPtr, char_type02* dstPtr) { - uint32_t codePoint = hexToU32NoCheck(*srcPtr + 2); + template JSONIFIER_INLINE bool handleUnicodeCodePoint(value_type01* srcPtr, value_type02* dstPtr) { + static constexpr uint32_t subCodePoint = 0xfffd; + uint32_t codePoint = hexToU32NoCheck(*srcPtr + 2); *srcPtr += 6; - if (codePoint >= 0xD800 && codePoint < 0xDC00) { - char_type01 srcData = *srcPtr; - if (((srcData[0] << 8) | srcData[1]) != ((static_cast>(0x5Cu) << 8) | static_cast>(0x75u))) { - codePoint = 0xFFFD; + if (codePoint >= 0xd800 && codePoint < 0xdc00) { + value_type01 srcData = *srcPtr; + if (((srcData[0] << 8) | srcData[1]) != ((static_cast>(0x5Cu) << 8) | static_cast>(0x75u))) { + codePoint = subCodePoint; } else { uint32_t codePoint02 = hexToU32NoCheck(srcData + 2); - uint32_t lowBit = codePoint02 - 0xDC00; + uint32_t lowBit = codePoint02 - 0xdc00; if (lowBit >> 10) { - codePoint = 0xFFFD; + codePoint = subCodePoint; } else { - codePoint = (((codePoint - 0xD800) << 10) | lowBit) + 0x10000; + codePoint = (((codePoint - 0xd800) << 10) | lowBit) + 0x10000; *srcPtr += 6; } } - } else if (codePoint >= 0xdc00 && codePoint <= 0xdFFF) { - codePoint = 0xFFFD; + } else if (codePoint >= 0xdc00 && codePoint <= 0xdfff) { + codePoint = subCodePoint; } - uint64_t offset = codePointToUtf8(codePoint, *dstPtr); + size_t offset = codePointToUtf8(codePoint, *dstPtr); *dstPtr += offset; return offset > 0; } - template constexpr uint64_t getStringLength() { - return shortStringsSupport ? 16 : BytesPerStep; + template constexpr value_type hasZero(value_type chunk) noexcept { + return static_cast((((chunk - static_cast(0x0101010101010101)) & ~chunk) & static_cast(0x8080808080808080))); } - template - JSONIFIER_INLINE char_type02* parseString(const char_type01* source, char_type02* dest, uint64_t lengthNew) { - while (static_cast(lengthNew) >= static_cast(0)) { - string_parsing_type nextBackslashOrQuote = backslash_and_quote::copyAndFind(source, dest); - if (nextBackslashOrQuote != 0) { - nextBackslashOrQuote = tzcnt(nextBackslashOrQuote); - auto escapeChar = source[nextBackslashOrQuote]; - if (escapeChar == 0x22u) { - return dest + nextBackslashOrQuote; + template constexpr value_type hasQuote(value_type chunk) noexcept { + return static_cast(hasZero(chunk ^ static_cast(0b0010001000100010001000100010001000100010001000100010001000100010))); + } + + template constexpr value_type hasEscape(value_type chunk) noexcept { + return static_cast(hasZero(chunk ^ static_cast(0b0101110001011100010111000101110001011100010111000101110001011100))); + } + + template constexpr value_type isLess16(value_type c) noexcept { + return static_cast(hasZero(c & static_cast(0b1111000011110000111100001111000011110000111100001111000011110000))); + } + + template + JSONIFIER_INLINE static integer_type copyAndFindParse(char_type01* string1, char_type02* string2) { + const simd_type values{ gatherValuesU(string1) }; + std::memcpy(string2, string1, sizeof(simd_type)); + return tzcnt(static_cast(simd_base::cmpeq(values, backslashes) | simd_base::cmpeq(values, quotes))); + } + + template + JSONIFIER_INLINE static integer_type copyAndFindParse(char_type01* string1, char_type02* string2) { + integer_type newValue{}; + std::memcpy(string2, string1, sizeof(simd_type)); + std::memcpy(&newValue, string1, sizeof(simd_type)); + return static_cast(tzcnt(static_cast(hasQuote(newValue) | hasEscape(newValue))) >> 3u); + } + + template + JSONIFIER_INLINE static integer_type copyAndFindSerialize(char_type01* string1, char_type02* string2) { + const simd_type values{ gatherValuesU(string1) }; + std::memcpy(string2, string1, sizeof(simd_type)); + return tzcnt(static_cast(simd_base::cmpeq(simd_base::opShuffle(escapeableTable00, values), values) | + simd_base::cmpeq(simd_base::opShuffle(escapeableTable01, values), values))); + } + + template + JSONIFIER_INLINE static integer_type copyAndFindSerialize(char_type01* string1, char_type02* string2) { + integer_type newValue{}; + std::memcpy(string2, string1, sizeof(integer_type)); + std::memcpy(&newValue, string1, sizeof(integer_type)); + return static_cast(tzcnt(static_cast(hasQuote(newValue) | hasEscape(newValue) | isLess16(newValue))) >> 3u); + } + + template + JSONIFIER_INLINE char_type02* parseString(const char_type01* string1, char_type02* string2, uint64_t lengthNew) { + using simd_type = typename jsonifier::concepts::get_type_at_index::type::type; + using integer_type = typename jsonifier::concepts::get_type_at_index::type::integer_type; + static constexpr uint64_t bytesProcessed = jsonifier::concepts::get_type_at_index::type::bytesProcessed; + static constexpr integer_type mask = jsonifier::concepts::get_type_at_index::type::mask; + while (static_cast(lengthNew) > 0) { + if constexpr (index < avx_integer_list::size - 1) { + if (lengthNew < bytesProcessed / 2) { + return parseString(string1, string2, lengthNew); } - escapeChar = source[nextBackslashOrQuote + 1]; - if (escapeChar == 0x75u) { - source += nextBackslashOrQuote; - dest += nextBackslashOrQuote; - handleUnicodeCodePoint(&source, &dest); - } else { - char_type01 escapeResult = escapeMap[escapeChar]; - if (escapeResult == 0u) { + } + integer_type nextBackslashOrQuote = copyAndFindParse(string1, string2); + if (nextBackslashOrQuote != mask) { + auto escapeChar = string1[nextBackslashOrQuote]; + if (escapeChar == 0x22u) { + return string2 + nextBackslashOrQuote; + } else if (escapeChar == 0x5Cu) { + escapeChar = string1[nextBackslashOrQuote + 1]; + if (escapeChar == 0x75u) { + lengthNew -= nextBackslashOrQuote; + string1 += nextBackslashOrQuote; + string2 += nextBackslashOrQuote; + if (!handleUnicodeCodePoint(&string1, &string2)) { + return nullptr; + } + continue; + } + escapeChar = escapeMap[escapeChar]; + if (escapeChar == 0u) { return static_cast(nullptr); } - dest[nextBackslashOrQuote] = escapeResult; - dest += nextBackslashOrQuote + 1ull; - source += nextBackslashOrQuote + 2ull; + string2[nextBackslashOrQuote] = escapeChar; lengthNew -= nextBackslashOrQuote + 2ull; + string2 += nextBackslashOrQuote + 1ull; + string1 += nextBackslashOrQuote + 2ull; } } else { - dest += getStringLength(); - source += getStringLength(); - lengthNew -= getStringLength(); + lengthNew -= bytesProcessed; + string2 += bytesProcessed; + string1 += bytesProcessed; } } - return static_cast(nullptr); + return string2; } - template - JSONIFIER_INLINE char_type01* serializeString(char_type01* source, char_type02* dest, uint64_t lengthNew, uint64_t& indexNew) { -#if JSONIFIER_CHECK_FOR_INSTRUCTION(JSONIFIER_ANY_AVX) - auto serializationLambda = [&](char_type01* source, char_type02*& dest, uint64_t remainingLength, auto&& comparitor) -> char_type01* { - while (comparitor(static_cast(lengthNew), static_cast(remainingLength))) { - string_parsing_type nextEscapeable = escapeable::copyAndFind(source, dest); - if (nextEscapeable != 0) { - nextEscapeable = tzcnt(nextEscapeable); - char_type01 escapeResult = static_cast(escapeableChars[static_cast(source[nextEscapeable])]); - if (escapeResult == 0u) { - lengthNew -= nextEscapeable; - indexNew += nextEscapeable; - source += nextEscapeable; - dest += nextEscapeable; - return source; - } - dest[nextEscapeable] = 0x5Cu; - dest[static_cast(nextEscapeable) + 1ull] = static_cast(escapeResult); - dest += static_cast(nextEscapeable) + 2ull; - indexNew += static_cast(nextEscapeable) + 2ull; - lengthNew -= (nextEscapeable + 1ull); - source += nextEscapeable + 1ull; - } else { - lengthNew -= remainingLength > 0 ? remainingLength : 1; - indexNew += remainingLength > 0 ? remainingLength : 1; - source += remainingLength > 0 ? remainingLength : 1; - dest += remainingLength > 0 ? remainingLength : 1; + template + JSONIFIER_INLINE void serializeString(const char_type01* string1, char_type02* string2, uint64_t lengthNew, uint64_t& indexNew) { + using simd_type = typename jsonifier::concepts::get_type_at_index::type::type; + using integer_type = typename jsonifier::concepts::get_type_at_index::type::integer_type; + static constexpr uint64_t bytesProcessed = jsonifier::concepts::get_type_at_index::type::bytesProcessed; + static constexpr integer_type mask = jsonifier::concepts::get_type_at_index::type::mask; + while (static_cast(lengthNew) > 0) { + if constexpr (index < avx_integer_list::size - 1) { + if (lengthNew < bytesProcessed / 2) { + return serializeString(string1, string2, lengthNew, indexNew); } } - return source; - }; - - source = serializationLambda(source, dest, getStringLength(), std::greater_equal{}); - std::remove_const_t newValues[getStringLength()]{}; - std::memcpy(newValues, source, lengthNew); - return serializationLambda(newValues, dest, 0, std::greater{}); -#else - return source; -#endif + integer_type nextEscapeable = copyAndFindSerialize(string1, string2); + if (nextEscapeable != mask) { + auto escapeResult = escapeTable[string1[nextEscapeable]]; + if (escapeResult == 0u) { + indexNew += nextEscapeable; + return; + } + lengthNew -= nextEscapeable; + indexNew += nextEscapeable; + string1 += nextEscapeable; + string2 += nextEscapeable; + std::memcpy(string2, &escapeResult, 2); + indexNew += 2ULL; + string2 += 2ULL; + --lengthNew; + ++string1; + } else { + lengthNew -= bytesProcessed; + indexNew += bytesProcessed; + string1 += bytesProcessed; + string2 += bytesProcessed; + } + } } - template JSONIFIER_INLINE bool parseBool(char_type* json) { - char_type values[5]{ "true" }; - return std::memcmp(values, json, 4) == 0; + JSONIFIER_INLINE bool parseBool(string_view_ptr json) { + uint8_t valueNew[5]{ "true" }; + return std::memcmp(valueNew, json, 4) == 0; } -}// namespace jsonifier_internal +}// namespace jsonifier_internal \ No newline at end of file diff --git a/Include/jsonifier/StringView.hpp b/Include/jsonifier/StringView.hpp index e6ac6b649..dfd6e4991 100644 --- a/Include/jsonifier/StringView.hpp +++ b/Include/jsonifier/StringView.hpp @@ -120,7 +120,7 @@ namespace jsonifier { } constexpr const_reference at(const size_type offsetNew) const { - if (offsetNew >= sizeVal) { + if (offsetNew >= sizeVal) [[unlikely]] { throw std::out_of_range{ "Sorry, but that index is beyond the end of this string_view instance." }; } return dataVal[offsetNew]; @@ -138,30 +138,8 @@ namespace jsonifier { return dataVal[sizeVal - 1]; } - JSONIFIER_INLINE size_type find(const_pointer args, size_type position = 0) const { - auto newSize = traits_type::length(args); - if (position + newSize > sizeVal) { - return npos; - } - auto foundValue = jsonifier_internal::find(dataVal + position, sizeVal - position, args, newSize); - return foundValue == npos ? npos : foundValue + position; - } - - template JSONIFIER_INLINE size_type find(value_type_newer args, size_type position = 0) const { - value_type newValue{ static_cast(args) }; - if (position + 1 > sizeVal) { - return npos; - } - auto foundValue = jsonifier_internal::find(dataVal + position, sizeVal - position, &newValue, 1); - return foundValue == npos ? npos : foundValue + position; - } - - template JSONIFIER_INLINE size_type find(const value_type_newer& args, size_type position = 0) const { - if (position + args.size() > sizeVal) { - return npos; - } - auto foundValue = jsonifier_internal::find(dataVal + position, sizeVal - position, args.data(), args.size()); - return foundValue == npos ? npos : foundValue + position; + template constexpr size_type find(arg_types&&... args) const { + return operator std::basic_string_view().find(std::forward(args)...); } template constexpr size_type findFirstOf(arg_types&&... args) const { @@ -187,7 +165,7 @@ namespace jsonifier { } constexpr string_view_base substr(const size_type offsetNew = 0, size_type countNew = npos) const { - if (offsetNew >= sizeVal) { + if (offsetNew >= sizeVal) [[unlikely]] { throw std::out_of_range("Substring position is out of range."); } @@ -195,19 +173,19 @@ namespace jsonifier { return string_view_base(dataVal + offsetNew, countNew); } - template JSONIFIER_INLINE explicit operator std::basic_string() const { - std::basic_string returnValue{}; + template constexpr explicit operator jsonifier::string_base() const { + jsonifier::string_base returnValue{}; returnValue.resize(sizeVal); - if (sizeVal > 0) { + if (sizeVal > 0) [[likely]] { std::memcpy(returnValue.data(), data(), returnValue.size()); } return returnValue; } - template JSONIFIER_INLINE explicit operator string_base() const { - string_base returnValue{}; + template constexpr explicit operator std::basic_string() const { + std::basic_string returnValue{}; returnValue.resize(sizeVal); - if (sizeVal > 0) { + if (sizeVal > 0) [[likely]] { std::memcpy(returnValue.data(), data(), returnValue.size()); } return returnValue; @@ -218,80 +196,73 @@ namespace jsonifier { } template - JSONIFIER_INLINE friend std::enable_if_t, bool> operator==(const string_view_base& lhs, const value_type_newer& rhs) { + constexpr friend std::enable_if_t, bool> operator==(const string_view_base& lhs, const value_type_newer& rhs) { auto rhsLength = traits_type::length(rhs); - if (lhs.size() != rhsLength) { - return false; - } - return jsonifier_internal::jsonifier_core_internal::compare(rhs, lhs.data(), rhsLength); + return rhsLength == lhs.size() && jsonifier_internal::jsonifier_core_internal::compare(lhs.data(), rhs, rhsLength); } - template JSONIFIER_INLINE friend bool operator==(const string_view_base& lhs, const value_type_newer& rhs) { - if (rhs.size() != lhs.size()) { - return false; - } - return jsonifier_internal::jsonifier_core_internal::compare(rhs.data(), lhs.data(), rhs.size()); + template constexpr friend bool operator==(const string_view_base& lhs, const value_type_newer& rhs) { + return rhs.size() == lhs.size() && jsonifier_internal::jsonifier_core_internal::compare(lhs.data(), rhs.data(), rhs.size()); } template - JSONIFIER_INLINE friend string_base operator+(const value_type_newer (&lhs)[size], const string_view_base& rhs) { + constexpr friend string_base operator+(const value_type_newer (&lhs)[size], const string_view_base& rhs) { string_base newLhs{ lhs }; newLhs += rhs; return newLhs; } template - JSONIFIER_INLINE friend string_base operator+=(const value_type_newer (&lhs)[size], const string_view_base& rhs) { + constexpr friend string_base operator+=(const value_type_newer (&lhs)[size], const string_view_base& rhs) { string_base newLhs{ lhs }; newLhs += rhs; return newLhs; } - template - JSONIFIER_INLINE friend string_base operator+(string_type_newer&& lhs, const string_view_base& rhs) { + template constexpr friend string_base operator+(string_type_newer&& lhs, const string_view_base& rhs) { string_base> newLhs{ lhs }; newLhs += rhs; return newLhs; } template - JSONIFIER_INLINE friend string_base operator+=(string_type_newer&& lhs, const string_view_base& rhs) { + constexpr friend string_base operator+=(string_type_newer&& lhs, const string_view_base& rhs) { string_base> newLhs{ lhs }; newLhs += rhs; return newLhs; } - JSONIFIER_INLINE string_base operator+(const value_type& rhs) { + constexpr string_base operator+(const value_type& rhs) { string_base newLhs{ *this }; newLhs.pushBack(rhs); return newLhs; } - JSONIFIER_INLINE string_base operator+=(const value_type& rhs) { + constexpr string_base operator+=(const value_type& rhs) { string_base newLhs{ *this }; newLhs.pushBack(rhs); return newLhs; } - template JSONIFIER_INLINE string_base operator+(const string_type_new& rhs) const { + template constexpr string_base operator+(const string_type_new& rhs) const { string_base newLhs{ *this }; newLhs += rhs; return newLhs; } - template JSONIFIER_INLINE string_base operator+=(const string_type_new& rhs) { + template constexpr string_base operator+=(const string_type_new& rhs) { string_base newLhs{ *this }; newLhs.append(rhs.data(), rhs.size()); return newLhs; } - template JSONIFIER_INLINE string_base operator+(const value_type_newer (&rhs)[size]) const { + template constexpr string_base operator+(const value_type_newer (&rhs)[size]) const { string_base newLhs{ *this }; newLhs += rhs; return newLhs; } - template JSONIFIER_INLINE string_base operator+=(const value_type_newer (&rhs)[size]) { + template constexpr string_base operator+=(const value_type_newer (&rhs)[size]) { string_base newLhs{ *this }; newLhs += rhs; return newLhs; @@ -305,7 +276,7 @@ namespace jsonifier { using string_view = string_view_base; JSONIFIER_INLINE std::ostream& operator<<(std::ostream& oStream, const jsonifier::string_view_base& string) { - oStream << string.operator jsonifier::string(); + oStream << string.operator jsonifier::string_base(); return oStream; } @@ -314,21 +285,12 @@ namespace jsonifier { namespace jsonifier_internal { template struct hash> { - constexpr uint64_t operator()(jsonifier::string_view_base value, uint64_t seed) const { + constexpr uint64_t operator()(const jsonifier::string_view_base& value, uint32_t seed) const { return fnv1aHash(value, seed); } - constexpr uint64_t operator()(jsonifier::string_view_base value, uint64_t seed) const { + constexpr uint64_t operator()(const jsonifier::string_view_base& value, uint32_t seed) const { return fnv1aHash(value, seed); } }; } - -namespace std { - - template<> struct hash { - JSONIFIER_INLINE size_t operator()(jsonifier ::string_view lhs) const { - return jsonifier_internal::fnv1aHash(lhs); - } - }; -} diff --git a/Include/jsonifier/Tables.hpp b/Include/jsonifier/Tables.hpp index 30e34ccfb..2f900f824 100644 --- a/Include/jsonifier/Tables.hpp +++ b/Include/jsonifier/Tables.hpp @@ -44,14 +44,7 @@ namespace jsonifier_internal { 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x20u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u }; - constexpr bool structuralTable[]{ false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, true, - true, false, false, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, - false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, true, false, false, - false, false, false, false, false, false, true, false, false, false, false, false, false, false, true, false, false, false, false, false, true, false, false, false, false, - false, false, true, false, true, false, false }; - - constexpr int16_t asciiToValueTable[]{ -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, + constexpr int8_t asciiToValueTable[]{ -48, -47, -46, -45, -44, -43, -42, -41, -40, -39, -38, -37, -36, -35, -34, -33, -32, -31, -30, -29, -28, -27, -26, -25, -24, -23, -22, -21, -20, -19, -18, -17, -16, -15, -14, -13, -12, -11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79 }; @@ -63,20 +56,6 @@ namespace jsonifier_internal { true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false }; - constexpr uint8_t escapeMap[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x08u, 0x09u, 0x0Au, 0x00u, 0x0Cu, 0x0Du, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x22u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x2fu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x5cu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x08u, 0x00u, 0x00u, 0x00u, 0x0cu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x0au, 0x00u, 0x00u, 0x00u, 0x0du, 0x00u, - 0x09u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u }; - - constexpr uint8_t escapeableChars[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x62u, 0x74u, 0x6Eu, 0x00u, 0x66u, 0x72u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x22u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x5Cu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, - 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u }; - constexpr uint8_t charTable[]{ 0x30u, 0x30u, 0x30u, 0x31u, 0x30u, 0x32u, 0x30u, 0x33u, 0x30u, 0x34u, 0x30u, 0x35u, 0x30u, 0x36u, 0x30u, 0x37u, 0x30u, 0x38u, 0x30u, 0x39u, 0x31u, 0x30u, 0x31u, 0x31u, 0x31u, 0x32u, 0x31u, 0x33u, 0x31u, 0x34u, 0x31u, 0x35u, 0x31u, 0x36u, 0x31u, 0x37u, 0x31u, 0x38u, 0x31u, 0x39u, 0x32u, 0x30u, 0x32u, 0x31u, 0x32u, 0x32u, 0x32u, 0x33u, 0x32u, 0x34u, 0x32u, 0x35u, 0x32u, 0x36u, 0x32u, 0x37u, 0x32u, 0x38u, 0x32u, 0x39u, 0x33u, 0x30u, 0x33u, 0x31u, 0x33u, 0x32u, 0x33u, 0x33u, @@ -87,6 +66,33 @@ namespace jsonifier_internal { 0x38u, 0x32u, 0x38u, 0x33u, 0x38u, 0x34u, 0x38u, 0x35u, 0x38u, 0x36u, 0x38u, 0x37u, 0x38u, 0x38u, 0x38u, 0x39u, 0x39u, 0x30u, 0x39u, 0x31u, 0x39u, 0x32u, 0x39u, 0x33u, 0x39u, 0x34u, 0x39u, 0x35u, 0x39u, 0x36u, 0x39u, 0x37u, 0x39u, 0x38u, 0x39u, 0x39u }; + constexpr uint8_t escapeMap[]{ 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x22u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x2fu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x5Cu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x08u, 0x00u, 0x00u, 0x00u, 0x0Cu, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x0Au, 0x00u, 0x00u, 0x00u, 0x0Du, 0x00u, + 0x09u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, + 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u, 0x00u }; + + constexpr uint16_t escapeTable[]{ 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x625Cu, 0x745Cu, 0x6E5Cu, 0x0000u, 0x665C, 0x725Cu, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x225Cu, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x5C5Cu, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, + 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u, 0x0000u }; + constexpr uint32_t digitToVal32[]{ 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, 0xFFFFFFFFu, diff --git a/Include/jsonifier/Tuple.hpp b/Include/jsonifier/Tuple.hpp index a3a9beed5..3fc0125db 100644 --- a/Include/jsonifier/Tuple.hpp +++ b/Include/jsonifier/Tuple.hpp @@ -35,7 +35,7 @@ namespace jsonifier_internal { } protected: - template static constexpr auto shrinkIndexArray(auto& valuesNew01, std::index_sequence) { + template static constexpr auto shrinkIndexArray(const array_type& valuesNew01, std::index_sequence) { std::array res{}; ((res[indices] = valuesNew01[indices]), ...); return res; @@ -44,38 +44,46 @@ namespace jsonifier_internal { static constexpr auto filter() { constexpr auto n = std::tuple_size_v; std::array indices{}; - size_t x = 0; - forEach([&](auto index) { + size_t x = 0; + auto filterImpl = [&](auto index, auto&& filterImpl) { using value_type = jsonifier::concepts::unwrap>; if constexpr (!std::convertible_to) { indices[x++] = index - 1; } - }); + if constexpr (index < n - 1) { + filterImpl(std::integral_constant{}, filterImpl); + } + }; + filterImpl(std::integral_constant{}, filterImpl); return std::make_pair(indices, x); } - template static constexpr void groupSizesHelper(auto& diffs, auto& indices, std::index_sequence) { + template + static constexpr void groupSizesImpl(array_type01& diffs, array_type02& indices, std::index_sequence) { ((diffs[indicesNew] = indices[indicesNew + 1] - indices[indicesNew]), ...); } template static constexpr auto groupSizes(const std::array& indices, size_t nTotal) { std::array diffs; - groupSizesHelper(diffs, indices, std::make_index_sequence{}); + groupSizesImpl(diffs, indices, std::make_index_sequence{}); diffs[nGroups - 1] = nTotal - indices[nGroups - 1]; return diffs; } + template static constexpr auto getElemImpl(const value_type& t) { + if constexpr (value == 0 || std::convertible_to) { + return jsonifier::string_view(std::get(t)); + } else { + return std::get(t); + } + } + + template static constexpr auto getElem(const value_type& t) { + return getElemImpl(t); + } + template static constexpr auto makeGroup(const tuple_t& t, std::index_sequence) { - auto getElem = [&](auto x) { - constexpr auto value = decltype(x)::value; - using type = decltype(std::get(t)); - if constexpr (value == 0 || std::convertible_to) { - return jsonifier::string_view(std::get(t)); - } else { - return std::get(t); - } - }; - return std::make_tuple(getElem(std::integral_constant{})...); + return std::make_tuple(getElem(t)...); } template static constexpr auto makeGroupsImpl(tuple_t&& object, std::index_sequence) { @@ -84,7 +92,7 @@ namespace jsonifier_internal { makeGroup()]>(newTuple, std::make_index_sequence()]>{})...); } - static constexpr auto makeGroupsHelper() { + static constexpr auto makeGroupsImpl() { constexpr auto nNew = std::tuple_size_v; constexpr auto filtered = filter(); constexpr auto startsNew = shrinkIndexArray(filtered.first, std::make_index_sequence{}); @@ -92,10 +100,28 @@ namespace jsonifier_internal { return std::make_tuple(startsNew, sizesNew); } - static constexpr auto h = makeGroupsHelper(); + static constexpr auto h = makeGroupsImpl(); static constexpr auto starts = get<0>(h); static constexpr auto sizes = get<1>(h); static constexpr auto nGroups = starts.size(); }; + template constexpr decltype(auto) convSv(value_type&& value) noexcept { + if constexpr (std::is_convertible_v) { + return jsonifier::string_view{ value }; + } else { + return std::forward(value); + } + } + + template JSONIFIER_INLINE decltype(auto) getMember(value_type01&& value, value_type02& member_ptr) { + if constexpr (std::is_member_object_pointer_v) { + return value.*member_ptr; + } else if constexpr (std::is_pointer_v) { + return *member_ptr; + } else { + return member_ptr; + } + } + } \ No newline at end of file diff --git a/Include/jsonifier/TypeEntities.hpp b/Include/jsonifier/TypeEntities.hpp index bcb661128..10325b10e 100644 --- a/Include/jsonifier/TypeEntities.hpp +++ b/Include/jsonifier/TypeEntities.hpp @@ -30,37 +30,33 @@ #include #include +namespace jsonifier_internal { + + template class parser; +} + namespace jsonifier { class raw_json_data; - template class vector; + template class vector; template struct core {}; -} - -namespace jsonifier_internal { - - template class parser; - - template struct array { + template struct value { value_type parseValue; }; - template struct object { + template struct scalar_value { value_type parseValue; }; -} - -namespace jsonifier { namespace concepts { // from // https://stackoverflow.com/questions/16337610/how-to-know-if-a-type-is-a-specialization-of-stdvector template class> constexpr bool is_specialization_v = false; - template class T, class... Args> constexpr bool is_specialization_v, T> = true; + template class value_type, class... Args> constexpr bool is_specialization_v, value_type> = true; template using tag = std::integral_constant; @@ -118,9 +114,6 @@ namespace jsonifier { template concept stateless = std::is_empty_v>; - template - concept is_parser = is_specialization_v>, jsonifier_internal::parser>; - template concept void_t = std::is_void_v>; @@ -144,32 +137,34 @@ namespace jsonifier { concept unsigned_t = std::unsigned_integral> && !bool_t; template - concept unsigned_int16_t = unsigned_t && sizeof(value_type) == 2; + concept uint8_type = unsigned_t && sizeof(value_type) == 1; + + template + concept uint16_type = unsigned_t && sizeof(value_type) == 2; template - concept unsigned_int32_t = unsigned_t && sizeof(value_type) == 4; + concept uint32_type = unsigned_t && sizeof(value_type) == 4; template - concept unsigned_int64_t = unsigned_t && sizeof(value_type) == 8; + concept uint64_type = unsigned_t && sizeof(value_type) == 8; template - concept signed_int16_t = signed_t && sizeof(value_type) == 2; + concept int16_type = signed_t && sizeof(value_type) == 2; template - concept signed_int32_t = signed_t && sizeof(value_type) == 4; + concept int32_type = signed_t && sizeof(value_type) == 4; template - concept signed_int64_t = signed_t && sizeof(value_type) == 8; + concept int64_type = signed_t && sizeof(value_type) == 8; template concept float_t = std::floating_point>; template - concept char_t = std::same_as, char> || std::same_as, wchar_t> || std::same_as, char8_t> || - std::same_as, char16_t> || std::same_as, char32_t>; + concept char_type = std::same_as, char>; template - concept num_t = ( float_t || unsigned_t || signed_t )&&!char_t; + concept num_t = ( float_t || unsigned_t || signed_t )&&!char_type; template concept has_substr = requires(value_type value) { @@ -197,7 +192,7 @@ namespace jsonifier { }; template - concept copyable = std::copy_constructible; + concept copyable = std::copy_constructible>; template concept unique_ptr_t = requires(value_type value) { @@ -209,7 +204,7 @@ namespace jsonifier { concept shared_ptr_t = requires(value_type value) { typename unwrap::element_type; typename unwrap::deleter_type; - } && has_release && std::copy_constructible>; + } && has_release && copyable; template concept has_find = requires(value_type value) { @@ -231,9 +226,6 @@ namespace jsonifier { { *value }; }; - template - concept same_as = std::convertible_to, unwrap> || std::same_as, unwrap>; - template concept null_t = nullable_t || always_null_t; @@ -266,19 +258,19 @@ namespace jsonifier { template using core_wrapper_t = unwrap)>; template - concept jsonifier_array_t = jsonifier_t && is_specialization_v, jsonifier_internal::array>; + concept jsonifier_scalar_value_t = jsonifier_t && is_specialization_v, scalar_value>; template - concept jsonifier_object_t = jsonifier_t && is_specialization_v, jsonifier_internal::object>; + concept jsonifier_value_t = jsonifier_t && is_specialization_v, value>; template concept enum_t = std::is_enum_v>; template - concept vector_t = ( !map_t && vector_subscriptable && has_data )&&!jsonifier_array_t && !has_substr; + concept vector_t = ( !map_t && vector_subscriptable && has_data )&&!jsonifier_value_t && !has_substr; template - concept raw_array_t = std::is_array_v; + concept raw_array_t = std::is_array_v> || std::is_pointer_v>; template concept buffer_like = vector_subscriptable && has_data && has_resize; @@ -290,14 +282,40 @@ namespace jsonifier { concept time_type = is_specialization_v>, std::chrono::duration>; template - concept uint8_type = std::same_as, uint8_t>; - - template - concept char_type = uint8_type || char_t; + concept char_t = uint8_type || char_type; template concept integer_t = std::integral> && !bool_t; + template struct type_holder { + static constexpr uint64_t bytesProcessed{ bytesProcessedNew }; + static constexpr integer_type_new mask{ maskNew }; + using type = simd_type; + using integer_type = integer_type_new; + }; + + template struct type_list; + + template struct type_list { + using current_type = value_type; + using remaining_types = type_list; + static constexpr std::size_t size = 1 + sizeof...(rest); + }; + + template struct type_list { + using current_type = value_type; + static constexpr std::size_t size = 1; + }; + + template struct get_type_at_index; + + template struct get_type_at_index, 0> { + using type = value_type; + }; + + template struct get_type_at_index, Index> { + using type = typename get_type_at_index, Index - 1>::type; + }; } }// namespace jsonifier_internal diff --git a/Include/jsonifier/Vector.hpp b/Include/jsonifier/Vector.hpp index 0b34eb4e4..e679adbae 100644 --- a/Include/jsonifier/Vector.hpp +++ b/Include/jsonifier/Vector.hpp @@ -29,7 +29,8 @@ namespace jsonifier { - template class vector : protected std::equal_to, protected jsonifier_internal::alloc_wrapper { + template class vector : protected std::equal_to, + protected jsonifier_internal::alloc_wrapper { public: using value_type = value_type_new; using pointer = value_type*; @@ -44,7 +45,11 @@ namespace jsonifier { using size_type = uint64_t; using allocator = jsonifier_internal::alloc_wrapper; - JSONIFIER_INLINE vector() = default; + JSONIFIER_INLINE vector() { + if constexpr (doWeUseInitialBuffer) { + resize(static_cast(static_cast(1024 * 1024 * 4) * 0.85f)); + } + } JSONIFIER_INLINE vector& operator=(vector&& other) noexcept { if (this != &other && dataVal != other.dataVal) { @@ -73,12 +78,12 @@ namespace jsonifier { } } - JSONIFIER_INLINE vector& operator=(std::vector other) { + JSONIFIER_INLINE vector& operator=(std::vector&& other) { vector{ other }.swap(*this); return *this; } - JSONIFIER_INLINE explicit vector(std::vector other) : capacityVal{}, sizeVal{}, dataVal{} { + JSONIFIER_INLINE explicit vector(std::vector&& other) : capacityVal{}, sizeVal{}, dataVal{} { auto sizeValNew = other.size(); if (sizeValNew > 0 && sizeValNew < maxSize()) { reserve(sizeValNew); @@ -280,6 +285,24 @@ namespace jsonifier { return dataVal[sizeVal - 1]; } + JSONIFIER_INLINE reference emplace_back(value_type&& c) { + if (sizeVal + 1 >= capacityVal) { + reserve(capacityVal * 2 + 2); + } + allocator::construct(&dataVal[sizeVal++], std::move(c)); + + return dataVal[sizeVal - 1]; + } + + JSONIFIER_INLINE reference emplace_back(const value_type& c) { + if (sizeVal + 1 >= capacityVal) { + reserve(capacityVal * 2 + 2); + } + allocator::construct(&dataVal[sizeVal++], c); + + return dataVal[sizeVal - 1]; + } + JSONIFIER_INLINE void erase(size_type count) { if (count >= sizeVal) { return; @@ -344,9 +367,9 @@ namespace jsonifier { } capacityVal = newSize; dataVal = newPtr; - std::uninitialized_fill(dataVal + sizeVal, dataVal + capacityVal, value_type{}); + std::uninitialized_value_construct(dataVal + sizeVal, dataVal + capacityVal); } else if (newSize > sizeVal) [[unlikely]] { - std::uninitialized_fill(dataVal + sizeVal, dataVal + capacityVal, value_type{}); + std::uninitialized_value_construct(dataVal + sizeVal, dataVal + capacityVal); } else if (newSize < sizeVal) { std::destroy(dataVal + newSize, dataVal + sizeVal); } @@ -422,18 +445,3 @@ namespace jsonifier { }; }// namespace jsonifier - -namespace jsonifier_internal { - - class structural_index_vector : public jsonifier::vector { - public: - using allocator = alloc_wrapper; - using size_type = uint64_t; - using pointer = structural_index*; - using reference = structural_index&; - - JSONIFIER_INLINE structural_index_vector() { - resize(16384); - }; - }; -} diff --git a/ReadMe.md b/ReadMe.md index 01d610f2b..ca4d258c7 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -68,29 +68,29 @@ namespace jsonifier { template<> struct core { using value_type = TestNS::fixed_object_t; - static constexpr auto parseValue = createObject("int_array", &value_type::int_array, "float_array", &value_type::float_array, "double_array", &value_type::double_array); + static constexpr auto parseValue = createValue("int_array", &value_type::int_array, "float_array", &value_type::float_array, "double_array", &value_type::double_array); }; template<> struct core { using value_type = TestNS::fixed_name_object_t; - static constexpr auto parseValue = createObject("name0", &value_type::name0, "name1", &value_type::name1, "name2", &value_type::name2, "name3", &value_type::name3, "name4", &value_type::name4); + static constexpr auto parseValue = createValue("name0", &value_type::name0, "name1", &value_type::name1, "name2", &value_type::name2, "name3", &value_type::name3, "name4", &value_type::name4); }; template<> struct core { using value_type = TestNS::nested_object_t; - static constexpr auto parseValue = createObject("v3s", &value_type::v3s, "id", &value_type::id); + static constexpr auto parseValue = createValue("v3s", &value_type::v3s, "id", &value_type::id); }; template<> struct core { using value_type = TestNS::another_object_t; static constexpr auto parseValue = - createObject("string", &value_type::string, "another_string", &value_type::another_string, "boolean", &value_type::boolean, "nested_object", &value_type::nested_object); + createValue("string", &value_type::string, "another_string", &value_type::another_string, "boolean", &value_type::boolean, "nested_object", &value_type::nested_object); }; template<> struct core { using value_type = TestNS::obj_t; static constexpr auto parseValue = - createObject("fixed_object", &value_type::fixed_object, "fixed_name_object", &value_type::fixed_name_object, "another_object", &value_type::another_object, "string_array", + createValue("fixed_object", &value_type::fixed_object, "fixed_name_object", &value_type::fixed_name_object, "another_object", &value_type::another_object, "string_array", &value_type::string_array, "string", &value_type::string, "Number", &value_type::Number, "boolean", &value_type::boolean, "another_bool", &value_type::another_bool); }; } @@ -104,7 +104,7 @@ std::string buffer{ json0 }; obj_t obj{}; -jsonifier::jsonifier_core parser{}; +jsonifier::jsonifier_core<> parser{}; parser.parseJson(obj, buffer); ``` ### Usage - Serialization @@ -115,7 +115,7 @@ std::string buffer{}; obj_t obj{}; -jsonifier::jsonifier_core serializer{}; +jsonifier::jsonifier_core<> serializer{}; serializer.serializeJson(obj, buffer); ``` ## Excluding Keys from Serialization at Runtime @@ -186,7 +186,7 @@ Here's a complete example of parsing JSON data and handling errors: #include int32_t main() { - jsonifier::string buffer{ your_json_string }; + std::string buffer{ your_json_string }; obj_t obj; jsonifier::jsonifier_core jsonifier; diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index e9a55847c..fae21d8e0 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -20,14 +20,6 @@ FetchContent_Declare( ) FetchContent_MakeAvailable(simdjson) -FetchContent_Declare( - fmt - GIT_REPOSITORY https://github.com/fmtlib/fmt.git - GIT_TAG master - GIT_SHALLOW TRUE -) -FetchContent_MakeAvailable(fmt) - add_executable( "Json-Performance" "main.cpp" @@ -35,13 +27,20 @@ add_executable( target_link_libraries( "Json-Performance" PUBLIC - Jsonifier::Jsonifier glaze::glaze simdjson fmt::fmt + Jsonifier::Jsonifier glaze::glaze simdjson +) + +target_compile_options( + "Json-Performance" PUBLIC + "$<$:/Zi>" ) target_link_options( "Json-Performance" PUBLIC "$<$:$<$:-fsanitize=address>>" "$<$:/DEBUG>" + "$<$:/OPT:REF>" + "$<$:/OPT:ICF>" ) if (WIN32) diff --git a/Tests/main.cpp b/Tests/main.cpp index 37bfbb6a4..9e4da76db 100644 --- a/Tests/main.cpp +++ b/Tests/main.cpp @@ -1,173 +1,316 @@ #if defined(JSONIFIER_CPU_INSTRUCTIONS) - //#undef JSONIFIER_CPU_INSTRUCTIONS -//#define JSONIFIER_CPU_INSTRUCTIONS (JSONIFIER_POPCNT|JSONIFIER_BMI|JSONIFIER_BMI2|JSONIFIER_LZCNT) +//#undef JSONIFIER_CPU_INSTRUCTIONS +//#define JSONIFIER_CPU_INSTRUCTIONS (JSONIFIER_AVX | JSONIFIER_POPCNT | JSONIFIER_BMI | JSONIFIER_BMI2 | JSONIFIER_LZCNT) #endif #include "glaze/core/macros.hpp" #include "glaze/glaze.hpp" #include #include #include -#include "fmt/format.h" #include #include -static constexpr jsonifier::string_view discordData{ - "{\"d\":{\"_trace\":[\"[\\\"gateway-prd-us-east1-c-kxg8\\\",{\\\"micros\\\":156315,\\\"calls\\\":[\\\"id_created\\\",{\\\"micros\\\":1486," - "\\\"calls\\\":[]},\\\"session_lookup_" - "time\\\",{\\\"micros\\\":465,\\\"calls\\\":[]},\\\"session_lookup_finished\\\",{\\\"micros\\\":17,\\\"calls\\\":[]},\\\"discord-sessions-prd-2-" - "98\\\",{\\\"micros\\\":153461," - "\\\"calls\\\":[\\\"start_session\\\",{\\\"micros\\\":101160,\\\"calls\\\":[\\\"discord-api-5b464978d4-8n7pg\\\",{\\\"micros\\\":60256," - "\\\"calls\\\":[\\\"get_user\\\",{" - "\\\"micros\\\":11839},\\\"get_guilds\\\",{\\\"micros\\\":2977},\\\"send_scheduled_deletion_message\\\",{\\\"micros\\\":10},\\\"guild_join_" - "requests\\\",{\\\"micros\\\":5258}," - "\\\"authorized_ip_coro\\\",{\\\"micros\\\":13}]}]},\\\"starting_guild_connect\\\",{\\\"micros\\\":293,\\\"calls\\\":[]},\\\"presence_" - "started\\\",{\\\"micros\\\":292," - "\\\"calls\\\":[]},\\\"guilds_started\\\",{\\\"micros\\\":163,\\\"calls\\\":[]},\\\"guilds_connect\\\",{\\\"micros\\\":2,\\\"calls\\\":[]}," - "\\\"presence_connect\\\",{" - "\\\"micros\\\":51520,\\\"calls\\\":[]},\\\"connect_finished\\\",{\\\"micros\\\":51525,\\\"calls\\\":[]},\\\"build_ready\\\",{\\\"micros\\\":24," - "\\\"calls\\\":[]},\\\"clean_" - "ready\\\",{\\\"micros\\\":1,\\\"calls\\\":[]},\\\"optimize_ready\\\",{\\\"micros\\\":1,\\\"calls\\\":[]},\\\"split_ready\\\",{\\\"micros\\\":0," - "\\\"calls\\\":[]}]}]}]\"]," - "\"application\":{\"flags\":27828224,\"id\":1142733646600614004},\"auth\":{},\"current_location\":[\"CA\",\"CA:ON\"],\"geo_ordered_rtc_regions\":" - "[\"newark\",\"us-east\",\"us-" - "central\",\"atlanta\",\"us-south\"],\"guild_join_requests\":[],\"guilds\":[{\"id\":318872312596267018,\"unavailable\":true},{\"id\":" - "931640556814237706,\"unavailable\":true},{" - "\"id\":991025447875784714,\"unavailable\":true},{\"id\":995048955215872071,\"unavailable\":true},{\"id\":1022405038922006538,\"unavailable\":" - "true},{\"id\":" - "1032783776184533022,\"unavailable\":true},{\"id\":1078501504119476282,\"unavailable\":true},{\"id\":1131853763506880522,\"unavailable\":true},{" - "\"id\":1162943351935467552," - "\"unavailable\":true}],\"presences\":[],\"private_channels\":[],\"relationships\":[],\"resume_gateway_url\":\"wss://" - "gateway-us-east1-c.discord.gg\",\"session_id\":\"8a44f1277caeae224941fff2cc594c8f\",\"session_type\":\"normal\",\"shard\":\"01\",\"user\":{" - "\"avatar\":" - "\"88bd9ce7bf889c0d36fb4afd3725900b\",\"bot\":true,\"discriminator\":\"3055\",\"email\":null,\"flags\":0,\"global_name\":\"\",\"id\":" - "1142733646600614004,\"mfa_enabled\":false," - "\"username\":\"MBot-MusicHouse-2\",\"verified\":true},\"user_settings\":{},\"v\":10},\"op\":0,\"s\":1,\"t\":\"READY\"}" +class user_data { + public: + std::string avatarDecoration{}; + std::string discriminator{}; + std::string globalName{}; + std::string userName{}; + uint64_t accentColor{}; + uint64_t premiumType{}; + uint64_t publicFlags{}; + std::string locale{}; + std::string banner{}; + std::string avatar{}; + std::string email{}; + bool mfaEnabled{}; + std::string id{}; + uint64_t flags{}; + bool verified{}; + bool system{}; + bool bot{}; }; -struct application { - int64_t flags; - int64_t id; +class guild_scheduled_event_data { + public: + std::string scheduledStartTime{}; + std::string scheduledEndTime{}; + std::string description{}; + uint64_t entityMetadata{}; + std::string creatorId{}; + std::string channelId{}; + uint64_t privacyLevel{}; + std::string entityId{}; + std::string guildId{}; + uint64_t entityType{}; + uint64_t userCount{}; + user_data creator{}; + std::string name{}; + uint64_t status{}; + std::string id{}; }; -struct guild { - int64_t id; - bool unavailable; +class role_data { + public: + std::string unicodeEmoji{}; + std::string permissions{}; + uint64_t position{}; + std::string name{}; + std::string icon{}; + bool mentionable{}; + uint64_t color{}; + std::string id{}; + uint64_t flags{}; + bool managed{}; + bool hoist{}; }; -struct user { - std::string avatar; - bool bot; - std::string discriminator; - int64_t flags; - std::string globalName; - int64_t id; - bool mfaEnabled; - std::string username; - bool verified; +class channel_data { + public: + uint64_t defaultThreadRateLimitPerUser{}; + std::vector appliedTags{}; + uint64_t defaultAutoArchiveDuration{}; + std::vector recipients{}; + std::string lastPinTimestamp{}; + uint64_t totalMessageSent{}; + uint64_t rateLimitPerUser{}; + uint64_t videoQualityMode{}; + std::string lastMessageId{}; + std::string applicationId{}; + std::string permissions{}; + std::string rtcRegion{}; + uint64_t messageCount{}; + uint64_t memberCount{}; + std::string parentId{}; + std::string ownerId{}; + std::string guildId{}; + uint64_t userLimit{}; + std::string topic{}; + uint64_t position{}; + uint64_t bitrate{}; + std::string name{}; + std::string icon{}; + std::string id{}; + uint64_t flags{}; + uint64_t type{}; + bool managed{}; + bool nsfw{}; }; -struct d { - std::vector trace; - application applicationVal; - std::vector currentLocation; - std::vector geoOrderedRtcRegions; - std::vector guilds; - std::string resumeGatewayUrl; - std::string sessionId; - std::string sessionType; - std::string shard; - user userVal; - int64_t v; +class guild_member_data { + public: + std::string communicationDisabledUntil{}; + std::vector roles{}; + std::string premiumSince{}; + std::string permissions{}; + std::string joinedAt{}; + std::string guildId{}; + std::string avatar{}; + std::string nick{}; + user_data user{}; + uint64_t flags{}; + bool pending{}; + bool deaf{}; + bool mute{}; +}; + +class guild_data { + public: + std::vector guildScheduledEvents{}; + std::vector members{}; + uint64_t defaultMessageNotifications{}; + std::vector channels{}; + uint64_t maxStageVideoChannelUsers{}; + std::string publicUpdatesChannelId{}; + uint64_t premiumSubscriptionCount{}; + std::vector features{}; + uint64_t approximatePresenceCount{}; + std::string safetyAlertsChannelId{}; + uint64_t approximateMemberCount{}; + bool premiumProgressBarEnabled{}; + uint64_t explicitContentFilter{}; + uint64_t maxVideoChannelUsers{}; + std::vector roles{}; + std::string systemChannelId{}; + std::string widgetChannelId{}; + std::string preferredLocale{}; + std::string discoverySplash{}; + uint64_t systemChannelFlags{}; + std::string rulesChannelId{}; + uint64_t verificationLevel{}; + std::string applicationId{}; + std::string vanityUrlCode{}; + std::string afkChannelId{}; + std::string description{}; + std::string permissions{}; + uint64_t maxPresences{}; + std::string discovery{}; + uint64_t memberCount{}; + std::string joinedAt{}; + uint64_t premiumTier{}; + std::string ownerId{}; + uint64_t maxMembers{}; + uint64_t afkTimeout{}; + std::string splash{}; + std::string banner{}; + bool widgetEnabled{}; + uint64_t nsfwLevel{}; + uint64_t mfaLevel{}; + std::string name{}; + std::string icon{}; + bool unavailable{}; + std::string id{}; + uint64_t flags{}; + bool large{}; + bool owner{}; }; -struct welcome { - d dVal; - int64_t op; - int64_t s; +struct discord_message { std::string t; + uint64_t s; + uint64_t op; + guild_data d; +}; + +template<> struct jsonifier::core { + using value_type = user_data; + static constexpr auto parseValue = createValue("id", &value_type::id, "username", &value_type::userName, "discriminator", &value_type::discriminator, "bot", &value_type::bot, + "system", &value_type::system, "mfa_enabled", &value_type::mfaEnabled, "accentColor", &value_type::accentColor, "locale", &value_type::locale, "verified", + &value_type::verified, "email", &value_type::email, "flags", &value_type::flags, "premium_type", &value_type::premiumType, "public_flags", &value_type::publicFlags, + "avatar_decoration", &value_type::avatarDecoration); }; -template<> struct jsonifier::core { - using OTy = application; - static constexpr auto parseValue = createObject("flags", &OTy::flags, "id", &OTy::id); +template<> struct jsonifier::core { + using value_type = role_data; + static constexpr auto parseValue = createValue("id", &value_type::id, "name", &value_type::name, "color", &value_type::color, "hoist", &value_type::hoist, "position", + &value_type::position, "permissions", &value_type::permissions, "managed", &value_type::managed, "mentionable", &value_type::mentionable, "flags", &value_type::flags); }; -template<> struct jsonifier::core { - using OTy = guild; - static constexpr auto parseValue = createObject("id", &OTy::id, "unavailable", &OTy::unavailable); +template<> struct jsonifier::core { + using value_type = guild_member_data; + static constexpr auto parseValue = createValue("user", &value_type::user, "roles", &value_type::roles, "joined_at", &value_type::joinedAt, "deaf", &value_type::deaf, "mute", + &value_type::mute, "flags", &value_type::flags, "pending", &value_type::pending, "permissions", &value_type::permissions, "guild_id", &value_type::guildId); }; -template<> struct jsonifier::core { - using OTy = user; - static constexpr auto parseValue = createObject("avatar", &OTy::avatar, "bot", &OTy::bot, "discriminator", &OTy::discriminator, "flags", &OTy::flags, "global_name", - &OTy::globalName, "id", &OTy::id, "mfa_enabled", &OTy::mfaEnabled, "username", &OTy::username, "verified", &OTy::verified); +template<> struct jsonifier::core { + using value_type = channel_data; + static constexpr auto parseValue = createValue("default_thread_rate_limit_per_user", &value_type::defaultThreadRateLimitPerUser, "applied_tags", &value_type::appliedTags, + "default_auto_archive_duration", &value_type::defaultAutoArchiveDuration, "recipients", &value_type::recipients, "last_pin_timestamp", &value_type::lastPinTimestamp, + "total_message_sent", &value_type::totalMessageSent, "rate_limit_per_user", &value_type::rateLimitPerUser, "video_quality_mode", &value_type::videoQualityMode, + "permissions", &value_type::permissions, "message_count", &value_type::messageCount, "owner_id", &value_type::ownerId, "member_count", &value_type::memberCount, "flags", + &value_type::flags, "user_limit", &value_type::userLimit, "type", &value_type::type, "guild_id", &value_type::guildId, "position", &value_type::position, "name", + &value_type::name, "bitrate", &value_type::bitrate, "id", &value_type::id, "managed", &value_type::managed, "nsfw", &value_type::nsfw); }; -template<> struct jsonifier::core { - using OTy = d; - static constexpr auto parseValue = createObject("_trace", &OTy::trace, "application", &OTy::applicationVal, "current_location", &OTy::currentLocation, - "geo_ordered_rtc_regions", &OTy::geoOrderedRtcRegions, "guilds", &OTy::guilds, "resume_gateway_url", &OTy::resumeGatewayUrl, "session_id", &OTy::sessionId, "session_type", - &OTy::sessionType, "shard", &OTy::shard, "user", &OTy::userVal, "v", &OTy::v); +template<> struct jsonifier::core { + using value_type = guild_scheduled_event_data; + static constexpr auto parseValue = createValue("id", &value_type::id, "privacy_level", &value_type::privacyLevel, "entity_metadata", &value_type::entityMetadata, "entity_type", + &value_type::entityType, "status", &value_type::status, "scheduled_start_time", &value_type::scheduledStartTime, "scheduled_end_time", &value_type::scheduledEndTime, + "creator_id", &value_type::creatorId, "channel_id", &value_type::channelId, "entity_id", &value_type::entityId, "user_count", &value_type::userCount, "guild_id", + &value_type::guildId, "creator", &value_type::creator, "name", &value_type::name); }; -template<> struct jsonifier::core { - using OTy = welcome; - static constexpr auto parseValue = createObject("d", &OTy::dVal, "op", &OTy::op, "s", &OTy::s, "t", &OTy::t); +template<> struct jsonifier::core { + using value_type = guild_data; + static constexpr auto parseValue = createValue("default_message_notifications", &value_type::defaultMessageNotifications, "guild_scheduled_events", + &value_type::guildScheduledEvents, "explicit_content_filter", &value_type::explicitContentFilter, "system_channel_flags", &value_type::systemChannelFlags, "widget_enabled", + &value_type::widgetEnabled, "unavailable", &value_type::unavailable, "owner", &value_type::owner, "large", &value_type::large, "member_count", &value_type::memberCount, + "verification_level", &value_type::verificationLevel, "id", &value_type::id, "channels", &value_type::channels, "roles", &value_type::roles, "members", + &value_type::members, "owner_id", &value_type::ownerId, "permissions", &value_type::permissions, "features", &value_type::features, "max_stage_video_channel_users", + &value_type::maxStageVideoChannelUsers, "premium_subscription_count", &value_type::premiumSubscriptionCount, "approximate_presence_count", + &value_type::approximatePresenceCount, "approximate_member_count", &value_type::approximateMemberCount, "premium_progress_bar_enabled", + &value_type::premiumProgressBarEnabled, "max_video_channel_users", &value_type::maxVideoChannelUsers, "preferred_locale", &value_type::preferredLocale, "system_channel_id", + &value_type::systemChannelId, "widget_channel_id", &value_type::widgetChannelId, "nsfw_level", &value_type::nsfwLevel, "premium_tier", &value_type::premiumTier, + "afk_timeout", &value_type::afkTimeout, "max_members", &value_type::maxMembers, "mfa_level", &value_type::mfaLevel, "name", &value_type::name, "icon", &value_type::icon); }; -template<> struct glz::meta { - using OTy = application; - static constexpr auto value = object("flags", &OTy::flags, "id", &OTy::id); +template<> struct jsonifier::core { + using OTy = discord_message; + static constexpr auto parseValue = createValue("t", &OTy::t, "s", &OTy::s, "op", &OTy::op, "d", &OTy::d); }; -template<> struct glz::meta { - using OTy = guild; - static constexpr auto value = object("id", &OTy::id, "unavailable", &OTy::unavailable); +template<> struct glz::meta { + using value_type = user_data; + static constexpr auto value = object("id", &value_type::id, "username", &value_type::userName, "discriminator", &value_type::discriminator, "bot", &value_type::bot, "system", + &value_type::system, "mfa_enabled", &value_type::mfaEnabled, "accentColor", &value_type::accentColor, "locale", &value_type::locale, "verified", &value_type::verified, + "email", &value_type::email, "flags", &value_type::flags, "premium_type", &value_type::premiumType, "public_flags", &value_type::publicFlags, "avatar_decoration", + &value_type::avatarDecoration); }; -template<> struct glz::meta { - using OTy = user; - static constexpr auto value = object("avatar", &OTy::avatar, "bot", &OTy::bot, "discriminator", &OTy::discriminator, "flags", &OTy::flags, "global_name", skip{}, "id", - &OTy::id, "mfa_enabled", &OTy::mfaEnabled, "username", &OTy::username, "verified", &OTy::verified, "email", skip{}); +template<> struct glz::meta { + using value_type = role_data; + static constexpr auto value = object("id", &value_type::id, "name", &value_type::name, "color", &value_type::color, "hoist", &value_type::hoist, "position", + &value_type::position, "permissions", &value_type::permissions, "managed", &value_type::managed, "mentionable", &value_type::mentionable, "flags", &value_type::flags); }; -template<> struct glz::meta { - using OTy = d; - static constexpr auto value = object("_trace", &OTy::trace, "application", &OTy::applicationVal, "auth", skip{}, "current_location", &OTy::currentLocation, - "geo_ordered_rtc_regions", &OTy::geoOrderedRtcRegions, "guilds", &OTy::guilds, "resume_gateway_url", &OTy::resumeGatewayUrl, "session_id", &OTy::sessionId, "session_type", - &OTy::sessionType, "shard", &OTy::shard, "user", &OTy::userVal, "user_settings", skip{}, "v", &OTy::v, "guild_join_requests", skip{}, "presences", skip{}, "relationships", - skip{}, "private_channels", skip{}); +template<> struct glz::meta { + using value_type = guild_member_data; + static constexpr auto value = object("user", &value_type::user, "roles", &value_type::roles, "joined_at", &value_type::joinedAt, "deaf", &value_type::deaf, "mute", + &value_type::mute, "flags", &value_type::flags, "pending", &value_type::pending, "permissions", &value_type::permissions, "guild_id", &value_type::guildId); }; -template<> struct glz::meta { - using OTy = welcome; - static constexpr auto value = object("d", &OTy::dVal, "op", &OTy::op, "s", &OTy::s, "t", &OTy::t); +template<> struct glz::meta { + using value_type = channel_data; + static constexpr auto value = object("default_thread_rate_limit_per_user", &value_type::defaultThreadRateLimitPerUser, "applied_tags", &value_type::appliedTags, + "default_auto_archive_duration", &value_type::defaultAutoArchiveDuration, "recipients", &value_type::recipients, "last_pin_timestamp", &value_type::lastPinTimestamp, + "total_message_sent", &value_type::totalMessageSent, "rate_limit_per_user", &value_type::rateLimitPerUser, "video_quality_mode", &value_type::videoQualityMode, + "permissions", &value_type::permissions, "message_count", &value_type::messageCount, "owner_id", &value_type::ownerId, "member_count", &value_type::memberCount, "flags", + &value_type::flags, "user_limit", &value_type::userLimit, "type", &value_type::type, "guild_id", &value_type::guildId, "position", &value_type::position, "name", + &value_type::name, "bitrate", &value_type::bitrate, "id", &value_type::id, "managed", &value_type::managed, "nsfw", &value_type::nsfw); +}; + +template<> struct glz::meta { + using value_type = guild_scheduled_event_data; + static constexpr auto value = object("id", &value_type::id, "privacy_level", &value_type::privacyLevel, "entity_metadata", &value_type::entityMetadata, "entity_type", + &value_type::entityType, "status", &value_type::status, "scheduled_start_time", &value_type::scheduledStartTime, "scheduled_end_time", &value_type::scheduledEndTime, + "creator_id", &value_type::creatorId, "channel_id", &value_type::channelId, "entity_id", &value_type::entityId, "user_count", &value_type::userCount, "guild_id", + &value_type::guildId, "creator", &value_type::creator, "name", &value_type::name); +}; + +template<> struct glz::meta { + using value_type = guild_data; + static constexpr auto value = object("default_message_notifications", &value_type::defaultMessageNotifications, "guild_scheduled_events", &value_type::guildScheduledEvents, + "explicit_content_filter", &value_type::explicitContentFilter, "system_channel_flags", &value_type::systemChannelFlags, "widget_enabled", &value_type::widgetEnabled, + "unavailable", &value_type::unavailable, "owner", &value_type::owner, "large", &value_type::large, "member_count", &value_type::memberCount, "verification_level", + &value_type::verificationLevel, "id", &value_type::id, "channels", &value_type::channels, "roles", &value_type::roles, "members", &value_type::members, "owner_id", + &value_type::ownerId, "permissions", &value_type::permissions, "features", &value_type::features, "max_stage_video_channel_users", &value_type::maxStageVideoChannelUsers, + "premium_subscription_count", &value_type::premiumSubscriptionCount, "approximate_presence_count", &value_type::approximatePresenceCount, "approximate_member_count", + &value_type::approximateMemberCount, "premium_progress_bar_enabled", &value_type::premiumProgressBarEnabled, "max_video_channel_users", &value_type::maxVideoChannelUsers, + "preferred_locale", &value_type::preferredLocale, "system_channel_id", &value_type::systemChannelId, "widget_channel_id", &value_type::widgetChannelId, "nsfw_level", + &value_type::nsfwLevel, "premium_tier", &value_type::premiumTier, "afk_timeout", &value_type::afkTimeout, "max_members", &value_type::maxMembers, "mfa_level", + &value_type::mfaLevel, "name", &value_type::name, "icon", &value_type::icon, "banner", skip{}); +}; + +// Specialization for discord_message +template<> struct glz::meta { + using OTy = discord_message; + static constexpr auto value = object("t", &OTy::t, "s", &OTy::s, "op", &OTy::op, "d", &OTy::d); }; struct test_struct { - jsonifier::vector testStrings{}; - jsonifier::vector testUints{}; - jsonifier::vector testDoubles{}; - jsonifier::vector testInts{}; + std::vector testStrings{}; jsonifier::vector testBools{}; + std::vector testUints{}; + std::vector testDoubles{}; + std::vector testInts{}; }; struct json_data { - std::string theData{}; - jsonifier::vector arraySizes{}; + jsonifier::string theData{}; + std::vector arraySizes{}; }; template struct Test { - jsonifier::vector a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + std::vector a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; }; template struct TestGenerator { - jsonifier::vector a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; + std::vector a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z; std::random_device randomEngine{}; std::mt19937 gen{ randomEngine() }; - static constexpr jsonifier::string_view charset{ "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~\\\r\b\f\t\n" }; + static constexpr std::string_view charset{ "!#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~\"\\\r\b\f\t\n" }; template value_type randomizeNumber(value_type mean, value_type stdDeviation) { std::normal_distribution<> normalDistributionTwo{ static_cast(mean), static_cast(stdDeviation) }; @@ -179,18 +322,21 @@ template struct TestGenerator { } JSONIFIER_INLINE static json_data generateJsonData() { - jsonifier::string buffer{}; + std::string buffer{}; TestGenerator generator{}; jsonifier::jsonifier_core parser{}; + glz::write_json(generator, buffer); + //std::cout << "SERIALIZED JSON (GLAZE): " << buffer << std::endl; + buffer.clear(); parser.serializeJson(generator, buffer); //std::cout << "SERIALIZED JSON: " << buffer << std::endl; json_data returnData{}; - returnData.theData = buffer; + returnData.theData = buffer; return returnData; } std::string generateString() { - auto length{ randomizeNumber(45.0f, 10.0f) }; + auto length{ randomizeNumber(45.0f, 25.0f) }; static int32_t charsetSize = charset.size(); std::mt19937 generator(std::random_device{}()); std::uniform_int_distribution distribution(0, charsetSize - 1); @@ -221,30 +367,32 @@ template struct TestGenerator { TestGenerator() { auto fill = [&](auto& v) { - auto arraySize01 = randomizeNumber(35, 15); + auto arraySize01 = randomizeNumber(35, 20); + auto arraySize02 = randomizeNumber(20, 10); + auto arraySize03 = randomizeNumber(5, 1); v.resize(arraySize01); for (uint64_t x = 0; x < arraySize01; ++x) { - auto arraySize01 = randomizeNumber(20, 5); + auto arraySize01 = randomizeNumber(arraySize02, arraySize03); for (uint64_t y = 0; y < arraySize01; ++y) { - v[x].testStrings.emplace_back(generateString()); + auto newString = generateString(); + v[x].testStrings.emplace_back(newString); } - arraySize01 = randomizeNumber(20, 5); + arraySize01 = randomizeNumber(arraySize02, arraySize03); for (uint64_t y = 0; y < arraySize01; ++y) { v[x].testUints.emplace_back(generateUint()); } - arraySize01 = randomizeNumber(20, 5); + arraySize01 = randomizeNumber(arraySize02, arraySize03); for (uint64_t y = 0; y < arraySize01; ++y) { v[x].testInts.emplace_back(generateInt()); } - arraySize01 = randomizeNumber(20, 5); + arraySize01 = randomizeNumber(arraySize02, arraySize03); for (uint64_t y = 0; y < arraySize01; ++y) { v[x].testBools.emplace_back(generateBool()); } - arraySize01 = randomizeNumber(20, 5); + arraySize01 = randomizeNumber(arraySize02, arraySize03); for (uint64_t y = 0; y < arraySize01; ++y) { v[x].testDoubles.emplace_back(generateDouble()); } - } }; @@ -281,18 +429,18 @@ GLZ_META(test_struct, testBools, testInts, testUints, testDoubles, testStrings); GLZ_META(Test, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z); GLZ_META(TestGenerator, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z); template struct AbcTest { - jsonifier::vector z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a; + std::vector z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a; }; template<> struct jsonifier::core { using OTy = test_struct; - static constexpr auto parseValue = createObject("testBools", &OTy::testBools, "testInts", &OTy::testInts, "testUints", &OTy::testUints, "testDoubles", &OTy::testDoubles, - "testStrings", &OTy::testStrings); + static constexpr auto parseValue = + createValue("testBools", &OTy::testBools, "testInts", &OTy::testInts, "testUints", &OTy::testUints, "testDoubles", &OTy::testDoubles, "testStrings", &OTy::testStrings); }; template<> struct jsonifier::core> { using OTy = Test; - static constexpr auto parseValue = createObject("a", &OTy::a, "b", &OTy::b, "c", &OTy::c, "d", &OTy::d, "e", &OTy::e, "f", &OTy::f, "g", &OTy::g, "h", &OTy::h, "i", &OTy::i, + static constexpr auto parseValue = createValue("a", &OTy::a, "b", &OTy::b, "c", &OTy::c, "d", &OTy::d, "e", &OTy::e, "f", &OTy::f, "g", &OTy::g, "h", &OTy::h, "i", &OTy::i, "j", &OTy::j, "k", &OTy::k, "l", &OTy::l, "m", &OTy::m, "n", &OTy::n, "o", &OTy::o, "p", &OTy::p, "q", &OTy::q, "r", &OTy::r, "s", &OTy::s, "t", &OTy::t, "u", &OTy::u, "v", &OTy::v, "w", &OTy::w, "x", &OTy::x, "y", &OTy::y, "z", &OTy::z); }; @@ -300,14 +448,14 @@ template<> struct jsonifier::core> { template<> struct jsonifier::core> { using OTy = TestGenerator; - static constexpr auto parseValue = createObject("a", &OTy::a, "b", &OTy::b, "c", &OTy::c, "d", &OTy::d, "e", &OTy::e, "f", &OTy::f, "g", &OTy::g, "h", &OTy::h, "i", &OTy::i, + static constexpr auto parseValue = createValue("a", &OTy::a, "b", &OTy::b, "c", &OTy::c, "d", &OTy::d, "e", &OTy::e, "f", &OTy::f, "g", &OTy::g, "h", &OTy::h, "i", &OTy::i, "j", &OTy::j, "k", &OTy::k, "l", &OTy::l, "m", &OTy::m, "n", &OTy::n, "o", &OTy::o, "p", &OTy::p, "q", &OTy::q, "r", &OTy::r, "s", &OTy::s, "t", &OTy::t, "u", &OTy::u, "v", &OTy::v, "w", &OTy::w, "x", &OTy::x, "y", &OTy::y, "z", &OTy::z); }; template<> struct jsonifier::core> { using OTy = AbcTest; - static constexpr auto parseValue = createObject("z", &OTy::z, "y", &OTy::y, "x", &OTy::x, "w", &OTy::w, "v", &OTy::v, "u", &OTy::u, "t", &OTy::t, "s", &OTy::s, "r", &OTy::r, + static constexpr auto parseValue = createValue("z", &OTy::z, "y", &OTy::y, "x", &OTy::x, "w", &OTy::w, "v", &OTy::v, "u", &OTy::u, "t", &OTy::t, "s", &OTy::s, "r", &OTy::r, "q", &OTy::q, "p", &OTy::p, "o", &OTy::o, "n", &OTy::n, "m", &OTy::m, "l", &OTy::l, "k", &OTy::k, "j", &OTy::j, "i", &OTy::i, "h", &OTy::h, "g", &OTy::g, "f", &OTy::f, "e", &OTy::e, "d", &OTy::d, "c", &OTy::c, "b", &OTy::b, "a", &OTy::a); }; @@ -315,7 +463,7 @@ template<> struct jsonifier::core> { GLZ_META(AbcTest, z, y, x, w, v, u, t, s, r, q, p, o, n, m, l, k, j, i, h, g, f, e, d, c, b, a); #if defined(NDEBUG) -constexpr uint64_t iterations = 100; +constexpr uint64_t iterations = 200; #else constexpr uint64_t iterations = 1; #endif @@ -326,24 +474,27 @@ struct results { std::string url{}; uint64_t iterations{}; - std::optional json_byte_length{}; - std::optional json_read{}; - std::optional json_write{}; + std::optional json_write_byte_length{}; + std::optional json_read_byte_length{}; + std::optional json_read{}; + std::optional json_write{}; void print() { std::cout << std::string{ "| " } + name + " " + test + ": " + url + "\n" + "| ------------------------------------------------------------ " "|\n"; - if (json_byte_length) { - auto mbCount = static_cast(*json_byte_length) / (1024.0 * 1024.0); - auto readSecondCount = static_cast(*json_read) / (1000000000.0); - std::cout << "Length: " << *json_byte_length << std::endl; - std::cout << "Read: " << static_cast(mbCount / readSecondCount) << " MB/s\n"; - if (json_write) { - auto writeSecondCount = static_cast(*json_write) / (1000000000.0); - std::cout << "Write: " << static_cast(mbCount / writeSecondCount) << " MB/s\n"; - } + if (json_read_byte_length && json_read) { + auto mbReadCount = static_cast(*json_read_byte_length) / 1e+6l; + auto readSecondCount = *json_read / 1e+9l; + std::cout << "Read Length: " << *json_read_byte_length << std::endl; + std::cout << "Read: " << mbReadCount / readSecondCount << " MB/s\n"; + } + if (json_write_byte_length && json_write) { + auto mbWrittenCount = static_cast(*json_write_byte_length) / 1e+6l; + auto writeSecondCount = *json_write / 1e+9l; + std::cout << "Write Length: " << *json_write_byte_length << std::endl; + std::cout << "Write: " << mbWrittenCount / writeSecondCount << " MB/s\n"; } std::cout << "\n---" << std::endl; @@ -353,17 +504,24 @@ struct results { std::string write{}; std::string read{}; std::string finalstring{}; - auto mbCount = static_cast(*json_byte_length) / (1024.0 * 1024.0); - auto readSecondCount = static_cast(*json_read) / (1000000000.0); - double writeSecondCount{}; - if (json_write) { - writeSecondCount = static_cast(*json_write) / (1000000000.0); - write = fmt::format("{}", static_cast(mbCount / writeSecondCount)); + if (json_read && json_read_byte_length) { + double mbReadCount = static_cast(*json_read_byte_length) / 1e+6l; + double readSecondCount = *json_read / 1e+9l; + std::stringstream stream01{}; + stream01 << static_cast(mbReadCount / readSecondCount); + read = stream01.str(); + } + if (json_write && json_write_byte_length) { + double mbWrittenCount = static_cast(*json_write_byte_length) / 1e+6l; + double writeSecondCount = *json_write / 1e+9l; + std::stringstream stream01{}; + stream01 << static_cast(mbWrittenCount / writeSecondCount); + write = stream01.str(); } else { write = "N/A"; } - read = fmt::format("{}", static_cast(mbCount / readSecondCount)); - finalstring = fmt::format("| [**{}**]({}) | **{}** | **{}** |", name, url, write, read); + + finalstring = std::string{ "| [" + name + "](" + url + ") | " + write + " | " + read + " |" }; return finalstring; } }; @@ -379,15 +537,15 @@ class FileLoader { theStream.close(); } - void saveFile(std::string fileToSave) { + void saveFile(const jsonifier::string& fileToSave) { auto theStream = std::ofstream{ filePath.data(), std::ios::binary | std::ios::out | std::ios::in | std::ios::trunc }; theStream << ""; theStream.write(fileToSave.data(), fileToSave.size()); theStream.close(); } - operator std::string() { - return fileContents; + operator jsonifier::string() { + return jsonifier::string{ fileContents }; } ~FileLoader() { @@ -398,21 +556,21 @@ class FileLoader { std::string filePath{}; }; -template uint64_t benchmark(Function function, int64_t iterationCount) { - uint64_t currentLowestTime{ std::numeric_limits::max() }; +template double benchmark(Function function, int64_t iterationCount) { + std::chrono::duration currentLowestTime{ std::numeric_limits::max() }; for (int64_t x = 0; x < iterationCount; ++x) { - auto startTime = std::chrono::duration_cast>(std::chrono::system_clock::now().time_since_epoch()); + auto startTime = std::chrono::high_resolution_clock::now(); function(); - auto endTime = std::chrono::duration_cast>(std::chrono::system_clock::now().time_since_epoch()); - auto newTime = endTime - startTime; - if (static_cast(newTime.count()) < currentLowestTime) { - currentLowestTime = static_cast(newTime.count()); + auto endTime = std::chrono::high_resolution_clock::now(); + auto newTime = std::chrono::duration_cast>(endTime - startTime); + if (newTime < currentLowestTime) { + currentLowestTime = newTime; } } - return currentLowestTime; + return currentLowestTime.count(); } -auto jsonifier_single_test(const std::string bufferNew, bool doWePrint = true) { +auto jsonifier_single_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; results r{ "jsonifier", "Single Test", "https://github.com/realtimechris/jsonifier", 1 }; @@ -420,14 +578,14 @@ auto jsonifier_single_test(const std::string bufferNew, bool doWePrint = true) { jsonifier::jsonifier_core parser{}; auto result = benchmark( [&]() { - parser.parseJson(uint64Test, buffer); + parser.parseJson(uint64Test, buffer); }, 1); for (auto& value: parser.getErrors()) { std::cout << "Jsonifier Error: " << value << std::endl; } - r.json_byte_length = buffer.size(); - r.json_read = result; + r.json_read_byte_length = buffer.size(); + r.json_read = result; buffer.clear(); result = benchmark( @@ -435,10 +593,17 @@ auto jsonifier_single_test(const std::string bufferNew, bool doWePrint = true) { parser.serializeJson(uint64Test, buffer); }, 1); + for (auto& value: uint64Test.a) { + for (auto& value02: value.testStrings) { + //std::cout << "VALUE: " << value02 << std::endl; + } + } + for (auto& value: parser.getErrors()) { std::cout << "Jsonifier Error: " << value << std::endl; } - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -447,7 +612,7 @@ auto jsonifier_single_test(const std::string bufferNew, bool doWePrint = true) { return r; } -auto jsonifier_test(const std::string bufferNew, bool doWePrint = true) { +auto jsonifier_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; results r{ "jsonifier", "Multi Test", "https://github.com/realtimechris/jsonifier", iterations }; @@ -463,8 +628,8 @@ auto jsonifier_test(const std::string bufferNew, bool doWePrint = true) { std::cout << "Jsonifier Error: " << value << std::endl; } - r.json_read = result; - r.json_byte_length = buffer.size(); + r.json_read_byte_length = buffer.size(); + r.json_read = result; buffer.clear(); result = benchmark( @@ -475,7 +640,8 @@ auto jsonifier_test(const std::string bufferNew, bool doWePrint = true) { for (auto& value: parser.getErrors()) { std::cout << "Jsonifier Error: " << value << std::endl; } - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -484,7 +650,7 @@ auto jsonifier_test(const std::string bufferNew, bool doWePrint = true) { return r; } -auto jsonifier_abc_test(const std::string bufferNew, bool doWePrint = true) { +auto jsonifier_abc_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; results r{ "jsonifier", "Abc Test", "https://github.com/realtimechris/jsonifier", iterations }; @@ -502,7 +668,7 @@ auto jsonifier_abc_test(const std::string bufferNew, bool doWePrint = true) { r.json_read = result; - r.json_byte_length = buffer.size(); + r.json_read_byte_length = buffer.size(); buffer.clear(); result = benchmark( @@ -513,7 +679,8 @@ auto jsonifier_abc_test(const std::string bufferNew, bool doWePrint = true) { for (auto& value: parser.getErrors()) { std::cout << "Jsonifier Error: " << value << std::endl; } - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -522,12 +689,12 @@ auto jsonifier_abc_test(const std::string bufferNew, bool doWePrint = true) { return r; } -auto jsonifier_discord_test(bool doWePrint = true) { - std::string buffer{ discordData }; +auto jsonifier_discord_test(const std::string& discordDataNew, bool doWePrint = true) { + std::string buffer{ discordDataNew }; auto newSize = buffer.size(); results r{ "jsonifier", "Discord Test", "https://github.com/realtimechris/jsonifier", iterations }; - welcome discordDataTest{}; + discord_message discordDataTest{}; jsonifier::jsonifier_core parser{}; auto result = benchmark( @@ -541,7 +708,7 @@ auto jsonifier_discord_test(bool doWePrint = true) { r.json_read = result; - r.json_byte_length = buffer.size(); + r.json_read_byte_length = buffer.size(); buffer.clear(); result = benchmark( @@ -552,7 +719,8 @@ auto jsonifier_discord_test(bool doWePrint = true) { for (auto& value: parser.getErrors()) { std::cout << "Jsonifier Error: " << value << std::endl; } - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -561,7 +729,7 @@ auto jsonifier_discord_test(bool doWePrint = true) { return r; } -auto glaze_single_test(const std::string bufferNew, bool doWePrint = true) { +auto glaze_single_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; results r{ "glaze", "Single Test", "https://github.com/stephenberry/glaze", 1 }; @@ -569,13 +737,18 @@ auto glaze_single_test(const std::string bufferNew, bool doWePrint = true) { auto result = benchmark( [&]() { - if (auto error = glz::read_json(uint64Test, buffer); error) { - std::cout << "glaze Error: " << glz::format_error(error, buffer) << std::endl; + try { + if (auto error = glz::read(uint64Test, buffer); error) { + std::cout << "Glaze Error: " << glz::format_error(error, buffer) << std::endl; + } + } catch (std ::exception& error) { + std::cout << "Glaze Error: " << error.what() << std::endl; } }, 1); - r.json_read = result; + r.json_read = result; + r.json_read_byte_length = buffer.size(); buffer.clear(); result = benchmark( @@ -583,8 +756,8 @@ auto glaze_single_test(const std::string bufferNew, bool doWePrint = true) { glz::write_json(uint64Test, buffer); }, 1); - r.json_byte_length = buffer.size(); - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -593,7 +766,7 @@ auto glaze_single_test(const std::string bufferNew, bool doWePrint = true) { return r; } -auto glaze_test(const std::string bufferNew, bool doWePrint = true) { +auto glaze_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; results r{ "glaze", "Multi Test", "https://github.com/stephenberry/glaze", iterations }; @@ -601,15 +774,19 @@ auto glaze_test(const std::string bufferNew, bool doWePrint = true) { auto result = benchmark( [&]() { - if (auto error = glz::read_json(uint64Test, buffer); error) { - std::cout << "glaze Error: " << glz::format_error(error, buffer) << std::endl; + try { + if (auto error = glz::read(uint64Test, buffer); error) { + std::cout << "Glaze Error: " << glz::format_error(error, buffer) << std::endl; + } + } catch (std ::exception& error) { + std::cout << "Glaze Error: " << error.what() << std::endl; } }, iterations); r.json_read = result; - r.json_byte_length = buffer.size(); + r.json_read_byte_length = buffer.size(); buffer.clear(); result = benchmark( @@ -617,7 +794,8 @@ auto glaze_test(const std::string bufferNew, bool doWePrint = true) { glz::write_json(uint64Test, buffer); }, iterations); - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -626,7 +804,7 @@ auto glaze_test(const std::string bufferNew, bool doWePrint = true) { return r; } -auto glaze_abc_test(const std::string bufferNew, bool doWePrint = true) { +auto glaze_abc_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; results r{ "glaze", "Abc Test", "https://github.com/stephenberry/glaze", iterations }; @@ -634,15 +812,19 @@ auto glaze_abc_test(const std::string bufferNew, bool doWePrint = true) { auto result = benchmark( [&]() { - if (auto error = glz::read_json(uint64Test, buffer); error) { - std::cout << "glaze Error: " << glz::format_error(error, buffer) << std::endl; + try { + if (auto error = glz::read(uint64Test, buffer); error) { + std::cout << "Glaze Error: " << glz::format_error(error, buffer) << std::endl; + } + } catch (std ::exception& error) { + std::cout << "Glaze Error: " << error.what() << std::endl; } }, iterations); r.json_read = result; - r.json_byte_length = buffer.size(); + r.json_read_byte_length = buffer.size(); buffer.clear(); result = benchmark( @@ -650,7 +832,8 @@ auto glaze_abc_test(const std::string bufferNew, bool doWePrint = true) { glz::write_json(uint64Test, buffer); }, iterations); - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -659,23 +842,27 @@ auto glaze_abc_test(const std::string bufferNew, bool doWePrint = true) { return r; } -auto glaze_discord_test(bool doWePrint = true) { +auto glaze_discord_test(const std::string& discordData, bool doWePrint = true) { std::string buffer{ discordData }; results r{ "glaze", "Discord Test", "https://github.com/stephenberry/glaze", iterations }; - welcome discordDataTest{}; + discord_message discordDataTest{}; auto result = benchmark( [&]() { - if (auto error = glz::read_json(discordDataTest, buffer); error) { - std::cout << "glaze Error: " << glz::format_error(error, buffer) << std::endl; + try { + if (auto error = glz::read(discordDataTest, buffer); error) { + std::cout << "Glaze Error: " << glz::format_error(error, buffer) << std::endl; + } + } catch (std ::exception& error) { + std::cout << "Glaze Error: " << error.what() << std::endl; } }, iterations); r.json_read = result; - r.json_byte_length = buffer.size(); + r.json_read_byte_length = buffer.size(); buffer.clear(); result = benchmark( @@ -683,7 +870,8 @@ auto glaze_discord_test(bool doWePrint = true) { glz::write_json(discordDataTest, buffer); }, iterations); - r.json_write = result; + r.json_write_byte_length = buffer.size(); + r.json_write = result; buffer.clear(); if (doWePrint) { r.print(); @@ -703,6 +891,7 @@ struct on_demand { }; template void simdPullArray(ondemand::array newX, jsonifier::vector& newVector); +template void simdPullArray(ondemand::array newX, std::vector& newVector); void simdPullMap(ondemand::object newX, std::unordered_map& newVector) { for (auto iter = newX.begin(); iter != newX.end(); ++iter) { @@ -710,33 +899,48 @@ void simdPullMap(ondemand::object newX, std::unordered_map void simdPullArray(ondemand::array newX, jsonifier::vector& newVector) { +template<> void simdPullArray(ondemand::array newX, std::vector& newVector) { for (ondemand::value value: newX) { - newVector.emplace_back(value.get_double()); + double newValue{}; + if (!value.get_double().get(newValue)) { + newVector.emplace_back(newValue); + } } } -template<> void simdPullArray(ondemand::array newX, jsonifier::vector& newVector) { +template<> void simdPullArray(ondemand::array newX, std::vector& newVector) { for (ondemand::value value: newX) { - newVector.emplace_back(value.get_int64()); + int64_t newValue{}; + if (!value.get_int64().get(newValue)) { + newVector.emplace_back(newValue); + } } } -template<> void simdPullArray(ondemand::array newX, jsonifier::vector& newVector) { +template<> void simdPullArray(ondemand::array newX, std::vector& newVector) { for (ondemand::value value: newX) { - newVector.emplace_back(value.get_uint64()); + uint64_t newValue{}; + if (!value.get_uint64().get(newValue)) { + newVector.emplace_back(newValue); + } } } template<> void simdPullArray(ondemand::array newX, jsonifier::vector& newVector) { for (ondemand::value value: newX) { - newVector.emplace_back(value.get_bool()); + bool newValue{}; + if (!value.get_bool().get(newValue)) { + newVector.emplace_back(newValue); + } } } -template<> void simdPullArray(ondemand::array newX, jsonifier::vector& newVector) { +template<> void simdPullArray(ondemand::array newX, std::vector& newVector) { for (ondemand::value value: newX) { - newVector.emplace_back(static_cast(value.get_string().value())); + std::string_view newValue{}; + if (!value.get_string().get(newValue)) { + newVector.emplace_back(newValue); + } } } @@ -793,18 +997,22 @@ bool on_demand::read_in_order(Test& obj, const padded_string& json) return false; } -auto simdjson_single_test(const std::string& bufferNew, bool doWePrint = true) { +auto simdjson_single_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; on_demand parser{}; results r{ "simdjson", "Single Test", "https://github.com/simdjson/simdjson", 1 }; Test uint64Test{}; - r.json_byte_length = buffer.size(); - uint64_t result{}; + r.json_read_byte_length = buffer.size(); + double result{}; result = benchmark( [&]() { - parser.read_in_order(uint64Test, padded_string{ buffer }); + try { + parser.read_in_order(uint64Test, padded_string{ buffer }); + } catch (std ::exception& error) { + std::cout << "Simdjson Error: " << error.what() << std::endl; + } }, 1); @@ -817,18 +1025,22 @@ auto simdjson_single_test(const std::string& bufferNew, bool doWePrint = true) { return r; } -auto simdjson_test(const std::string& bufferNew, bool doWePrint = true) { +auto simdjson_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; on_demand parser{}; results r{ "simdjson", "Multi Test", "https://github.com/simdjson/simdjson", iterations }; Test uint64Test{}; - r.json_byte_length = buffer.size(); - uint64_t result{}; + r.json_read_byte_length = buffer.size(); + double result{}; result = benchmark( [&]() { - parser.read_in_order(uint64Test, padded_string{ buffer }); + try { + parser.read_in_order(uint64Test, padded_string{ buffer }); + } catch (std ::exception& error) { + std::cout << "Simdjson Error: " << error.what() << std::endl; + } }, iterations); @@ -879,92 +1091,461 @@ bool on_demand_abc::read_out_of_order(AbcTest& obj, const padded_st return false; } -template void extract_value(const simdjson::dom::element& elem, const char* key, T& value) { - simdjson::dom::element val; - if (elem[key].get(val) != simdjson::error_code::SUCCESS) { - throw std::runtime_error("Error extracting value for key: " + std::string(key)); +std::string getString(simdjson::ondemand::value value, const std::string& key) { + simdjson::ondemand::value field; + if (!value[key].get(field)) { + std::string_view result; + simdjson::error_code error{}; + field.get_string().tie(result, error); + return static_cast(result); } - if constexpr (std::same_as) { - value = static_cast(val.get().value()); - } else { - value = val.get(); + return ""; +} + +int64_t getInt(simdjson::ondemand::value value, const std::string& key) { + simdjson::ondemand::value field; + if (!value[key].get(field)) { + int64_t result; + simdjson::error_code error{}; + field.get_int64().tie(result, error); + return result; } + return 0; } -void extract_array(const simdjson::dom::element& elem, const char* key, std::vector& values) { - simdjson::dom::array arr; - if (elem[key].get(arr) != simdjson::error_code::SUCCESS) { - throw std::runtime_error("Error extracting array for key: " + std::string(key)); +bool getBool(simdjson::ondemand::value value, const std::string& key) { + simdjson::ondemand::value field; + if (!value[key].get(field)) { + bool result; + simdjson::error_code error{}; + field.get_bool().tie(result, error); + return result; } - for (auto val: arr) { - values.emplace_back(static_cast(val.get().value())); + return false; +} + +std::vector getInts(simdjson::ondemand::value value) { + std::vector roles; + for (simdjson::ondemand::value role: value) { + uint64_t roleValue; + simdjson::error_code error{}; + role.get_uint64().tie(roleValue, error); + roles.emplace_back(roleValue); } + return roles; } -void extract_guilds(const simdjson::dom::element& elem, const char* key, std::vector& guilds) { - simdjson::dom::array arr; - if (elem[key].get(arr) != simdjson::error_code::SUCCESS) { - throw std::runtime_error("Error extracting array for key: " + std::string(key)); +std::vector getStrings(simdjson::ondemand::value value) { + std::vector roles; + for (simdjson::ondemand::value role: value) { + std::string_view roleValue; + simdjson::error_code error{}; + role.get_string().tie(roleValue, error); + roles.emplace_back(roleValue); } - for (auto val: arr) { - guild g; - extract_value(val, "id", g.id); - extract_value(val, "unavailable", g.unavailable); - guilds.push_back(g); + return roles; +} + +user_data parseUserData(simdjson::ondemand::value jsonData) { + user_data user; + + simdjson::ondemand::object userObj = jsonData; + std::string_view newString{}; + jsonData["avatar_decoration"].get_string().get(newString); + user.avatarDecoration = std::string(newString); + + jsonData["discriminator"].get_string().get(newString); + user.discriminator = std::string(newString); + + jsonData["global_name"].get_string().get(newString); + user.globalName = std::string(newString); + + jsonData["user_name"].get_string().get(newString); + user.userName = std::string(newString); + + jsonData["locale"].get_string().get(newString); + user.locale = std::string(newString); + + jsonData["banner"].get_string().get(newString); + user.banner = std::string(newString); + + jsonData["avatar"].get_string().get(newString); + user.avatar = std::string(newString); + + jsonData["email"].get_string().get(newString); + user.email = std::string(newString); + + jsonData["id"].get_string().get(newString); + user.id = std::string(newString); + + jsonData["accent_color"].get_uint64().get(user.accentColor); + jsonData["premium_type"].get_uint64().get(user.premiumType); + jsonData["public_flags"].get_uint64().get(user.publicFlags); + jsonData["mfa_enabled"].get_bool().get(user.mfaEnabled); + jsonData["flags"].get_uint64().get(user.flags); + jsonData["verified"].get_bool().get(user.verified); + jsonData["system"].get_bool().get(user.system); + jsonData["bot"].get_bool().get(user.bot); + + return user; +} + +guild_scheduled_event_data parseGuildScheduledEventData(simdjson::ondemand::value json_data) { + guild_scheduled_event_data event; + + event.scheduledStartTime = json_data["scheduled_start_time"].get_string().value(); + event.scheduledEndTime = json_data["scheduled_end_time"].get_string().value(); + event.description = json_data["description"].get_string().value(); + event.entityMetadata = json_data["entity_metadata"].get_int64().value(); + event.creatorId = json_data["creator_id"].get_string().value(); + event.channelId = json_data["channel_id"].get_string().value(); + event.entityId = json_data["entity_id"].get_string().value(); + event.privacyLevel = json_data["privacy_level"].get_int64().value(); + event.guildId = json_data["guild_id"].get_string().value(); + event.userCount = json_data["user_count"].get_uint64().value(); + event.entityType = json_data["entity_type"].get_int64().value(); + std::string_view newString{}; + simdjson::ondemand::object creator_obj = json_data["creator"]; + + creator_obj["avatar_decoration"].get_string().get(newString); + event.creator.avatarDecoration = std::string(newString); + + creator_obj["discriminator"].get_string().get(newString); + event.creator.discriminator = std::string(newString); + + creator_obj["global_name"].get_string().get(newString); + event.creator.globalName = std::string(newString); + + creator_obj["user_name"].get_string().get(newString); + event.creator.userName = std::string(newString); + + creator_obj["locale"].get_string().get(newString); + event.creator.locale = std::string(newString); + + creator_obj["banner"].get_string().get(newString); + event.creator.banner = std::string(newString); + + creator_obj["avatar"].get_string().get(newString); + event.creator.avatar = std::string(newString); + + creator_obj["email"].get_string().get(newString); + event.creator.email = std::string(newString); + + creator_obj["id"].get_string().get(newString); + event.creator.id = std::string(newString); + creator_obj["accent_color"].get_uint64().get(event.creator.accentColor); + creator_obj["premium_type"].get_uint64().get(event.creator.premiumType); + creator_obj["public_flags"].get_uint64().get(event.creator.publicFlags); + creator_obj["mfa_enabled"].get_bool().get(event.creator.mfaEnabled); + creator_obj["flags"].get_uint64().get(event.creator.flags); + creator_obj["verified"].get_bool().get(event.creator.verified); + creator_obj["system"].get_bool().get(event.creator.system); + creator_obj["bot"].get_bool().get(event.creator.bot); + + json_data["name"].get_string().get(newString); + event.name = std::string(newString); + json_data["status"].get_uint64().get(event.status); + json_data["id"].get_string().get(newString); + event.id = std::string(newString); + + return event; +} + +channel_data parseChannelData(simdjson::ondemand::value jsonData) { + channel_data channel; + + simdjson::ondemand::object channelObj = jsonData; + std::string_view newString{}; + + channelObj["default_thread_rate_limit_per_user"].get_uint64().get(channel.defaultThreadRateLimitPerUser); + + for (auto tag: channelObj["applied_tags"]) { + tag.get_string().get(newString); + channel.appliedTags.push_back(std::string(newString)); } + + channelObj["default_auto_archive_duration"].get_uint64().get(channel.defaultAutoArchiveDuration); + + channelObj["last_pin_timestamp"].get_string().get(newString); + channel.lastPinTimestamp = std::string(newString); + + channelObj["total_message_sent"].get_uint64().get(channel.totalMessageSent); + channelObj["rate_limit_per_user"].get_uint64().get(channel.rateLimitPerUser); + channelObj["video_quality_mode"].get_uint64().get(channel.videoQualityMode); + + channelObj["last_message_id"].get_string().get(newString); + channel.lastMessageId = std::string(newString); + + channelObj["application_id"].get_string().get(newString); + channel.applicationId = std::string(newString); + + channelObj["permissions"].get_string().get(newString); + channel.permissions = std::string(newString); + + channelObj["rtc_region"].get_string().get(newString); + channel.rtcRegion = std::string(newString); + + channelObj["message_count"].get_uint64().get(channel.messageCount); + channelObj["member_count"].get_uint64().get(channel.memberCount); + + channelObj["parent_id"].get_string().get(newString); + channel.parentId = std::string(newString); + + channelObj["owner_id"].get_string().get(newString); + channel.ownerId = std::string(newString); + + channelObj["guild_id"].get_string().get(newString); + channel.guildId = std::string(newString); + + channelObj["user_limit"].get_uint64().get(channel.userLimit); + + channelObj["topic"].get_string().get(newString); + channel.topic = std::string(newString); + + channelObj["position"].get_uint64().get(channel.position); + channelObj["bitrate"].get_uint64().get(channel.bitrate); + + channelObj["name"].get_string().get(newString); + channel.name = std::string(newString); + + channelObj["icon"].get_string().get(newString); + channel.icon = std::string(newString); + + channelObj["id"].get_string().get(newString); + channel.id = std::string(newString); + + channelObj["flags"].get_uint64().get(channel.flags); + + channelObj["managed"].get_bool().get(channel.managed); + + channelObj["type"].get_uint64().get(channel.type); + + channelObj["nsfw"].get_bool().get(channel.nsfw); + + return channel; +} + + +role_data parseRoleData(simdjson::ondemand::value jsonData) { + role_data role; + + simdjson::ondemand::object roleObj = jsonData; + std::string_view newString{}; + + jsonData["unicode_emoji"].get_string().get(newString); + role.unicodeEmoji = std::string(newString); + + jsonData["permissions"].get_string().get(newString); + role.permissions = std::string(newString); + + jsonData["position"].get_uint64().get(role.position); + + jsonData["name"].get_string().get(newString); + role.name = std::string(newString); + + jsonData["icon"].get_string().get(newString); + role.icon = std::string(newString); + + jsonData["color"].get_uint64().get(role.color); + + jsonData["id"].get_string().get(newString); + role.id = std::string(newString); + + jsonData["flags"].get_uint64().get(role.flags); + + jsonData["mentionable"].get_bool().get(role.mentionable); + + jsonData["managed"].get_bool().get(role.managed); + + jsonData["hoist"].get_bool().get(role.hoist); + + return role; } -void extract_user(const simdjson::dom::element& elem, const char* key, user& usr) { - extract_value(elem[key], "avatar", usr.avatar); - extract_value(elem[key], "bot", usr.bot); - extract_value(elem[key], "discriminator", usr.discriminator); - extract_value(elem[key], "flags", usr.flags); - extract_value(elem[key], "global_name", usr.globalName); - extract_value(elem[key], "id", usr.id); - extract_value(elem[key], "mfa_enabled", usr.mfaEnabled); - extract_value(elem[key], "username", usr.username); - extract_value(elem[key], "verified", usr.verified); +guild_member_data parseGuildMemberData(simdjson::ondemand::value jsonData) { + guild_member_data guildMember; + + simdjson::ondemand::object memberObj = jsonData; + std::string_view newString{}; + + memberObj["communicationDisabledUntil"].get_string().get(newString); + guildMember.communicationDisabledUntil = std::string(newString); + + for (auto role: memberObj["roles"]) { + role.get_string().get(newString); + guildMember.roles.push_back(std::string(newString)); + } + + memberObj["premium_since"].get_string().get(newString); + guildMember.premiumSince = std::string(newString); + + memberObj["permissions"].get_string().get(newString); + guildMember.permissions = std::string(newString); + + memberObj["joined_at"].get_string().get(newString); + guildMember.joinedAt = std::string(newString); + + memberObj["guild_id"].get_string().get(newString); + guildMember.guildId = std::string(newString); + + memberObj["avatar"].get_string().get(newString); + guildMember.avatar = std::string(newString); + + memberObj["nick"].get_string().get(newString); + guildMember.nick = std::string(newString); + + guildMember.user = parseUserData(memberObj["user"].value()); + + memberObj["flags"].get_uint64().get(guildMember.flags); + memberObj["pending"].get_bool().get(guildMember.pending); + memberObj["deaf"].get_bool().get(guildMember.deaf); + memberObj["mute"].get_bool().get(guildMember.mute); + + return guildMember; +} + + +guild_data parseGuildData(simdjson::ondemand::value jsonData) { + guild_data guild; + + simdjson::ondemand::object guildObj = jsonData; + std::string_view newString{}; + + for (auto event: guildObj["guild_scheduled_events"]) { + guild_scheduled_event_data eventData = parseGuildScheduledEventData(event.value()); + guild.guildScheduledEvents.push_back(eventData); + } + + for (auto member: guildObj["members"]) { + guild_member_data memberData = parseGuildMemberData(member.value()); + guild.members.push_back(memberData); + } + + guildObj["default_message_notifications"].get_uint64().get(guild.defaultMessageNotifications); + + for (auto channel: guildObj["channels"]) { + channel_data channelData = parseChannelData(channel.value()); + guild.channels.push_back(channelData); + } + + guildObj["max_stage_video_channel_users"].get_uint64().get(guild.maxStageVideoChannelUsers); + guildObj["public_updates_channel_id"].get_string().get(newString); + guild.publicUpdatesChannelId = std::string(newString); + guildObj["premium_subscription_count"].get_uint64().get(guild.premiumSubscriptionCount); + + for (auto feature: guildObj["features"]) { + feature.get_string().get(newString); + guild.features.push_back(std::string(newString)); + } + + guildObj["approximate_presence_count"].get_uint64().get(guild.approximatePresenceCount); + guildObj["safety_alerts_channel_id"].get_string().get(newString); + guild.safetyAlertsChannelId = std::string(newString); + guildObj["approximate_member_count"].get_uint64().get(guild.approximateMemberCount); + guildObj["premium_progress_bar_enabled"].get_bool().get(guild.premiumProgressBarEnabled); + guildObj["max_video_channel_users"].get_uint64().get(guild.maxVideoChannelUsers); + guildObj["explicit_content_filter"].get_uint64().get(guild.explicitContentFilter); + + for (auto role: guildObj["roles"]) { + role_data roleData = parseRoleData(role.value()); + guild.roles.push_back(roleData); + } + + guildObj["system_channel_id"].get_string().get(newString); + guild.systemChannelId = std::string(newString); + guildObj["widget_channel_id"].get_string().get(newString); + guild.widgetChannelId = std::string(newString); + guildObj["preferred_locale"].get_string().get(newString); + guild.preferredLocale = std::string(newString); + guildObj["discovery_splash"].get_string().get(newString); + guild.discoverySplash = std::string(newString); + guildObj["system_channel_flags"].get_uint64().get(guild.systemChannelFlags); + guildObj["rules_channel_id"].get_string().get(newString); + guild.rulesChannelId = std::string(newString); + guildObj["application_id"].get_string().get(newString); + guild.applicationId = std::string(newString); + guildObj["verification_level"].get_uint64().get(guild.verificationLevel); + guildObj["vanity_url_code"].get_string().get(newString); + guild.vanityUrlCode = std::string(newString); + guildObj["afk_channel_id"].get_string().get(newString); + guild.afkChannelId = std::string(newString); + guildObj["description"].get_string().get(newString); + guild.description = std::string(newString); + guildObj["permissions"].get_string().get(newString); + guild.permissions = std::string(newString); + guildObj["max_presences"].get_uint64().get(guild.maxPresences); + guildObj["discovery"].get_string().get(newString); + guild.discovery = std::string(newString); + guildObj["member_count"].get_uint64().get(guild.memberCount); + guildObj["joined_at"].get_string().get(newString); + guild.joinedAt = std::string(newString); + guildObj["owner_id"].get_string().get(newString); + guild.ownerId = std::string(newString); + guildObj["premium_tier"].get_uint64().get(guild.premiumTier); + guildObj["max_members"].get_uint64().get(guild.maxMembers); + guildObj["afk_timeout"].get_uint64().get(guild.afkTimeout); + guildObj["splash"].get_string().get(newString); + guild.splash = std::string(newString); + guildObj["banner"].get_string().get(newString); + guild.banner = std::string(newString); + guildObj["widget_enabled"].get_bool().get(guild.widgetEnabled); + guildObj["nsfw_level"].get_uint64().get(guild.nsfwLevel); + guildObj["name"].get_string().get(newString); + guild.name = std::string(newString); + guildObj["icon"].get_string().get(newString); + guild.icon = std::string(newString); + guildObj["mfa_level"].get_uint64().get(guild.mfaLevel); + guildObj["unavailable"].get_bool().get(guild.unavailable); + guildObj["id"].get_string().get(newString); + guild.id = std::string(newString); + guildObj["flags"].get_uint64().get(guild.flags); + guildObj["large"].get_bool().get(guild.large); + guildObj["owner"].get_bool().get(guild.owner); + + return guild; } -void parse_json(const simdjson::dom::element& doc, welcome& welcomeData) { - extract_array(doc["d"], "_trace", welcomeData.dVal.trace); - extract_value(doc["d"], "resume_gateway_url", welcomeData.dVal.resumeGatewayUrl); - extract_value(doc["d"], "session_id", welcomeData.dVal.sessionId); - extract_value(doc["d"], "session_type", welcomeData.dVal.sessionType); - extract_value(doc["d"], "shard", welcomeData.dVal.shard); - extract_value(doc["d"], "v", welcomeData.dVal.v); +discord_message parseDiscordMessage(simdjson::ondemand::value jsonData) { + discord_message message; + + simdjson::ondemand::object messageObj = jsonData; + std::string_view newString{}; - extract_array(doc["d"], "current_location", welcomeData.dVal.currentLocation); - extract_array(doc["d"], "geo_ordered_rtc_regions", welcomeData.dVal.geoOrderedRtcRegions); - extract_guilds(doc["d"], "guilds", welcomeData.dVal.guilds); + messageObj["t"].get_string().get(newString); + message.t = std::string(newString); - extract_user(doc["d"], "user", welcomeData.dVal.userVal); + messageObj["s"].get_uint64().get(message.s); + messageObj["op"].get_uint64().get(message.op); - extract_value(doc, "op", welcomeData.op); - extract_value(doc, "s", welcomeData.s); - extract_value(doc, "t", welcomeData.t); + message.d = parseGuildData(messageObj["d"]); + + return message; } -auto simdjson_discord_test(bool doWePrint = true) { +auto simdjson_discord_test(const std::string& discordData, bool doWePrint = true) { std::string buffer{ discordData }; AbcTest obj{}; results r{ "simdjson", "Discord Test", "https://github.com/simdjson/simdjson", iterations }; - simdjson::dom::parser parser; + simdjson::ondemand::parser parser; - welcome welcomeData; + discord_message welcomeData; auto result = benchmark( [&]() { - simdjson::dom::element doc = parser.parse(buffer); - parse_json(doc, welcomeData); + try { + auto doc = parser.iterate(buffer); + parseDiscordMessage(doc); + } catch (std ::exception& error) { + std::cout << "Simdjson Error: " << error.what() << std::endl; + } }, iterations); - r.json_byte_length = buffer.size(); - r.json_read = result; + r.json_read_byte_length = buffer.size(); + r.json_read = result; if (doWePrint) { r.print(); } @@ -972,23 +1553,27 @@ auto simdjson_discord_test(bool doWePrint = true) { return r; } -auto simdjson_abc_test(const std::string& bufferNew, bool doWePrint = true) { +auto simdjson_abc_test(const jsonifier::string& bufferNew, bool doWePrint = true) { std::string buffer{ bufferNew }; on_demand_abc parser{}; AbcTest obj{}; results r{ "simdjson", "Abc Test", "https://github.com/simdjson/simdjson", iterations }; - uint64_t result{}; + double result{}; result = benchmark( [&]() { - parser.read_out_of_order(obj, padded_string{ buffer }); + try { + parser.read_out_of_order(obj, padded_string{ buffer }); + } catch (std ::exception& error) { + std::cout << "Simdjson Error: " << error.what() << std::endl; + } }, iterations); - r.json_byte_length = buffer.size(); - r.json_read = result; + r.json_read_byte_length = buffer.size(); + r.json_read = result; if (doWePrint) { r.print(); } @@ -1001,7 +1586,7 @@ static std::string table_header = R"( | ------------------------------------------------- | ---------- | ----------- |)"; std::string regular_test(const json_data& jsonData) { - jsonifier::vector results{}; + std::vector results{}; for (uint32_t x = 0; x < 2; ++x) { simdjson_test(jsonData.theData, false); } @@ -1028,7 +1613,7 @@ std::string regular_test(const json_data& jsonData) { } std::string abc_test(const json_data& jsonData) { - jsonifier::vector results{}; + std::vector results{}; for (uint32_t x = 0; x < 2; ++x) { simdjson_abc_test(jsonData.theData, false); } @@ -1054,20 +1639,20 @@ std::string abc_test(const json_data& jsonData) { return table; } -std::string discord_test(const json_data& jsonData) { - jsonifier::vector results{}; +std::string discord_test(const std::string& jsonData) { + std::vector results{}; for (uint32_t x = 0; x < 2; ++x) { - simdjson_discord_test(false); + simdjson_discord_test(jsonData, false); } - results.emplace_back(simdjson_discord_test()); + results.emplace_back(simdjson_discord_test(jsonData)); for (uint32_t x = 0; x < 2; ++x) { - glaze_discord_test(false); + glaze_discord_test(jsonData, false); } - results.emplace_back(glaze_discord_test()); + results.emplace_back(glaze_discord_test(jsonData)); for (uint32_t x = 0; x < 2; ++x) { - jsonifier_discord_test(false); + jsonifier_discord_test(jsonData, false); } - results.emplace_back(jsonifier_discord_test()); + results.emplace_back(jsonifier_discord_test(jsonData)); std::string table{}; const auto n = results.size(); @@ -1082,7 +1667,7 @@ std::string discord_test(const json_data& jsonData) { } std::string single_test(const json_data& jsonData) { - jsonifier::vector results{}; + std::vector results{}; for (uint32_t x = 0; x < 2; ++x) { simdjson_single_test(jsonData.theData, false); } @@ -1108,55 +1693,108 @@ std::string single_test(const json_data& jsonData) { return table; }; +namespace fs = std::filesystem; + +std::string readFileRecursively(const std::string& filename) { + fs::path currentPath = fs::current_path(); + + while (!currentPath.empty()) { + fs::path filePath = currentPath / filename; + + if (fs::exists(filePath) && fs::is_regular_file(filePath)) { + std::ifstream fileStream(filePath); + if (fileStream.is_open()) { + return std::string((std::istreambuf_iterator(fileStream)), std::istreambuf_iterator()); + } else { + std::cerr << "Error opening file: " << filePath << std::endl; + return ""; + } + } + + currentPath = currentPath.parent_path(); + } + + std::cerr << "File not found: " << filename << std::endl; + return ""; +} + +static const jsonifier::string section00{ R"(# Json-Performance +Performance profiling of JSON libraries (Compiled and run on Ubuntu-22.04 using the Clang++18 compiler) + +Latest Results: ()" }; + +static const jsonifier::string section01{ R"() + +Discord Test Results [(View the data used in the test)](https://github.com/RealTimeChris/Json-Performance/blob/main/DiscordData.json): + +---- +)" }; + +static const jsonifier::string section02{ + R"( + +Single Iteration Test Results [(View the data used in the following tests)](https://github.com/RealTimeChris/Json-Performance/blob/main/JsonData.json): + +---- +)" +}; + +static const jsonifier::string section03{ + R"( + +Multi Iteration Test Results: + +---- +)" +}; + +static const jsonifier::string section04{ + R"( +> )" + + jsonifier::toString(iterations) + R"( iterations on a 6 core (Intel i7 8700k))" + R"( + +## ABC Test (Out of Sequence Performance) + +The JSON documents in the previous tests featured keys ranging from "a" to "z," where each key corresponds to an array of values. Notably, the documents in this test arrange these keys in reverse order, deviating from the typical "a" to "z" arrangement. + +This test effectively demonstrates the challenges encountered when utilizing simdjson and iterative parsers that lack the ability to efficiently allocate memory locations through hashing. In cases where the keys are not in the expected sequence, performance is significantly compromised, with the severity escalating as the document size increases. + +In contrast, hash-based solutions offer a viable alternative by circumventing these issues and maintaining optimal performance regardless of the JSON document's scale, or ordering of the keys being parsed. +)" +}; + +static const jsonifier::string section05{ R"( +> )" + + jsonifier::toString(iterations) + R"( iterations on a 6 core (Intel i7 8700k))" }; + int32_t main() { try { json_data jsonData{ TestGenerator::generateJsonData() }; #if defined(_WIN32) FileLoader fileLoader01{ "../../../ReadMe.md" }; FileLoader fileLoader02{ "../../../JsonData.json" }; - fileLoader02.saveFile(glz::prettify(jsonData.theData)); + fileLoader02.saveFile(jsonifier::prettify(jsonData.theData)); #else FileLoader fileLoader01{ "../ReadMe.md" }; FileLoader fileLoader02{ "../JsonData.json" }; - fileLoader02.saveFile(glz::prettify(jsonData.theData)); + fileLoader02.saveFile(jsonifier::prettify(jsonData.theData)); #endif - std::string newTimeString{}; + jsonifier::string newTimeString{}; newTimeString.resize(1024); std::tm resultTwo{}; std::time_t result = std::time(nullptr); resultTwo = *localtime(&result); newTimeString.resize(strftime(newTimeString.data(), 1024, "%b %d, %Y", &resultTwo)); - auto discordTestResults = discord_test(jsonData); - auto singlTestResults = single_test(jsonData); - auto multiTestResults = regular_test(jsonData); - auto abcTestResults = abc_test(jsonData); - std::string newString = fileLoader01; - uint64_t currentStart{ 0 }; - uint64_t currentEnd{ 0 }; - currentEnd = newString.find("Latest results (") + std::string{ "Latest results (" }.size(); - std::string dateLine = newString.substr(currentStart, currentEnd); - currentStart = currentEnd + 2 + std::string{ "Jan 01, 2022" }.size(); - currentEnd = newString.find("Discord Test Results:") + std::string{ "Discord Test Results:" }.size(); - std::string section01 = newString.substr(currentStart, (currentEnd - currentStart)); - currentStart = newString.find("Single Iteration Test Results:"); - currentEnd = newString.find("Single Iteration Test Results:") + std::string{ "Single Iteration Test Results:" }.size(); - std::string section02 = newString.substr(currentStart, (currentEnd - currentStart)); - currentStart = newString.find("Multi Iteration Test Results:"); - currentEnd = newString.find("Multi Iteration Test Results:") + std::string{ "Multi Iteration Test Results:" }.size(); - std::string section03 = newString.substr(currentStart, (currentEnd - currentStart)); - currentStart = newString.find("## ABC Test (Out of Sequence Performance)"); - currentEnd = newString.find("In contrast, hash-based solutions offer a viable alternative by circumventing these issues and maintaining " - "optimal performance regardless of the JSON document's scale, or ordering of the keys being parsed.") + - std::string{ "In contrast, hash-based solutions offer a viable alternative by circumventing these issues and maintaining optimal " - "performance regardless of the JSON document's scale, or ordering of the keys being parsed." } - .size(); - std::string section04 = newString.substr(currentStart, (currentEnd - currentStart)); - std::string newerString = dateLine + newTimeString + "):" + section01 + "\n" + discordTestResults + "\n\n" + - "[Test object, used in the following tests:](https://github.com/RealTimeChris/Json-Performance/blob/main/JsonData.json)\n\n" + section02 + "\n" + singlTestResults + - "\n\n" + section03 + "\n" + multiTestResults + "\n" + "> " + std::to_string(iterations) + " iterations on a 6 core (Intel i7 8700k)\n\n" + section04 + "\n" + - abcTestResults + "\n" + "> " + std::to_string(iterations) + " iterations on a 6 core (Intel i7 8700k)"; + auto discordResults = discord_test(readFileRecursively("DiscordData.json")); + auto singleTestResults = single_test(jsonData); + auto multiTestResults = regular_test(jsonData); + auto abcTestResults = abc_test(jsonData); + jsonifier::string newerString = + section00 + newTimeString + section01 + discordResults + section02 + singleTestResults + section03 + multiTestResults + section04 + abcTestResults + section05; fileLoader01.saveFile(newerString); - } catch (std::exception& e) { + } catch (std::runtime_error& e) { + std::cout << e.what() << std::endl; + } catch (std::out_of_range& e) { std::cout << e.what() << std::endl; } return 0;