From dbe6000632c6a10f0b5e0934f978dd1a0362befe Mon Sep 17 00:00:00 2001 From: Lea Anthony Date: Fri, 27 Nov 2020 22:07:44 +1100 Subject: [PATCH] Support for radio menu items --- v2/internal/ffenestri/LICENCES.md | 13 + v2/internal/ffenestri/README.md | 62 --- v2/internal/ffenestri/ffenestri_darwin.c | 224 ++++++++- v2/internal/ffenestri/ffenestri_darwin.go | 111 ++++- v2/internal/ffenestri/hashmap.c | 397 --------------- v2/internal/ffenestri/hashmap.h | 571 +++++++++++++++++++--- v2/internal/ffenestri/vec.c | 113 +++++ v2/internal/ffenestri/vec.h | 181 +++++++ v2/internal/subsystem/event.go | 2 +- v2/internal/subsystem/menu.go | 10 +- v2/pkg/menu/menuitem.go | 58 ++- v2/pkg/menu/submenu.go | 10 - v2/test/kitchensink/main.go | 6 +- 13 files changed, 1181 insertions(+), 577 deletions(-) create mode 100644 v2/internal/ffenestri/LICENCES.md delete mode 100644 v2/internal/ffenestri/README.md delete mode 100644 v2/internal/ffenestri/hashmap.c create mode 100644 v2/internal/ffenestri/vec.c create mode 100644 v2/internal/ffenestri/vec.h delete mode 100644 v2/pkg/menu/submenu.go diff --git a/v2/internal/ffenestri/LICENCES.md b/v2/internal/ffenestri/LICENCES.md new file mode 100644 index 00000000..1b1bdf14 --- /dev/null +++ b/v2/internal/ffenestri/LICENCES.md @@ -0,0 +1,13 @@ +# 3rd Party Licenses + +## vec +Homepage: https://github.com/rxi/vec +License: https://github.com/rxi/vec/blob/master/LICENSE + +## json +Homepage: http://git.ozlabs.org/?p=ccan;a=tree;f=ccan/json;hb=HEAD +License: http://git.ozlabs.org/?p=ccan;a=blob;f=licenses/BSD-MIT;h=89de354795ec7a7cdab07c091029653d3618540d;hb=HEAD + +## hashmap +Homepage: https://github.com/sheredom/hashmap.h +License: https://github.com/sheredom/hashmap.h/blob/master/LICENSE \ No newline at end of file diff --git a/v2/internal/ffenestri/README.md b/v2/internal/ffenestri/README.md deleted file mode 100644 index 8eefa16d..00000000 --- a/v2/internal/ffenestri/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Dev Notes - -## DevTools error message - -There's an error message thrown when devtools is opened: - -``` -2020-09-11 22:00:31.083 te[20533:205250] NSWindow warning: adding an unknown subview: . Break on NSLog to debug. -2020-09-11 22:00:31.085 te[20533:205250] Call stack: -( - 0 AppKit 0x00007fff2790f9fd -[NSThemeFrame addSubview:] + 112 - 1 AppKit 0x00007fff2790f73b -[NSView addSubview:positioned:relativeTo:] + 203 - 2 AppKit 0x00007fff2790f5ee -[NSThemeFrame addSubview:positioned:relativeTo:] + 46 - 3 WebKit 0x00007fff3f10b6d3 _ZN6WebKit17WebInspectorProxy14platformAttachEv + 393 - 4 WebKit 0x00007fff3f52a58a _ZN6WebKit17WebInspectorProxy4openEv + 84 - 5 WebKit 0x00007fff3f6af6af _ZN6WebKit17WebInspectorProxy17didReceiveMessageERN3IPC10ConnectionERNS1_7DecoderE + 259 - 6 WebKit 0x00007fff3f1583d9 _ZN3IPC18MessageReceiverMap15dispatchMessageERNS_10ConnectionERNS_7DecoderE + 125 - 7 WebKit 0x00007fff3f49d71e _ZN6WebKit15WebProcessProxy17didReceiveMessageERN3IPC10ConnectionERNS1_7DecoderE + 28 - 8 WebKit 0x00007fff3f13929e _ZN3IPC10Connection15dispatchMessageENSt3__110unique_ptrINS_7DecoderENS1_14default_deleteIS3_EEEE + 698 - 9 WebKit 0x00007fff3f138b09 _ZN3IPC10Connection24dispatchIncomingMessagesEv + 477 - 10 JavaScriptCore 0x00007fff3bbf789d _ZN3WTF7RunLoop11performWorkEv + 573 - 11 JavaScriptCore 0x00007fff3bbf834a _ZN3WTF7RunLoop11performWorkEPv + 26 - 12 CoreFoundation 0x00007fff24ed34bc __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17 - 13 CoreFoundation 0x00007fff24ed3424 __CFRunLoopDoSource0 + 180 - 14 CoreFoundation 0x00007fff24ed319f __CFRunLoopDoSources0 + 248 - 15 CoreFoundation 0x00007fff24ed1bd1 __CFRunLoopRun + 890 - 16 CoreFoundation 0x00007fff24ed116e CFRunLoopRunSpecific + 563 - 17 HIToolbox 0x00007fff2dbc72e0 RunCurrentEventLoopInMode + 292 - 18 HIToolbox 0x00007fff2dbc70dc ReceiveNextEventCommon + 709 - 19 HIToolbox 0x00007fff2dbc6dff _BlockUntilNextEventMatchingListInModeWithFilter + 64 - 20 AppKit 0x00007fff278e6809 _DPSNextEvent + 879 - 21 AppKit 0x00007fff278e5035 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 1352 - 22 AppKit 0x00007fff278d7628 -[NSApplication run] + 586 - 23 te 0x000000000421dee8 Run + 1496 - 24 te 0x000000000406a710 runtime.asmcgocall + 112 -) -``` - -Found this related info: https://bugs.chromium.org/p/chromium/issues/detail?id=605219 - -``` -NSWindow has never supported clients adding subviews to anything other than the contentView. Some applications would add subviews to the contentView.superview (also known as the border view of the window). NSWindow will now log when it detects this scenario: "NSWindow warning: adding an unknown subview:". Applications doing this will need to fix this problem, as it prevents new features on 10.10 from working properly. See titlebarAccessoryViewControllers for official API. - -NSWindow now has the ability to add officially known subviews to the titlebar/toolbar area. The views are to be wrapped with a new NSViewController subclass called NSTitlebarAccessoryViewController and added to the window with the "titlebarAccessoryViewControllers" API. There are a set of methods to add and insert the titlebarAccessoryViewControllers, such as addTitlebarAccessoryViewController: and removeTitlebarAccessoryViewControllerAtIndex:. However, one can also utilize "removeFromParentViewController" to easily remove a given child view controller. NSTitlebarAccessoryViewController has a property to tell NSWindow where to place the view (layoutAttribute) and a property to determine how it behaves in full screen (fullScreenMinHeight). The NSToolbar fullScreenAccessoryView API is now deprecated, and clients should utilize this new API. -``` - -It doesn't appear to cause an issue, but needs resolving. - -## Startup timing issue - -It seems that even though the runtime is loaded, the CSS + JS after it aren't processed. -Pasting this part in devtools works: -``` -window.wails._.InjectCSS("html{text-align:center;}#input{margin:3rem;}#logo{width:50%;height:50%;margin:auto;display:block;background-position:center;background-size:cover;background-image:url(\"data:image/png;base64,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LliwoNB3f/nLX5aUIT0CcfWZJg1TPBzQ4cOH3/Oe9xTq6t15550lyx6ykitBp02b1qdc61/lnSrjwcUTf/7554866qievN+30/OKvnjZZZfZKsoSAAoRAOi1yg51vXnz5vxb7I9+9KM6lZ3uIgCE6/XXX58wYUL+339s7dq1zzzzTMno+1WuwYhen3766WULcMEFF1SZUbZL19ra+uyzz65cubL6x0qcfPLJLvqPZbu5q1evLnol2Jw5czqc0bZt29b82wMPPLCmp9x///3R7DrcpLPL29LS8tRTT3VPlTc2AaAQAYBeruQ8/KJFi/pkDrRVkpz/p2kIAEH72c9+ln+PFTcQp5xyyrnnnlvpf8v6wx/+UHbumzdvjvpeHc4x7eMf//g73vGOQod7f/7znzu+215uCIj43t/q665kRbz1rW/917/+1QvrM9mxJXeH55EsV6WMGjgBoBABgN4vab137dp1xBFHVG8Y07Zs2VLfklNzAkDoPvShD1X58Xflyor4b5QWsjNN2qBPf/rTnZt+9fkmdOxKpPvuixYtyt/1j1177bV1LHxOlUa2rr6wq1atir8e3yVf30XoJQSAQjoXABprY2us0nZC+hh5oy9spfLHp8TPOeec/JvroEGDDh8+3LPFp9sJAEGLGog//vGP6d95Da/bjofvLLm4It27il5s3769f//+NSxASVfvT3/6Uz3qtZdK7w+i9VJyHVelyky8853v7M33Uieb1s6dO9/2treVXYoqW9fIkSP37dtX9krZYAkAhRQKAOPGjcuelOudW13vLFXPaNZlj36tHW6i6dZyypQprqRtPgJA0OI+03nnnZftJHX92H/091Of+lQyo/ZyjWn0TtQSFRrGscPWKnlxwQUX9HSF9m7p9HX66acXrdiHHnqovuXPb/ny5Z3Yoi699NL463Z1MQGgkE5fAtT7e5mBnxZr3GXPlvyFF1648MIL82+osYULF9al/HQrAYD/vxa/ZCj9mmSA1tbW7du3J3uOShlg9+7dgwcPTn+xJlpaWpJhQ2l/8ygQq1atKlrbs2bNau/1O8KkeIcOHRo/fnzJInQ40HW0zWzcuLG+i9CrCACFdCUANEQPuyEKWUO9+bRMTunCv/jiiytWrBg+fHjO9jD9z/gO4IauCrIEgECVXOowb968PI1CHskTBBcsWJCdXdkyXHnllV2caXru8d/Pfe5z3V+LjSeq83379o0cObLQ2hwwYMDWrVt7f+ufLuGvf/3rohtz9PmpU6e6CighABRSKACMGjUq+k1t27Yt/vvP3iouW1tbW2i/i5dffjlZ/Ggd1XUlFBAVeMuWLfF29eSTT65fv/6+++772te+NnPmzKgZTxq6Qg3jsGHD3ADQlAQA/r9B37lz56BBg2py+29s8ODBu3fvrj7T5PXevXuPPvroKs+d7cTcd+3a1f0115AWLlyYVFTOql66dGm9S11NpR5JJ850R1auXNnD5e+1BIBC/lkkAPTJPMK8J5+bUdSKFSsC6fe3v9GePPzwwzXcJfWkso9yL3kz5zM04xfJsbxwtoFACADByd55Fr9YsmRJDe8EuPrqqws1Ftdee23nZlQiLvBVV13VrrUqZ9OmTfFzf3PuACLjxo175ZVX6l3wikrWcnqT3rFjR9Gry6KPDR8+vK2trR6L0usIAIUUDQAlG16nv9sDoi0hXsamb1STy37WrVsXL3svXzUdKnuLXf6Fij7597//vd6rhW4hAISo7KWcUafn6KOPrkmLM2zYsP379+efdfu/z7eOGDGiVnPft29f7Wut8UU1f+aZZ8a1lHMA0OjvT37yk0bZ62fLuWzZsk5sQl/4whfqUv7eRgAopHMBoIbnXbtPEgDC8fDDD/fpxWukkjwPc+zwk+nPGEujiQkA/NdNN92Uv2moYsWKFZ2Y+7e//e2c069evG9+85uN0mHtbiVne+J7f8squRohMX369OykGsjBgwdPPPHEPJtNWktLy1//+tf0dJLjgg1aD50jABTSlTMAvVywASAcZZvH1tZWY2k0MQGA/3r11VfHjRvXiSYj3XaMGTMmmk48wZz3jcX/e+jQofxP+S076+j18ccfH02nZMphKln25N7f7PWglao3av03b95caYKN4qGHHupT5MR3/JnJkyeXTCe0myDbBYCCBIBmEloA6FOueYwvpqVZCQC8yZ133lm2IajUWGQ/eccdd6QnmLO3FH9s5cqVnWunEsnzXAOXrfYvf/nLeVZlOhtEX2mvcNNIY5k1a1ae7arED3/4w3oXvM4EgEIEgGYSTgBIn/5N71vf+973JsfyaEoCAG9y+PDh0047LWfDkT2Q/K53vavsQ5Rydhyj706YMKHQAAVpEydObNAeas2VXKzy1FNPtba2VllxWcOHD690I0fD2bZtW/zA6TxDXyefie8Grj6CbXMTAAoRAJpJOAEgkW4eR4wYsX379vbwrnsMigBAqV/84hfZ5iCnBx54oOThKYXOAER/H3zwwaKtVfLiV7/6VRMcrq6hpO0+44wz8ldj/CI9GmajPxAnKvlXv/rVnJtT+p/x0yQqDTTU9ASAQgSAZhJIACi7lx8yZMjjjz/e6M0+HRIA+K/kp55/rJj47GH8sfe///3x4f8uNhmTJk3K32YlR20//OEP16AKmkV6FWQvrKpyQXxyBXwTtP5x4eNt8uWXXz7hhBOKblfR5v2Xv/yl7GRDIAAUIgA0k0ACQJ/MjmDYsGHr16+PKyGcti5MAgBlROk/5zCR6X9GLWZ6IkUPxiefKdryxne1lnTUtFyxtra24cOHZ9dmlfXb0tKyYcOG7KQaukqjwq9duzb/FpW8juJoQy94VwgAhQgAzSSQAFByMGjixInxsD/BnvYMigDAmyS/84suuihn2xE766yzshPpxFHk+MPTp0/PM9PEnDlzalYFzSKuyUsvvbRSW19pWOj4upfmULLtzZgxI+cmna6c22+/Pcz9nwBQiADQTAIJAImWlpbFixcfPHiw3hVPzxEAKG/Lli0DBgzINhNle41R2/HEE0/UcO4bNmx4y1vekueWzcjAgQO3bt1aw7k3uqS3unHjxmjVFNoNDB069Pnnn69v+btPtFXHdwMXcswxx+zZs6feZe9R8SZ044035r8jPw4AYSalWEkAaLhnSFUSLUgUAEK7vao5AkClc78lB4M++tGPxiM+u+U3KAIAZcRNwA033NCn3IXR2X9eeeWVXZ9diSuuuKJKg5Uuw0033dSVuTerqFanTp2afw8RX0l166231rvgNVZyX0q0reZ/JkBi3rx5yQTD2UHGZwBy5vDAzwBEW8W2bdsqVU7jihehc892bGjr1q1L10DjqlL+/v37z507t+TgXTjtGwIA/5E9wBP1nC6++OLqbUr04qKLLnrttddqOPfY4cOHZ8+enfTVKt2x+sUvflGDVSL9UIVKVVcivpn7tNNOKzuKa4MqexnrgQMHxo4dm3MHmf7MY489Vqfl6FHpQ4BRAMjf+4kCQJjPS05s3bq10EbVKKJliQJAIGcAOn0rWi+RZ4jnt7/97eeff/6qVava2traM5fstjf1+iVNAKAD11xzTXoI+bTo/a985Stx779WTUa6DYoywNKlS/v169en3BmAwYMH33LLLTWZaZOJqu7QoUOTJk067rjjxo0bd1xuv//979ubvfWPlm7NmjXRwkYxIH/9RB++8MIL0xOp4yJ0q/Si/eAHP0gWv3r9RNUYNQXtAff+I88991xcV1FtFNq6erN4WW677bZ6125PW79+fbL4jbUe4wJHxo8ff+qpp06dOnXGjBnz58//+te/fu+990YxNfsLTR/3Cfb3GyABgFLZgfy3b9++aNGiqCmJr5+O+v0nn3xy9E78oJBazbHSsed47tEc4xwyaNCgD3zgA8uWLdu9e3dN5t5kit54nf180+wAShakK4+o6+JXGksnNgZjhrQHUwnNulxZDb2kVbbGSsvV0MtLJwgA/EehjmNXxvnJOeUq7zfBEPXdqis100x1W6v9XPbzzVE/ZXViYZu4NjpBbTSHBm0Jk1NwHZa/ygU/DbfUdI4AQHllDxhUOYrQ9SajUntUJWy4ZrFDRU8FFP1WL1eyO0y/38UJNreiG0MIdZJHs54ECLOlbdylrn7sI88OnRAIAHRVFxuOQo1spQZL41WFyinRiWN7wdZhV04MhibnkVd6vxB2Ls26XOQnAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAAIiAAAAQEAEAAAACIgAAAAAAREAAAAgIAIAAAAERAAAAICACAAAABAQAQAAAALyf6bTKs5jpopFAAAAAElFTkSuQmCC\");}");// Get input + focus -var nameElement = document.getElementById("name"); -nameElement.focus(); -``` - -## FIX NEEDED - -We currently expect the text `` to appear in the html. -We should find the location of this text using case insensitive regex. \ No newline at end of file diff --git a/v2/internal/ffenestri/ffenestri_darwin.c b/v2/internal/ffenestri/ffenestri_darwin.c index c0a21c25..3cfc58ff 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.c +++ b/v2/internal/ffenestri/ffenestri_darwin.c @@ -73,7 +73,10 @@ extern const char *icon[]; int debug; // MenuItem map -map_t menuItemMap; +struct hashmap_s menuItemMap; + +// RadioGroup map. Maps a menuitem id with its associated radio group items +struct hashmap_s radioGroupMap; // Dispatch Method typedef void (^dispatchMethod)(void); @@ -106,6 +109,20 @@ BOOL yes(id self, SEL cmd) return YES; } +// Prints a hashmap entry +int hashmap_log(void const *context, struct hashmap_element_s const *e) { + printf("%s: %p ", (char*)e->key, e->data); + return 0; +} + +// Utility function to visualise a hashmap +void dumpHashmap(const char *name, struct hashmap_s *hashmap) { + printf("%s = { ", name); + if (0!=hashmap_iterate_pairs(hashmap, hashmap_log, NULL)) { + fprintf(stderr, "Failed to dump hashmap entries\n"); + } + printf("}\n"); +} extern void messageFromWindowCallback(const char *); typedef void (*ffenestriCallback)(const char *); @@ -330,8 +347,7 @@ void checkboxMenuItemPressed(id self, SEL cmd, id sender) { const char *menuID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue")); // Get the menu item from the menu item map - id menuItem; - hashmap_get(menuItemMap, (char*)menuID, (void**)&menuItem); + id menuItem = (id)hashmap_get(&menuItemMap, (char*)menuID, strlen(menuID)); // Get the current state bool state = msg(menuItem, s("state")); @@ -345,6 +361,42 @@ void checkboxMenuItemPressed(id self, SEL cmd, id sender) { free((void*)message); } +// radioMenuItemPressed +void radioMenuItemPressed(id self, SEL cmd, id sender) { + const char *menuID = (const char *)msg(msg(sender, s("representedObject")), s("pointerValue")); + + // Get the menu item from the menu item map + id menuItem = (id)hashmap_get(&menuItemMap, (char*)menuID, strlen(menuID)); + + // Check the menu items' current state + bool selected = msg(menuItem, s("state")); + + // If it's already selected, exit early + if (selected) { + return; + } + + // Get this item's radio group members and turn them off + id *members = (id*)hashmap_get(&radioGroupMap, (char*)menuID, strlen(menuID)); + + // Uncheck all members of the group + id thisMember = members[0]; + int count = 0; + while(thisMember != NULL) { + msg(thisMember, s("setState:"), NSControlStateValueOff); + count = count + 1; + thisMember = members[count]; + } + + // check the selected menu item + msg(menuItem, s("setState:"), NSControlStateValueOn); + + // Notify the backend + const char *message = concat("MC", menuID); + messageFromWindowCallback(message); + free((void*)message); +} + // closeWindow is called when the close button is pressed void closeWindow(id self, SEL cmd, id sender) { printf("\n\n\ncloseWindow called!!!!\n\n\n"); @@ -432,9 +484,30 @@ void* NewApplication(const char *title, int width, int height, int resizable, in result->sendMessageToBackend = (ffenestriCallback) messageFromWindowCallback; + + // Allocate new menuItem map + if( 0 != hashmap_create((const unsigned)16, &menuItemMap)) { + // Couldn't allocate map + Fatal(result, "Not enough memory to allocate menuItemMap!"); + return NULL; + } + + // Allocate the Radio Group Cache + if( 0 != hashmap_create((const unsigned)4, &radioGroupMap)) { + // Couldn't allocate map + Fatal(result, "Not enough memory to allocate radioGroupMap!"); + return NULL; + } + return (void*) result; } +int freeHashmapItem(void *context, struct hashmap_element_s const *e) { + free(e->data); + return -1; +} + + void DestroyApplication(struct Application *app) { Debug(app, "Destroying Application"); @@ -455,7 +528,15 @@ void DestroyApplication(struct Application *app) { } // Free menu item hashmap - hashmap_free(menuItemMap); + hashmap_destroy(&menuItemMap); + + // Free radio group members + if (0!=hashmap_iterate_pairs(&radioGroupMap, freeHashmapItem, NULL)) { + Error(app, "failed to deallocate hashmap entries!"); + } + + //Free radio groups hashmap + hashmap_destroy(&radioGroupMap); // Remove script handlers msg(app->manager, s("removeScriptMessageHandlerForName:"), str("windowDrag")); @@ -898,6 +979,8 @@ void createDelegate(struct Application *app) { // Menu Callbacks class_addMethod(delegateClass, s("menuCallback:"), (IMP)menuItemPressed, "v@:@"); class_addMethod(delegateClass, s("checkboxMenuCallback:"), (IMP)checkboxMenuItemPressed, "v@:@"); + class_addMethod(delegateClass, s("radioMenuCallback:"), (IMP)radioMenuItemPressed, "v@:@"); + // Script handler class_addMethod(delegateClass, s("userContentController:didReceiveScriptMessage:"), (IMP) messageHandler, "v@:@@"); @@ -1140,6 +1223,15 @@ bool getJSONBool(JsonNode *item, const char* key, bool *result) { return false; } +bool getJSONInt(JsonNode *item, const char* key, int *result) { + JsonNode *node = json_find_member(item, key); + if ( node != NULL && node->tag == JSON_NUMBER) { + *result = (int) node->number_; + return true; + } + return false; +} + id parseTextMenuItem(struct Application *app, id parentMenu, JsonNode *item, const char *label, const char *id, bool disabled) { const char *accelerator = ""; @@ -1150,14 +1242,30 @@ id parseCheckboxMenuItem(struct Application *app, id parentmenu, const char *tit id item = ALLOC("NSMenuItem"); // Store the item in the menu item map - hashmap_put(menuItemMap, (char*)menuid, item); + hashmap_put(&menuItemMap, (char*)menuid, strlen(menuid), item); id wrappedId = msg(c("NSValue"), s("valueWithPointer:"), menuid); msg(item, s("setRepresentedObject:"), wrappedId); msg(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("checkboxMenuCallback:"), str(key)); msg(item, s("setEnabled:"), !disabled); msg(item, s("autorelease")); - printf("\n\nSetting checked on menu: %s to %s\n\n", title, (checked? "true" : "false")); + msg(item, s("setState:"), (checked ? NSControlStateValueOn : NSControlStateValueOff)); + msg(parentmenu, s("addItem:"), item); + return item; + +} + +id parseRadioMenuItem(struct Application *app, id parentmenu, const char *title, const char *menuid, bool disabled, bool checked, const char *key) { + id item = ALLOC("NSMenuItem"); + + // Store the item in the menu item map + hashmap_put(&menuItemMap, (char*)menuid, strlen(menuid), item); + + id wrappedId = msg(c("NSValue"), s("valueWithPointer:"), menuid); + msg(item, s("setRepresentedObject:"), wrappedId); + msg(item, s("initWithTitle:action:keyEquivalent:"), str(title), s("radioMenuCallback:"), str(key)); + msg(item, s("setEnabled:"), !disabled); + msg(item, s("autorelease")); msg(item, s("setState:"), (checked ? NSControlStateValueOn : NSControlStateValueOff)); msg(parentmenu, s("addItem:"), item); return item; @@ -1176,7 +1284,6 @@ void parseMenuItem(struct Application *app, id parentMenu, JsonNode *item) { // Get the role JsonNode *role = json_find_member(item, "Role"); if( role != NULL ) { - printf("Parsing MENU ROLE %s!!!\n", role->string_); parseMenuRole(app, parentMenu, role); return; } @@ -1184,8 +1291,6 @@ void parseMenuItem(struct Application *app, id parentMenu, JsonNode *item) { // Check if this is a submenu JsonNode *submenu = json_find_member(item, "SubMenu"); if( submenu != NULL ) { - printf("Parsing SUBMENU!!!\n"); - // Get the label JsonNode *menuNameNode = json_find_member(item, "Label"); const char *name = ""; @@ -1204,7 +1309,6 @@ void parseMenuItem(struct Application *app, id parentMenu, JsonNode *item) { json_foreach(item, submenu) { // Get item label parseMenuItem(app, thisMenu, item); - printf("Parsing submenu item for '%s'!!!\n", name); } return; @@ -1217,7 +1321,7 @@ void parseMenuItem(struct Application *app, id parentMenu, JsonNode *item) { label = "(empty)"; } - const char *menuid = getJSONString(item, "Id"); + const char *menuid = getJSONString(item, "ID"); if ( menuid == NULL) { menuid = ""; } @@ -1239,7 +1343,6 @@ void parseMenuItem(struct Application *app, id parentMenu, JsonNode *item) { return; } if ( STREQ(type->string_, "Checkbox")) { - printf("PARSING CHECKBOX!!!!!!!!!!!"); // Get checked state bool checked = false; getJSONBool(item, "Checked", &checked); @@ -1247,6 +1350,14 @@ void parseMenuItem(struct Application *app, id parentMenu, JsonNode *item) { parseCheckboxMenuItem(app, parentMenu, label, menuid, disabled, checked, ""); return; } + if ( STREQ(type->string_, "Radio")) { + // Get checked state + bool checked = false; + getJSONBool(item, "Checked", &checked); + + parseRadioMenuItem(app, parentMenu, label, menuid, disabled, checked, ""); + return; + } return; } @@ -1268,22 +1379,98 @@ void parseMenu(struct Application *app, id parentMenu, JsonNode *menu) { } } +void dumpMemberList(const char *name, id *memberList) { + void *member = memberList[0]; + int count = 0; + printf("%s = %p -> [ ", name, memberList); + while( member != NULL ) { + printf("%p ", member); + count = count + 1; + member = memberList[count]; + } + printf("]\n"); +} + +void processRadioGroup(JsonNode *radioGroup) { + + int groupLength; + getJSONInt(radioGroup, "Length", &groupLength); + JsonNode *members = json_find_member(radioGroup, "Members"); + JsonNode *member; + + // Allocate array + size_t arrayLength = sizeof(id)*(groupLength+1); + id memberList[arrayLength]; + + // Build the radio group items + int count=0; + json_foreach(member, members) { + // Get menu by id + id menuItem = (id)hashmap_get(&menuItemMap, (char*)member->string_, strlen(member->string_)); + // Save Member + memberList[count] = menuItem; + count = count + 1; + } + // Null terminate array + memberList[groupLength] = 0; + + // dumpMemberList("memberList", memberList); + + // Store the members + json_foreach(member, members) { + // Copy the memberList + char *newMemberList = (char *)malloc(arrayLength); + memcpy(newMemberList, memberList, arrayLength); + // dumpMemberList("newMemberList", newMemberList); + // printf("Address of newMemberList = %p\n", newMemberList); + + // add group to each member of group + hashmap_put(&radioGroupMap, member->string_, strlen(member->string_), newMemberList); + } + + // dumpHashmap("radioGroupMap", &radioGroupMap); + +} + void parseMenuData(struct Application *app) { // Create a new menu bar id menubar = createMenu(str("")); - // Parse the menu json - JsonNode *menuData = json_decode(app->menuAsJSON); + // Parse the processed menu json + JsonNode *processedMenu = json_decode(app->menuAsJSON); + if( processedMenu == NULL ) { + // Parse error! + Fatal(app, "Unable to parse Menu JSON: %s", app->menuAsJSON); + return; + } + + // Pull out the Menu + JsonNode *menuData = json_find_member(processedMenu, "Menu"); if( menuData == NULL ) { // Parse error! - Fatal(app, "Unable to parse Menu JSON:", app->menuAsJSON); + Fatal(app, "Unable to find Menu data: %s", processedMenu); return; } parseMenu(app, menubar, menuData); + // Create the radiogroup cache + JsonNode *radioGroups = json_find_member(processedMenu, "RadioGroups"); + if( radioGroups == NULL ) { + // Parse error! + Fatal(app, "Unable to find RadioGroups data: %s", processedMenu); + return; + } + + // Iterate radio groups + JsonNode *radioGroup; + json_foreach(radioGroup, radioGroups) { + // Get item label + processRadioGroup(radioGroup); + } + // Apply the menu bar msg(msg(c("NSApplication"), s("sharedApplication")), s("setMainMenu:"), menubar); } @@ -1291,9 +1478,6 @@ void parseMenuData(struct Application *app) { void Run(struct Application *app, int argc, char **argv) { - // Allocate new hashmap - menuItemMap = hashmap_new(); - processDecorations(app); createApplication(app); @@ -1338,10 +1522,6 @@ void Run(struct Application *app, int argc, char **argv) { id wkwebview = msg(c("WKWebView"), s("alloc")); app->wkwebview = wkwebview; - // Only show content when fully rendered - - // TODO: Fix "NSWindow warning: adding an unknown subview: . Break on NSLog to debug." error - msg(wkwebview, s("initWithFrame:configuration:"), CGRectMake(0, 0, 0, 0), config); msg(contentView, s("addSubview:"), wkwebview); diff --git a/v2/internal/ffenestri/ffenestri_darwin.go b/v2/internal/ffenestri/ffenestri_darwin.go index 6a4e7af5..72c449c9 100644 --- a/v2/internal/ffenestri/ffenestri_darwin.go +++ b/v2/internal/ffenestri/ffenestri_darwin.go @@ -17,7 +17,11 @@ extern void SetWindowBackgroundIsTranslucent(void *); extern void SetMenu(void *, const char *); */ import "C" -import "encoding/json" +import ( + "encoding/json" + + "github.com/wailsapp/wails/v2/pkg/menu" +) func (a *Application) processPlatformSettings() error { @@ -69,12 +73,113 @@ func (a *Application) processPlatformSettings() error { // Process menu if mac.Menu != nil { - menuJson, err := json.Marshal(mac.Menu) + + /* + As radio groups need to be manually managed on OSX, + we preprocess the menu to determine the radio groups. + This is defined as any adjacent menu item of type "RadioType". + We keep a record of every radio group member we discover by saving + a list of all members of the group and the number of members + in the group (this last one is for optimisation at the C layer). + + Example: + { + "RadioGroups": [ + { + "Members": [ + "option-1", + "option-2", + "option-3" + ], + "Length": 3 + } + ] + } + */ + processedMenu := NewProcessedMenu(mac.Menu) + menuJSON, err := json.Marshal(processedMenu) if err != nil { return err } - C.SetMenu(a.app, a.string2CString(string(menuJson))) + C.SetMenu(a.app, a.string2CString(string(menuJSON))) } return nil } + +// ProcessedMenu is the original menu with the addition +// of radio groups extracted from the menu data +type ProcessedMenu struct { + Menu *menu.Menu + RadioGroups []*RadioGroup + currentRadioGroup []string +} + +// RadioGroup holds all the members of the same radio group +type RadioGroup struct { + Members []string + Length int +} + +// NewProcessedMenu processed the given menu and returns +// the original menu with the extracted radio groups +func NewProcessedMenu(menu *menu.Menu) *ProcessedMenu { + result := &ProcessedMenu{ + Menu: menu, + RadioGroups: []*RadioGroup{}, + currentRadioGroup: []string{}, + } + + result.processMenu() + + return result +} + +func (p *ProcessedMenu) processMenu() { + // Loop over top level menus + for _, item := range p.Menu.Items { + // Process MenuItem + p.processMenuItem(item) + } + + p.finaliseRadioGroup() +} + +func (p *ProcessedMenu) processMenuItem(item *menu.MenuItem) { + + switch item.Type { + + // We need to recurse submenus + case menu.SubmenuType: + + // Finalise any current radio groups as they don't trickle down to submenus + p.finaliseRadioGroup() + + // Process each submenu item + for _, subitem := range item.SubMenu { + p.processMenuItem(subitem) + } + case menu.RadioType: + // Add the item to the radio group + p.currentRadioGroup = append(p.currentRadioGroup, item.ID) + default: + p.finaliseRadioGroup() + } +} + +func (p *ProcessedMenu) finaliseRadioGroup() { + + // If we were processing a radio group, fix up the references + if len(p.currentRadioGroup) > 0 { + + // Create new radiogroup + group := &RadioGroup{ + Members: p.currentRadioGroup, + Length: len(p.currentRadioGroup), + } + p.RadioGroups = append(p.RadioGroups, group) + + // Empty the radio group + p.currentRadioGroup = []string{} + } +} diff --git a/v2/internal/ffenestri/hashmap.c b/v2/internal/ffenestri/hashmap.c deleted file mode 100644 index 3978400c..00000000 --- a/v2/internal/ffenestri/hashmap.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Generic map implementation. - */ -#include "hashmap.h" - -#include -#include -#include - -#define INITIAL_SIZE (256) -#define MAX_CHAIN_LENGTH (8) - -/* We need to keep keys and values */ -typedef struct _hashmap_element{ - char* key; - int in_use; - any_t data; -} hashmap_element; - -/* A hashmap has some maximum size and current size, - * as well as the data to hold. */ -typedef struct _hashmap_map{ - int table_size; - int size; - hashmap_element *data; -} hashmap_map; - -/* - * Return an empty hashmap, or NULL on failure. - */ -map_t hashmap_new() { - hashmap_map* m = (hashmap_map*) malloc(sizeof(hashmap_map)); - if(!m) goto err; - - m->data = (hashmap_element*) calloc(INITIAL_SIZE, sizeof(hashmap_element)); - if(!m->data) goto err; - - m->table_size = INITIAL_SIZE; - m->size = 0; - - return m; - err: - if (m) - hashmap_free(m); - return NULL; -} - -/* The implementation here was originally done by Gary S. Brown. I have - borrowed the tables directly, and made some minor changes to the - crc32-function (including changing the interface). //ylo */ - - /* ============================================================= */ - /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ - /* code or tables extracted from it, as desired without restriction. */ - /* */ - /* First, the polynomial itself and its table of feedback terms. The */ - /* polynomial is */ - /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ - /* */ - /* Note that we take it "backwards" and put the highest-order term in */ - /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ - /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ - /* the MSB being 1. */ - /* */ - /* Note that the usual hardware shift register implementation, which */ - /* is what we're using (we're merely optimizing it by doing eight-bit */ - /* chunks at a time) shifts bits into the lowest-order term. In our */ - /* implementation, that means shifting towards the right. Why do we */ - /* do it this way? Because the calculated CRC must be transmitted in */ - /* order from highest-order term to lowest-order term. UARTs transmit */ - /* characters in order from LSB to MSB. By storing the CRC this way, */ - /* we hand it to the UART in the order low-byte to high-byte; the UART */ - /* sends each low-bit to hight-bit; and the result is transmission bit */ - /* by bit from highest- to lowest-order term without requiring any bit */ - /* shuffling on our part. Reception works similarly. */ - /* */ - /* The feedback terms table consists of 256, 32-bit entries. Notes: */ - /* */ - /* The table can be generated at runtime if desired; code to do so */ - /* is shown later. It might not be obvious, but the feedback */ - /* terms simply represent the results of eight shift/xor opera- */ - /* tions for all combinations of data and CRC register values. */ - /* */ - /* The values must be right-shifted by eight bits by the "updcrc" */ - /* logic; the shift must be unsigned (bring in zeroes). On some */ - /* hardware you could probably optimize the shift in assembler by */ - /* using byte-swap instructions. */ - /* polynomial $edb88320 */ - /* */ - /* -------------------------------------------------------------------- */ - -static unsigned long crc32_tab[] = { - 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, - 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, - 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, - 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, - 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, - 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, - 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, - 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, - 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, - 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, - 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, - 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, - 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, - 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, - 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, - 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, - 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, - 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, - 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, - 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, - 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, - 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, - 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, - 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, - 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, - 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, - 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, - 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, - 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, - 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, - 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, - 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, - 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, - 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, - 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, - 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, - 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, - 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, - 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, - 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, - 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, - 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, - 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, - 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, - 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, - 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, - 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, - 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, - 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, - 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, - 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, - 0x2d02ef8dL - }; - -/* Return a 32-bit CRC of the contents of the buffer. */ - -unsigned long crc32(const unsigned char *s, unsigned int len) -{ - unsigned int i; - unsigned long crc32val; - - crc32val = 0; - for (i = 0; i < len; i ++) - { - crc32val = - crc32_tab[(crc32val ^ s[i]) & 0xff] ^ - (crc32val >> 8); - } - return crc32val; -} - -/* - * Hashing function for a string - */ -unsigned int hashmap_hash_int(hashmap_map * m, char* keystring){ - - unsigned long key = crc32((unsigned char*)(keystring), strlen(keystring)); - - /* Robert Jenkins' 32 bit Mix Function */ - key += (key << 12); - key ^= (key >> 22); - key += (key << 4); - key ^= (key >> 9); - key += (key << 10); - key ^= (key >> 2); - key += (key << 7); - key ^= (key >> 12); - - /* Knuth's Multiplicative Method */ - key = (key >> 3) * 2654435761; - - return key % m->table_size; -} - -/* - * Return the integer of the location in data - * to store the point to the item, or MAP_FULL. - */ -int hashmap_hash(map_t in, char* key){ - int curr; - int i; - - /* Cast the hashmap */ - hashmap_map* m = (hashmap_map *) in; - - /* If full, return immediately */ - if(m->size >= (m->table_size/2)) return MAP_FULL; - - /* Find the best index */ - curr = hashmap_hash_int(m, key); - - /* Linear probing */ - for(i = 0; i< MAX_CHAIN_LENGTH; i++){ - if(m->data[curr].in_use == 0) - return curr; - - if(m->data[curr].in_use == 1 && (strcmp(m->data[curr].key,key)==0)) - return curr; - - curr = (curr + 1) % m->table_size; - } - - return MAP_FULL; -} - -/* - * Doubles the size of the hashmap, and rehashes all the elements - */ -int hashmap_rehash(map_t in){ - int i; - int old_size; - hashmap_element* curr; - - /* Setup the new elements */ - hashmap_map *m = (hashmap_map *) in; - hashmap_element* temp = (hashmap_element *) - calloc(2 * m->table_size, sizeof(hashmap_element)); - if(!temp) return MAP_OMEM; - - /* Update the array */ - curr = m->data; - m->data = temp; - - /* Update the size */ - old_size = m->table_size; - m->table_size = 2 * m->table_size; - m->size = 0; - - /* Rehash the elements */ - for(i = 0; i < old_size; i++){ - int status; - - if (curr[i].in_use == 0) - continue; - - status = hashmap_put(m, curr[i].key, curr[i].data); - if (status != MAP_OK) - return status; - } - - free(curr); - - return MAP_OK; -} - -/* - * Add a pointer to the hashmap with some key - */ -int hashmap_put(map_t in, char* key, any_t value){ - int index; - hashmap_map* m; - - /* Cast the hashmap */ - m = (hashmap_map *) in; - - /* Find a place to put our value */ - index = hashmap_hash(in, key); - while(index == MAP_FULL){ - if (hashmap_rehash(in) == MAP_OMEM) { - return MAP_OMEM; - } - index = hashmap_hash(in, key); - } - - /* Set the data */ - m->data[index].data = value; - m->data[index].key = key; - m->data[index].in_use = 1; - m->size++; - - return MAP_OK; -} - -/* - * Get your pointer out of the hashmap with a key - */ -int hashmap_get(map_t in, char* key, any_t *arg){ - int curr; - int i; - hashmap_map* m; - - /* Cast the hashmap */ - m = (hashmap_map *) in; - - /* Find data location */ - curr = hashmap_hash_int(m, key); - - /* Linear probing, if necessary */ - for(i = 0; idata[curr].in_use; - if (in_use == 1){ - if (strcmp(m->data[curr].key,key)==0){ - *arg = (m->data[curr].data); - return MAP_OK; - } - } - - curr = (curr + 1) % m->table_size; - } - - *arg = NULL; - - /* Not found */ - return MAP_MISSING; -} - -/* - * Iterate the function parameter over each element in the hashmap. The - * additional any_t argument is passed to the function as its first - * argument and the hashmap element is the second. - */ -int hashmap_iterate(map_t in, PFany f, any_t item) { - int i; - - /* Cast the hashmap */ - hashmap_map* m = (hashmap_map*) in; - - /* On empty hashmap, return immediately */ - if (hashmap_length(m) <= 0) - return MAP_MISSING; - - /* Linear probing */ - for(i = 0; i< m->table_size; i++) - if(m->data[i].in_use != 0) { - any_t data = (any_t) (m->data[i].data); - int status = f(item, data); - if (status != MAP_OK) { - return status; - } - } - - return MAP_OK; -} - -/* - * Remove an element with that key from the map - */ -int hashmap_remove(map_t in, char* key){ - int i; - int curr; - hashmap_map* m; - - /* Cast the hashmap */ - m = (hashmap_map *) in; - - /* Find key */ - curr = hashmap_hash_int(m, key); - - /* Linear probing, if necessary */ - for(i = 0; idata[curr].in_use; - if (in_use == 1){ - if (strcmp(m->data[curr].key,key)==0){ - /* Blank out the fields */ - m->data[curr].in_use = 0; - m->data[curr].data = NULL; - m->data[curr].key = NULL; - - /* Reduce the size */ - m->size--; - return MAP_OK; - } - } - curr = (curr + 1) % m->table_size; - } - - /* Data not found */ - return MAP_MISSING; -} - -/* Deallocate the hashmap */ -void hashmap_free(map_t in){ - hashmap_map* m = (hashmap_map*) in; - free(m->data); - free(m); -} - -/* Return the length of the hashmap */ -int hashmap_length(map_t in){ - hashmap_map* m = (hashmap_map *) in; - if(m != NULL) return m->size; - else return 0; -} \ No newline at end of file diff --git a/v2/internal/ffenestri/hashmap.h b/v2/internal/ffenestri/hashmap.h index aa488025..0278bc3d 100644 --- a/v2/internal/ffenestri/hashmap.h +++ b/v2/internal/ffenestri/hashmap.h @@ -1,81 +1,518 @@ /* - * Generic hashmap manipulation functions - * - * Originally by Elliot C Back - http://elliottback.com/wp/hashmap-implementation-in-c/ - * - * Modified by Pete Warden to fix a serious performance problem, support strings as keys - * and removed thread synchronization - http://petewarden.typepad.com - */ -#ifndef __HASHMAP_H__ -#define __HASHMAP_H__ - -#define MAP_MISSING -3 /* No such element */ -#define MAP_FULL -2 /* Hashmap is full */ -#define MAP_OMEM -1 /* Out of Memory */ -#define MAP_OK 0 /* OK */ - -/* - * any_t is a pointer. This allows you to put arbitrary structures in - * the hashmap. - */ -typedef void *any_t; - -/* - * PFany is a pointer to a function that can take two any_t arguments - * and return an integer. Returns status code.. - */ -typedef int (*PFany)(any_t, any_t); - -/* - * map_t is a pointer to an internally maintained data structure. - * Clients of this package do not need to know how hashmaps are - * represented. They see and manipulate only map_t's. - */ -typedef any_t map_t; - -/* - * Return an empty hashmap. Returns NULL if empty. + The latest version of this library is available on GitHub; + https://github.com/sheredom/hashmap.h */ -extern map_t hashmap_new(); /* - * Iteratively call f with argument (item, data) for - * each element data in the hashmap. The function must - * return a map status code. If it returns anything other - * than MAP_OK the traversal is terminated. f must - * not reenter any hashmap functions, or deadlock may arise. - */ -extern int hashmap_iterate(map_t in, PFany f, any_t item); + This is free and unencumbered software released into the public domain. -/* - * Add an element to the hashmap. Return MAP_OK or MAP_OMEM. - */ -extern int hashmap_put(map_t in, char* key, any_t value); + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. -/* - * Get an element from the hashmap. Return MAP_OK or MAP_MISSING. - */ -extern int hashmap_get(map_t in, char* key, any_t *arg); + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. -/* - * Remove an element from the hashmap. Return MAP_OK or MAP_MISSING. - */ -extern int hashmap_remove(map_t in, char* key); + 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 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. -/* - * Get any element. Return MAP_OK or MAP_MISSING. - * remove - should the element be removed from the hashmap - */ -extern int hashmap_get_one(map_t in, any_t *arg, int remove); + For more information, please refer to +*/ +#ifndef SHEREDOM_HASHMAP_H_INCLUDED +#define SHEREDOM_HASHMAP_H_INCLUDED -/* - * Free the hashmap - */ -extern void hashmap_free(map_t in); +#if defined(_MSC_VER) +// Workaround a bug in the MSVC runtime where it uses __cplusplus when not +// defined. +#pragma warning(push, 0) +#pragma warning(disable : 4668) +#endif +#include +#include +#if (defined(_MSC_VER) && defined(__AVX__)) || \ + (!defined(_MSC_VER) && defined(__SSE4_2__)) +#define HASHMAP_SSE42 +#endif + +#if defined(HASHMAP_SSE42) +#include +#endif + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#if defined(_MSC_VER) +#pragma warning(push) +// Stop MSVC complaining about not inlining functions. +#pragma warning(disable : 4710) +// Stop MSVC complaining about inlining functions! +#pragma warning(disable : 4711) +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif + +#if defined(_MSC_VER) +#define HASHMAP_USED +#elif defined(__GNUC__) +#define HASHMAP_USED __attribute__((used)) +#else +#define HASHMAP_USED +#endif + +/* We need to keep keys and values. */ +struct hashmap_element_s { + const char *key; + unsigned key_len; + int in_use; + void *data; +}; + +/* A hashmap has some maximum size and current size, as well as the data to + * hold. */ +struct hashmap_s { + unsigned table_size; + unsigned size; + struct hashmap_element_s *data; +}; + +#define HASHMAP_MAX_CHAIN_LENGTH (8) + +#if defined(__cplusplus) +extern "C" { +#endif + +/// @brief Create a hashmap. +/// @param initial_size The initial size of the hashmap. Must be a power of two. +/// @param out_hashmap The storage for the created hashmap. +/// @return On success 0 is returned. +/// +/// Note that the initial size of the hashmap must be a power of two, and +/// creation of the hashmap will fail if this is not the case. +static int hashmap_create(const unsigned initial_size, + struct hashmap_s *const out_hashmap) HASHMAP_USED; + +/// @brief Put an element into the hashmap. +/// @param hashmap The hashmap to insert into. +/// @param key The string key to use. +/// @param len The length of the string key. +/// @param value The value to insert. +/// @return On success 0 is returned. +/// +/// The key string slice is not copied when creating the hashmap entry, and thus +/// must remain a valid pointer until the hashmap entry is removed or the +/// hashmap is destroyed. +static int hashmap_put(struct hashmap_s *const hashmap, const char *const key, + const unsigned len, void *const value) HASHMAP_USED; + +/// @brief Get an element from the hashmap. +/// @param hashmap The hashmap to get from. +/// @param key The string key to use. +/// @param len The length of the string key. +/// @return The previously set element, or NULL if none exists. +static void *hashmap_get(const struct hashmap_s *const hashmap, + const char *const key, + const unsigned len) HASHMAP_USED; + +/// @brief Remove an element from the hashmap. +/// @param hashmap The hashmap to remove from. +/// @param key The string key to use. +/// @param len The length of the string key. +/// @return On success 0 is returned. +static int hashmap_remove(struct hashmap_s *const hashmap, + const char *const key, + const unsigned len) HASHMAP_USED; + +/// @brief Iterate over all the elements in a hashmap. +/// @param hashmap The hashmap to iterate over. +/// @param f The function pointer to call on each element. +/// @param context The context to pass as the first argument to f. +/// @return If the entire hashmap was iterated then 0 is returned. Otherwise if +/// the callback function f returned non-zero then non-zero is returned. +static int hashmap_iterate(const struct hashmap_s *const hashmap, + int (*f)(void *const context, void *const value), + void *const context) HASHMAP_USED; + +/// @brief Iterate over all the elements in a hashmap. +/// @param hashmap The hashmap to iterate over. +/// @param f The function pointer to call on each element. +/// @param context The context to pass as the first argument to f. +/// @return If the entire hashmap was iterated then 0 is returned. +/// Otherwise if the callback function f returned positive then the positive +/// value is returned. If the callback function returns -1, the current item +/// is removed and iteration continues. +static int hashmap_iterate_pairs(struct hashmap_s *const hashmap, + int (*f)(void *const, struct hashmap_element_s *const), + void *const context) HASHMAP_USED; + +/// @brief Get the size of the hashmap. +/// @param hashmap The hashmap to get the size of. +/// @return The size of the hashmap. +static unsigned +hashmap_num_entries(const struct hashmap_s *const hashmap) HASHMAP_USED; + +/// @brief Destroy the hashmap. +/// @param hashmap The hashmap to destroy. +static void hashmap_destroy(struct hashmap_s *const hashmap) HASHMAP_USED; + +static unsigned hashmap_crc32_helper(const char *const s, + const unsigned len) HASHMAP_USED; +static unsigned +hashmap_hash_helper_int_helper(const struct hashmap_s *const m, + const char *const keystring, + const unsigned len) HASHMAP_USED; +static int hashmap_match_helper(const struct hashmap_element_s *const element, + const char *const key, + const unsigned len) HASHMAP_USED; +static int hashmap_hash_helper(const struct hashmap_s *const m, + const char *const key, const unsigned len, + unsigned *const out_index) HASHMAP_USED; +static int hashmap_rehash_iterator(void *const new_hash, + struct hashmap_element_s *const e) HASHMAP_USED; +static int hashmap_rehash_helper(struct hashmap_s *const m) HASHMAP_USED; + +#if defined(__cplusplus) +} +#endif + +#if defined(__cplusplus) +#define HASHMAP_CAST(type, x) static_cast(x) +#define HASHMAP_PTR_CAST(type, x) reinterpret_cast(x) +#define HASHMAP_NULL NULL +#else +#define HASHMAP_CAST(type, x) ((type)x) +#define HASHMAP_PTR_CAST(type, x) ((type)x) +#define HASHMAP_NULL 0 +#endif + +int hashmap_create(const unsigned initial_size, + struct hashmap_s *const out_hashmap) { + if (0 == initial_size || 0 != (initial_size & (initial_size - 1))) { + return 1; + } + + out_hashmap->data = + HASHMAP_CAST(struct hashmap_element_s *, + calloc(initial_size, sizeof(struct hashmap_element_s))); + if (!out_hashmap->data) { + return 1; + } + + out_hashmap->table_size = initial_size; + out_hashmap->size = 0; + + return 0; +} + +int hashmap_put(struct hashmap_s *const m, const char *const key, + const unsigned len, void *const value) { + unsigned int index; + + /* Find a place to put our value. */ + while (!hashmap_hash_helper(m, key, len, &index)) { + if (hashmap_rehash_helper(m)) { + return 1; + } + } + + /* Set the data. */ + m->data[index].data = value; + m->data[index].key = key; + m->data[index].key_len = len; + m->data[index].in_use = 1; + m->size++; + + return 0; +} + +void *hashmap_get(const struct hashmap_s *const m, const char *const key, + const unsigned len) { + unsigned int curr; + unsigned int i; + + /* Find data location */ + curr = hashmap_hash_helper_int_helper(m, key, len); + + /* Linear probing, if necessary */ + for (i = 0; i < HASHMAP_MAX_CHAIN_LENGTH; i++) { + if (m->data[curr].in_use) { + if (hashmap_match_helper(&m->data[curr], key, len)) { + return m->data[curr].data; + } + } + + curr = (curr + 1) % m->table_size; + } + + /* Not found */ + return HASHMAP_NULL; +} + +int hashmap_remove(struct hashmap_s *const m, const char *const key, + const unsigned len) { + unsigned int i; + unsigned int curr; + + /* Find key */ + curr = hashmap_hash_helper_int_helper(m, key, len); + + /* Linear probing, if necessary */ + for (i = 0; i < HASHMAP_MAX_CHAIN_LENGTH; i++) { + if (m->data[curr].in_use) { + if (hashmap_match_helper(&m->data[curr], key, len)) { + /* Blank out the fields including in_use */ + memset(&m->data[curr], 0, sizeof(struct hashmap_element_s)); + + /* Reduce the size */ + m->size--; + return 0; + } + } + curr = (curr + 1) % m->table_size; + } + + return 1; +} + +int hashmap_iterate(const struct hashmap_s *const m, + int (*f)(void *const, void *const), void *const context) { + unsigned int i; + + /* Linear probing */ + for (i = 0; i < m->table_size; i++) { + if (m->data[i].in_use) { + if (!f(context, m->data[i].data)) { + return 1; + } + } + } + return 0; +} + +int hashmap_iterate_pairs(struct hashmap_s *const hashmap, + int (*f)(void *const, struct hashmap_element_s *const), + void *const context) { + unsigned int i; + struct hashmap_element_s *p; + int r; + + /* Linear probing */ + for (i = 0; i < hashmap->table_size; i++) { + p=&hashmap->data[i]; + if (p->in_use) { + r=f(context, p); + switch (r) + { + case -1: /* remove item */ + memset(p, 0, sizeof(struct hashmap_element_s)); + hashmap->size--; + break; + case 0: /* continue iterating */ + break; + default: /* early exit */ + return 1; + } + } + } + return 0; +} + +void hashmap_destroy(struct hashmap_s *const m) { + free(m->data); + memset(m, 0, sizeof(struct hashmap_s)); +} + +unsigned hashmap_num_entries(const struct hashmap_s *const m) { + return m->size; +} + +unsigned hashmap_crc32_helper(const char *const s, const unsigned len) { + unsigned i; + unsigned crc32val = 0; + +#if defined(HASHMAP_SSE42) + for (i = 0; i < len; i++) { + crc32val = _mm_crc32_u8(crc32val, HASHMAP_CAST(unsigned char, s[i])); + } + + return crc32val; +#else + // Using polynomial 0x11EDC6F41 to match SSE 4.2's crc function. + static const unsigned crc32_tab[] = { + 0x00000000U, 0xF26B8303U, 0xE13B70F7U, 0x1350F3F4U, 0xC79A971FU, + 0x35F1141CU, 0x26A1E7E8U, 0xD4CA64EBU, 0x8AD958CFU, 0x78B2DBCCU, + 0x6BE22838U, 0x9989AB3BU, 0x4D43CFD0U, 0xBF284CD3U, 0xAC78BF27U, + 0x5E133C24U, 0x105EC76FU, 0xE235446CU, 0xF165B798U, 0x030E349BU, + 0xD7C45070U, 0x25AFD373U, 0x36FF2087U, 0xC494A384U, 0x9A879FA0U, + 0x68EC1CA3U, 0x7BBCEF57U, 0x89D76C54U, 0x5D1D08BFU, 0xAF768BBCU, + 0xBC267848U, 0x4E4DFB4BU, 0x20BD8EDEU, 0xD2D60DDDU, 0xC186FE29U, + 0x33ED7D2AU, 0xE72719C1U, 0x154C9AC2U, 0x061C6936U, 0xF477EA35U, + 0xAA64D611U, 0x580F5512U, 0x4B5FA6E6U, 0xB93425E5U, 0x6DFE410EU, + 0x9F95C20DU, 0x8CC531F9U, 0x7EAEB2FAU, 0x30E349B1U, 0xC288CAB2U, + 0xD1D83946U, 0x23B3BA45U, 0xF779DEAEU, 0x05125DADU, 0x1642AE59U, + 0xE4292D5AU, 0xBA3A117EU, 0x4851927DU, 0x5B016189U, 0xA96AE28AU, + 0x7DA08661U, 0x8FCB0562U, 0x9C9BF696U, 0x6EF07595U, 0x417B1DBCU, + 0xB3109EBFU, 0xA0406D4BU, 0x522BEE48U, 0x86E18AA3U, 0x748A09A0U, + 0x67DAFA54U, 0x95B17957U, 0xCBA24573U, 0x39C9C670U, 0x2A993584U, + 0xD8F2B687U, 0x0C38D26CU, 0xFE53516FU, 0xED03A29BU, 0x1F682198U, + 0x5125DAD3U, 0xA34E59D0U, 0xB01EAA24U, 0x42752927U, 0x96BF4DCCU, + 0x64D4CECFU, 0x77843D3BU, 0x85EFBE38U, 0xDBFC821CU, 0x2997011FU, + 0x3AC7F2EBU, 0xC8AC71E8U, 0x1C661503U, 0xEE0D9600U, 0xFD5D65F4U, + 0x0F36E6F7U, 0x61C69362U, 0x93AD1061U, 0x80FDE395U, 0x72966096U, + 0xA65C047DU, 0x5437877EU, 0x4767748AU, 0xB50CF789U, 0xEB1FCBADU, + 0x197448AEU, 0x0A24BB5AU, 0xF84F3859U, 0x2C855CB2U, 0xDEEEDFB1U, + 0xCDBE2C45U, 0x3FD5AF46U, 0x7198540DU, 0x83F3D70EU, 0x90A324FAU, + 0x62C8A7F9U, 0xB602C312U, 0x44694011U, 0x5739B3E5U, 0xA55230E6U, + 0xFB410CC2U, 0x092A8FC1U, 0x1A7A7C35U, 0xE811FF36U, 0x3CDB9BDDU, + 0xCEB018DEU, 0xDDE0EB2AU, 0x2F8B6829U, 0x82F63B78U, 0x709DB87BU, + 0x63CD4B8FU, 0x91A6C88CU, 0x456CAC67U, 0xB7072F64U, 0xA457DC90U, + 0x563C5F93U, 0x082F63B7U, 0xFA44E0B4U, 0xE9141340U, 0x1B7F9043U, + 0xCFB5F4A8U, 0x3DDE77ABU, 0x2E8E845FU, 0xDCE5075CU, 0x92A8FC17U, + 0x60C37F14U, 0x73938CE0U, 0x81F80FE3U, 0x55326B08U, 0xA759E80BU, + 0xB4091BFFU, 0x466298FCU, 0x1871A4D8U, 0xEA1A27DBU, 0xF94AD42FU, + 0x0B21572CU, 0xDFEB33C7U, 0x2D80B0C4U, 0x3ED04330U, 0xCCBBC033U, + 0xA24BB5A6U, 0x502036A5U, 0x4370C551U, 0xB11B4652U, 0x65D122B9U, + 0x97BAA1BAU, 0x84EA524EU, 0x7681D14DU, 0x2892ED69U, 0xDAF96E6AU, + 0xC9A99D9EU, 0x3BC21E9DU, 0xEF087A76U, 0x1D63F975U, 0x0E330A81U, + 0xFC588982U, 0xB21572C9U, 0x407EF1CAU, 0x532E023EU, 0xA145813DU, + 0x758FE5D6U, 0x87E466D5U, 0x94B49521U, 0x66DF1622U, 0x38CC2A06U, + 0xCAA7A905U, 0xD9F75AF1U, 0x2B9CD9F2U, 0xFF56BD19U, 0x0D3D3E1AU, + 0x1E6DCDEEU, 0xEC064EEDU, 0xC38D26C4U, 0x31E6A5C7U, 0x22B65633U, + 0xD0DDD530U, 0x0417B1DBU, 0xF67C32D8U, 0xE52CC12CU, 0x1747422FU, + 0x49547E0BU, 0xBB3FFD08U, 0xA86F0EFCU, 0x5A048DFFU, 0x8ECEE914U, + 0x7CA56A17U, 0x6FF599E3U, 0x9D9E1AE0U, 0xD3D3E1ABU, 0x21B862A8U, + 0x32E8915CU, 0xC083125FU, 0x144976B4U, 0xE622F5B7U, 0xF5720643U, + 0x07198540U, 0x590AB964U, 0xAB613A67U, 0xB831C993U, 0x4A5A4A90U, + 0x9E902E7BU, 0x6CFBAD78U, 0x7FAB5E8CU, 0x8DC0DD8FU, 0xE330A81AU, + 0x115B2B19U, 0x020BD8EDU, 0xF0605BEEU, 0x24AA3F05U, 0xD6C1BC06U, + 0xC5914FF2U, 0x37FACCF1U, 0x69E9F0D5U, 0x9B8273D6U, 0x88D28022U, + 0x7AB90321U, 0xAE7367CAU, 0x5C18E4C9U, 0x4F48173DU, 0xBD23943EU, + 0xF36E6F75U, 0x0105EC76U, 0x12551F82U, 0xE03E9C81U, 0x34F4F86AU, + 0xC69F7B69U, 0xD5CF889DU, 0x27A40B9EU, 0x79B737BAU, 0x8BDCB4B9U, + 0x988C474DU, 0x6AE7C44EU, 0xBE2DA0A5U, 0x4C4623A6U, 0x5F16D052U, + 0xAD7D5351U}; + + for (i = 0; i < len; i++) { + crc32val = crc32_tab[(HASHMAP_CAST(unsigned char, crc32val) ^ + HASHMAP_CAST(unsigned char, s[i]))] ^ + (crc32val >> 8); + } + return crc32val; +#endif +} + +unsigned hashmap_hash_helper_int_helper(const struct hashmap_s *const m, + const char *const keystring, + const unsigned len) { + unsigned key = hashmap_crc32_helper(keystring, len); + + /* Robert Jenkins' 32 bit Mix Function */ + key += (key << 12); + key ^= (key >> 22); + key += (key << 4); + key ^= (key >> 9); + key += (key << 10); + key ^= (key >> 2); + key += (key << 7); + key ^= (key >> 12); + + /* Knuth's Multiplicative Method */ + key = (key >> 3) * 2654435761; + + return key % m->table_size; +} + +int hashmap_match_helper(const struct hashmap_element_s *const element, + const char *const key, const unsigned len) { + return (element->key_len == len) && (0 == memcmp(element->key, key, len)); +} + +int hashmap_hash_helper(const struct hashmap_s *const m, const char *const key, + const unsigned len, unsigned *const out_index) { + unsigned int curr; + unsigned int i; + + /* If full, return immediately */ + if (m->size >= m->table_size) { + return 0; + } + + /* Find the best index */ + curr = hashmap_hash_helper_int_helper(m, key, len); + + /* Linear probing */ + for (i = 0; i < HASHMAP_MAX_CHAIN_LENGTH; i++) { + if (!m->data[curr].in_use) { + *out_index = curr; + return 1; + } + + if (m->data[curr].in_use && + hashmap_match_helper(&m->data[curr], key, len)) { + *out_index = curr; + return 1; + } + + curr = (curr + 1) % m->table_size; + } + + return 0; +} + +int hashmap_rehash_iterator(void *const new_hash, + struct hashmap_element_s *const e) { + int temp=hashmap_put(HASHMAP_PTR_CAST(struct hashmap_s *, new_hash), + e->key, e->key_len, e->data); + if (0table_size; + + struct hashmap_s new_hash; + + int flag = hashmap_create(new_size, &new_hash); + if (0!=flag) { + return flag; + } + + /* copy the old elements to the new table */ + flag = hashmap_iterate_pairs(m, hashmap_rehash_iterator, HASHMAP_PTR_CAST(void *, &new_hash)); + if (0!=flag) { + return flag; + } + + hashmap_destroy(m); + /* put new hash into old hash structure by copying */ + memcpy(m, &new_hash, sizeof(struct hashmap_s)); + + return 0; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#elif defined(__clang__) +#pragma clang diagnostic pop +#endif #endif \ No newline at end of file diff --git a/v2/internal/ffenestri/vec.c b/v2/internal/ffenestri/vec.c new file mode 100644 index 00000000..957d91d1 --- /dev/null +++ b/v2/internal/ffenestri/vec.c @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2014 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See LICENSE for details. + */ + +#include "vec.h" + + +int vec_expand_(char **data, int *length, int *capacity, int memsz) { + if (*length + 1 > *capacity) { + void *ptr; + int n = (*capacity == 0) ? 1 : *capacity << 1; + ptr = realloc(*data, n * memsz); + if (ptr == NULL) return -1; + *data = ptr; + *capacity = n; + } + return 0; +} + + +int vec_reserve_(char **data, int *length, int *capacity, int memsz, int n) { + (void) length; + if (n > *capacity) { + void *ptr = realloc(*data, n * memsz); + if (ptr == NULL) return -1; + *data = ptr; + *capacity = n; + } + return 0; +} + + +int vec_reserve_po2_( + char **data, int *length, int *capacity, int memsz, int n +) { + int n2 = 1; + if (n == 0) return 0; + while (n2 < n) n2 <<= 1; + return vec_reserve_(data, length, capacity, memsz, n2); +} + + +int vec_compact_(char **data, int *length, int *capacity, int memsz) { + if (*length == 0) { + free(*data); + *data = NULL; + *capacity = 0; + return 0; + } else { + void *ptr; + int n = *length; + ptr = realloc(*data, n * memsz); + if (ptr == NULL) return -1; + *capacity = n; + *data = ptr; + } + return 0; +} + + +int vec_insert_(char **data, int *length, int *capacity, int memsz, + int idx +) { + int err = vec_expand_(data, length, capacity, memsz); + if (err) return err; + memmove(*data + (idx + 1) * memsz, + *data + idx * memsz, + (*length - idx) * memsz); + return 0; +} + + +void vec_splice_(char **data, int *length, int *capacity, int memsz, + int start, int count +) { + (void) capacity; + memmove(*data + start * memsz, + *data + (start + count) * memsz, + (*length - start - count) * memsz); +} + + +void vec_swapsplice_(char **data, int *length, int *capacity, int memsz, + int start, int count +) { + (void) capacity; + memmove(*data + start * memsz, + *data + (*length - count) * memsz, + count * memsz); +} + + +void vec_swap_(char **data, int *length, int *capacity, int memsz, + int idx1, int idx2 +) { + unsigned char *a, *b, tmp; + int count; + (void) length; + (void) capacity; + if (idx1 == idx2) return; + a = (unsigned char*) *data + idx1 * memsz; + b = (unsigned char*) *data + idx2 * memsz; + count = memsz; + while (count--) { + tmp = *a; + *a = *b; + *b = tmp; + a++, b++; + } +} diff --git a/v2/internal/ffenestri/vec.h b/v2/internal/ffenestri/vec.h new file mode 100644 index 00000000..2871a09e --- /dev/null +++ b/v2/internal/ffenestri/vec.h @@ -0,0 +1,181 @@ +/** + * Copyright (c) 2014 rxi + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef VEC_H +#define VEC_H + +#include +#include + +#define VEC_VERSION "0.2.1" + + +#define vec_unpack_(v)\ + (char**)&(v)->data, &(v)->length, &(v)->capacity, sizeof(*(v)->data) + + +#define vec_t(T)\ + struct { T *data; int length, capacity; } + + +#define vec_init(v)\ + memset((v), 0, sizeof(*(v))) + + +#define vec_deinit(v)\ + ( free((v)->data),\ + vec_init(v) ) + + +#define vec_push(v, val)\ + ( vec_expand_(vec_unpack_(v)) ? -1 :\ + ((v)->data[(v)->length++] = (val), 0), 0 ) + + +#define vec_pop(v)\ + (v)->data[--(v)->length] + + +#define vec_splice(v, start, count)\ + ( vec_splice_(vec_unpack_(v), start, count),\ + (v)->length -= (count) ) + + +#define vec_swapsplice(v, start, count)\ + ( vec_swapsplice_(vec_unpack_(v), start, count),\ + (v)->length -= (count) ) + + +#define vec_insert(v, idx, val)\ + ( vec_insert_(vec_unpack_(v), idx) ? -1 :\ + ((v)->data[idx] = (val), 0), (v)->length++, 0 ) + + +#define vec_sort(v, fn)\ + qsort((v)->data, (v)->length, sizeof(*(v)->data), fn) + + +#define vec_swap(v, idx1, idx2)\ + vec_swap_(vec_unpack_(v), idx1, idx2) + + +#define vec_truncate(v, len)\ + ((v)->length = (len) < (v)->length ? (len) : (v)->length) + + +#define vec_clear(v)\ + ((v)->length = 0) + + +#define vec_first(v)\ + (v)->data[0] + + +#define vec_last(v)\ + (v)->data[(v)->length - 1] + + +#define vec_reserve(v, n)\ + vec_reserve_(vec_unpack_(v), n) + + +#define vec_compact(v)\ + vec_compact_(vec_unpack_(v)) + + +#define vec_pusharr(v, arr, count)\ + do {\ + int i__, n__ = (count);\ + if (vec_reserve_po2_(vec_unpack_(v), (v)->length + n__) != 0) break;\ + for (i__ = 0; i__ < n__; i__++) {\ + (v)->data[(v)->length++] = (arr)[i__];\ + }\ + } while (0) + + +#define vec_extend(v, v2)\ + vec_pusharr((v), (v2)->data, (v2)->length) + + +#define vec_find(v, val, idx)\ + do {\ + for ((idx) = 0; (idx) < (v)->length; (idx)++) {\ + if ((v)->data[(idx)] == (val)) break;\ + }\ + if ((idx) == (v)->length) (idx) = -1;\ + } while (0) + + +#define vec_remove(v, val)\ + do {\ + int idx__;\ + vec_find(v, val, idx__);\ + if (idx__ != -1) vec_splice(v, idx__, 1);\ + } while (0) + + +#define vec_reverse(v)\ + do {\ + int i__ = (v)->length / 2;\ + while (i__--) {\ + vec_swap((v), i__, (v)->length - (i__ + 1));\ + }\ + } while (0) + + +#define vec_foreach(v, var, iter)\ + if ( (v)->length > 0 )\ + for ( (iter) = 0;\ + (iter) < (v)->length && (((var) = (v)->data[(iter)]), 1);\ + ++(iter)) + + +#define vec_foreach_rev(v, var, iter)\ + if ( (v)->length > 0 )\ + for ( (iter) = (v)->length - 1;\ + (iter) >= 0 && (((var) = (v)->data[(iter)]), 1);\ + --(iter)) + + +#define vec_foreach_ptr(v, var, iter)\ + if ( (v)->length > 0 )\ + for ( (iter) = 0;\ + (iter) < (v)->length && (((var) = &(v)->data[(iter)]), 1);\ + ++(iter)) + + +#define vec_foreach_ptr_rev(v, var, iter)\ + if ( (v)->length > 0 )\ + for ( (iter) = (v)->length - 1;\ + (iter) >= 0 && (((var) = &(v)->data[(iter)]), 1);\ + --(iter)) + + + +int vec_expand_(char **data, int *length, int *capacity, int memsz); +int vec_reserve_(char **data, int *length, int *capacity, int memsz, int n); +int vec_reserve_po2_(char **data, int *length, int *capacity, int memsz, + int n); +int vec_compact_(char **data, int *length, int *capacity, int memsz); +int vec_insert_(char **data, int *length, int *capacity, int memsz, + int idx); +void vec_splice_(char **data, int *length, int *capacity, int memsz, + int start, int count); +void vec_swapsplice_(char **data, int *length, int *capacity, int memsz, + int start, int count); +void vec_swap_(char **data, int *length, int *capacity, int memsz, + int idx1, int idx2); + + +typedef vec_t(void*) vec_void_t; +typedef vec_t(char*) vec_str_t; +typedef vec_t(int) vec_int_t; +typedef vec_t(char) vec_char_t; +typedef vec_t(float) vec_float_t; +typedef vec_t(double) vec_double_t; + +#endif \ No newline at end of file diff --git a/v2/internal/subsystem/event.go b/v2/internal/subsystem/event.go index 202e535a..8e3adf64 100644 --- a/v2/internal/subsystem/event.go +++ b/v2/internal/subsystem/event.go @@ -141,7 +141,7 @@ func (e *Event) notifyListeners(eventName string, message *message.EventMessage) // Get list of event listeners listeners := e.listeners[eventName] if listeners == nil { - e.logger.Trace("No listeners for %s", eventName) + e.logger.Trace("No listeners for event '%s'", eventName) return } diff --git a/v2/internal/subsystem/menu.go b/v2/internal/subsystem/menu.go index e5bce9c3..a651176d 100644 --- a/v2/internal/subsystem/menu.go +++ b/v2/internal/subsystem/menu.go @@ -144,12 +144,12 @@ func (m *Menu) processMenuItem(item *menu.MenuItem) { return } - if item.Id != "" { - if m.menuItems[item.Id] != nil { - m.logger.Error("Menu id '%s' is used by multiple menu items: %s %s", m.menuItems[item.Id].Label, item.Label) + if item.ID != "" { + if m.menuItems[item.ID] != nil { + m.logger.Error("Menu id '%s' is used by multiple menu items: %s %s", m.menuItems[item.ID].Label, item.Label) return } - m.menuItems[item.Id] = item + m.menuItems[item.ID] = item } } @@ -159,7 +159,7 @@ func (m *Menu) notifyListeners(menuid string, menuItem *menu.MenuItem) { // Get list of menu listeners listeners := m.listeners[menuid] if listeners == nil { - m.logger.Trace("No listeners for %s", menuid) + m.logger.Trace("No listeners for MenuItem with ID '%s'", menuid) return } diff --git a/v2/pkg/menu/menuitem.go b/v2/pkg/menu/menuitem.go index 948e8c58..a4b6fad3 100644 --- a/v2/pkg/menu/menuitem.go +++ b/v2/pkg/menu/menuitem.go @@ -1,20 +1,31 @@ package menu +// MenuItem represents a menuitem contained in a menu type MenuItem struct { - Id string `json:"Id,omitempty"` - Label string - Role Role `json:"Role,omitempty"` + // The unique identifier of this menu item + ID string `json:"ID,omitempty"` + // Label is what appears as the menu text + Label string + // Role is a predefined menu type + Role Role `json:"Role,omitempty"` + // Accelerator holds a representation of a key binding Accelerator string `json:"Accelerator,omitempty"` - Type Type - Disabled bool - Hidden bool - Checked bool - SubMenu []*MenuItem `json:"SubMenu,omitempty"` + // Type of MenuItem, EG: Checkbox, Text, Separator, Radio, Submenu + Type Type + // Disabled makes the item unselectable + Disabled bool + // Hidden ensures that the item is not shown in the menu + Hidden bool + // Checked indicates if the item is selected (used by Checkbox and Radio types only) + Checked bool + // Submenu contains a list of menu items that will be shown as a submenu + SubMenu []*MenuItem `json:"SubMenu,omitempty"` } +// Text is a helper to create basic Text menu items func Text(label string, id string) *MenuItem { return &MenuItem{ - Id: id, + ID: id, Label: label, Type: TextType, } @@ -26,3 +37,32 @@ func Separator() *MenuItem { Type: SeparatorType, } } + +// Radio is a helper to create basic Radio menu items +func Radio(label string, id string, selected bool) *MenuItem { + return &MenuItem{ + ID: id, + Label: label, + Type: RadioType, + Checked: selected, + } +} + +// Checkbox is a helper to create basic Checkbox menu items +func Checkbox(label string, id string, checked bool) *MenuItem { + return &MenuItem{ + ID: id, + Label: label, + Type: CheckboxType, + Checked: checked, + } +} + +// SubMenu is a helper to create Submenus +func SubMenu(label string, items []*MenuItem) *MenuItem { + return &MenuItem{ + Label: label, + SubMenu: items, + Type: SubmenuType, + } +} diff --git a/v2/pkg/menu/submenu.go b/v2/pkg/menu/submenu.go deleted file mode 100644 index 815828cb..00000000 --- a/v2/pkg/menu/submenu.go +++ /dev/null @@ -1,10 +0,0 @@ -package menu - -// SubMenu creates a new submenu which may be added to other -// menus -func SubMenu(label string, items []*MenuItem) *MenuItem { - return &MenuItem{ - Label: label, - SubMenu: items, - } -} diff --git a/v2/test/kitchensink/main.go b/v2/test/kitchensink/main.go index 54e6a26d..dd9a7c4b 100644 --- a/v2/test/kitchensink/main.go +++ b/v2/test/kitchensink/main.go @@ -41,11 +41,15 @@ func main() { Hidden: true, }, &menu.MenuItem{ - Id: "checkbox-menu", + ID: "checkbox-menu", Label: "Checkbox Menu", Type: menu.CheckboxType, Checked: true, }, + menu.Separator(), + menu.Radio("Option 1", "option-1", true), + menu.Radio("Option 2", "option-2", false), + menu.Radio("Option 3", "option-3", false), }), })