Don't run the benchmark by default
[profile/ivi/libxkbcommon.git] / src / alloc.c
index 52d7af2..e782d57 100644 (file)
@@ -23,29 +23,357 @@ OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
 THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
 
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "utils.h"
-#include "xkballoc.h"
-#include "xkbcommon/xkbcommon.h"
-#include "XKBcommonint.h"
-#include <X11/extensions/XKB.h>
+#include "xkb-priv.h"
+#include "alloc.h"
 
 int
-XkbcAllocCompatMap(struct xkb_keymap * xkb, unsigned which, unsigned nSI)
+XkbcAllocClientMap(struct xkb_keymap *keymap, unsigned which,
+                   unsigned nTotalTypes)
+{
+    struct xkb_client_map * map;
+
+    if (!keymap || ((nTotalTypes > 0) && (nTotalTypes < XkbNumRequiredTypes)))
+        return BadValue;
+
+    if (!keymap->map) {
+        map = uTypedCalloc(1, struct xkb_client_map);
+        if (!map)
+            return BadAlloc;
+        keymap->map = map;
+    }
+    else
+        map = keymap->map;
+
+    if ((which & XkbKeyTypesMask) && (nTotalTypes > 0)) {
+        if (!map->types) {
+            map->types = uTypedCalloc(nTotalTypes, struct xkb_key_type);
+            if (!map->types)
+                return BadAlloc;
+
+            map->num_types = 0;
+            map->size_types = nTotalTypes;
+        }
+        else if (map->size_types < nTotalTypes) {
+            struct xkb_key_type *prev_types = map->types;
+
+            map->types = uTypedRealloc(map->types, nTotalTypes,
+                                          struct xkb_key_type);
+            if (!map->types) {
+                free(prev_types);
+                map->num_types = map->size_types = 0;
+                return BadAlloc;
+            }
+
+            map->size_types = nTotalTypes;
+            memset(&map->types[map->num_types], 0,
+                   (map->size_types - map->num_types) * sizeof(struct xkb_key_type));
+        }
+    }
+
+    if (which & XkbKeySymsMask) {
+        if (!map->key_sym_map) {
+            map->key_sym_map = uTypedCalloc(keymap->max_key_code + 1,
+                                            struct xkb_sym_map);
+            if (!map->key_sym_map)
+                return BadAlloc;
+        }
+    }
+
+    if (which & XkbModifierMapMask) {
+        if (!map->modmap) {
+            map->modmap = uTypedCalloc(keymap->max_key_code + 1,
+                                       unsigned char);
+            if (!map->modmap)
+                return BadAlloc;
+        }
+    }
+
+    return Success;
+}
+
+int
+XkbcAllocServerMap(struct xkb_keymap *keymap, unsigned which,
+                   unsigned nNewActions)
+{
+    unsigned i;
+    struct xkb_server_map * map;
+
+    if (!keymap)
+        return BadMatch;
+
+    if (!keymap->server) {
+        map = uTypedCalloc(1, struct xkb_server_map);
+        if (!map)
+            return BadAlloc;
+
+        for (i = 0; i < XkbNumVirtualMods; i++)
+            map->vmods[i] = XkbNoModifierMask;
+
+        keymap->server = map;
+    }
+    else
+        map = keymap->server;
+
+    if (!which)
+        return Success;
+
+    if (!map->explicit) {
+        i = keymap->max_key_code + 1;
+        map->explicit = uTypedCalloc(i, unsigned char);
+        if (!map->explicit)
+            return BadAlloc;
+    }
+
+    if (nNewActions < 1)
+        nNewActions = 1;
+
+    if (!map->acts) {
+        map->acts = uTypedCalloc(nNewActions + 1, union xkb_action);
+        if (!map->acts)
+            return BadAlloc;
+        map->num_acts = 1;
+        map->size_acts = nNewActions + 1;
+    }
+    else if ((map->size_acts - map->num_acts) < (int)nNewActions) {
+        unsigned need;
+        union xkb_action *prev_acts = map->acts;
+
+        need = map->num_acts + nNewActions;
+        map->acts = uTypedRealloc(map->acts, need, union xkb_action);
+        if (!map->acts) {
+            free(prev_acts);
+            map->num_acts = map->size_acts = 0;
+            return BadAlloc;
+        }
+
+        map->size_acts = need;
+        memset(&map->acts[map->num_acts], 0,
+               (map->size_acts - map->num_acts) * sizeof(union xkb_action));
+    }
+
+    if (!map->key_acts) {
+        i = keymap->max_key_code + 1;
+        map->key_acts = uTypedCalloc(i, unsigned short);
+        if (!map->key_acts)
+            return BadAlloc;
+    }
+
+    if (!map->behaviors) {
+        i = keymap->max_key_code + 1;
+        map->behaviors = uTypedCalloc(i, struct xkb_behavior);
+        if (!map->behaviors)
+            return BadAlloc;
+    }
+
+    if (!map->vmodmap) {
+        i = keymap->max_key_code + 1;
+        map->vmodmap = uTypedCalloc(i, uint32_t);
+        if (!map->vmodmap)
+            return BadAlloc;
+    }
+
+    return Success;
+}
+
+int
+XkbcCopyKeyType(struct xkb_key_type * from, struct xkb_key_type * into)
+{
+    int i;
+
+    if (!from || !into)
+        return BadMatch;
+
+    free(into->map);
+    into->map = NULL;
+    free(into->preserve);
+    into->preserve= NULL;
+    for (i = 0; i < into->num_levels; i++)
+        free(UNCONSTIFY(into->level_names[i]));
+    free(into->level_names);
+    into->level_names = NULL;
+
+    *into = *from;
+
+    if (from->map && (into->map_count > 0)) {
+        into->map = uTypedCalloc(into->map_count, struct xkb_kt_map_entry);
+        if (!into->map)
+            return BadAlloc;
+        memcpy(into->map, from->map,
+               into->map_count * sizeof(struct xkb_kt_map_entry));
+    }
+
+    if (from->preserve && (into->map_count > 0)) {
+        into->preserve = uTypedCalloc(into->map_count, struct xkb_mods);
+        if (!into->preserve)
+            return BadAlloc;
+        memcpy(into->preserve, from->preserve,
+               into->map_count * sizeof(struct xkb_mods));
+    }
+
+    if (from->level_names && (into->num_levels > 0)) {
+        into->level_names = uTypedCalloc(into->num_levels, const char *);
+        if (!into->level_names)
+            return BadAlloc;
+        for (i = 0; i < into->num_levels; i++)
+            into->level_names[i] = strdup(from->level_names[i]);
+    }
+
+    return Success;
+}
+
+bool
+XkbcResizeKeySyms(struct xkb_keymap *keymap, xkb_keycode_t key,
+                  unsigned int needed)
+{
+    if (keymap->map->key_sym_map[key].size_syms >= needed)
+        return true;
+
+    keymap->map->key_sym_map[key].syms =
+        uTypedRecalloc(keymap->map->key_sym_map[key].syms,
+                       keymap->map->key_sym_map[key].size_syms,
+                       needed,
+                       xkb_keysym_t);
+    if (!keymap->map->key_sym_map[key].syms) {
+        keymap->map->key_sym_map[key].size_syms = 0;
+        return false;
+    }
+    keymap->map->key_sym_map[key].size_syms = needed;
+
+    return true;
+}
+
+union xkb_action *
+XkbcResizeKeyActions(struct xkb_keymap *keymap, xkb_keycode_t key,
+                     uint32_t needed)
+{
+    xkb_keycode_t i, nActs;
+    union xkb_action *newActs;
+
+    if (needed == 0) {
+        keymap->server->key_acts[key] = 0;
+        return NULL;
+    }
+
+    if (XkbKeyHasActions(keymap, key) &&
+        (XkbKeyGroupsWidth(keymap, key) >= needed))
+        return XkbKeyActionsPtr(keymap, key);
+
+    if (keymap->server->size_acts - keymap->server->num_acts >= (int)needed) {
+        keymap->server->key_acts[key] = keymap->server->num_acts;
+        keymap->server->num_acts += needed;
+
+        return &keymap->server->acts[keymap->server->key_acts[key]];
+    }
+
+    keymap->server->size_acts = keymap->server->num_acts + needed + 8;
+    newActs = uTypedCalloc(keymap->server->size_acts, union xkb_action);
+    if (!newActs)
+        return NULL;
+    newActs[0].type = XkbSA_NoAction;
+    nActs = 1;
+
+    for (i = keymap->min_key_code; i <= keymap->max_key_code; i++) {
+        xkb_keycode_t nKeyActs, nCopy;
+
+        if ((keymap->server->key_acts[i] == 0) && (i != key))
+            continue;
+
+        nCopy = nKeyActs = XkbKeyNumActions(keymap, i);
+        if (i == key) {
+            nKeyActs= needed;
+            if (needed < nCopy)
+                nCopy = needed;
+        }
+
+        if (nCopy > 0)
+            memcpy(&newActs[nActs], XkbKeyActionsPtr(keymap, i),
+                   nCopy * sizeof(union xkb_action));
+        if (nCopy < nKeyActs)
+            memset(&newActs[nActs + nCopy], 0,
+                   (nKeyActs - nCopy) * sizeof(union xkb_action));
+
+        keymap->server->key_acts[i] = nActs;
+        nActs += nKeyActs;
+    }
+
+    free(keymap->server->acts);
+    keymap->server->acts = newActs;
+    keymap->server->num_acts = nActs;
+
+    return &keymap->server->acts[keymap->server->key_acts[key]];
+}
+
+void
+XkbcFreeClientMap(struct xkb_keymap *keymap)
+{
+    struct xkb_client_map * map;
+    struct xkb_key_type * type;
+    xkb_keycode_t key;
+    int i;
+
+    if (!keymap || !keymap->map)
+        return;
+
+    map = keymap->map;
+
+    for (i = 0, type = map->types; i < map->num_types && type; i++, type++) {
+        int j;
+        free(type->map);
+        free(type->preserve);
+        for (j = 0; j < type->num_levels; j++)
+            free(UNCONSTIFY(type->level_names[j]));
+        free(type->level_names);
+        free(UNCONSTIFY(type->name));
+    }
+    free(map->types);
+
+    if (map->key_sym_map) {
+        for (key = keymap->min_key_code; key < keymap->max_key_code; key++) {
+            free(map->key_sym_map[key].sym_index);
+            free(map->key_sym_map[key].num_syms);
+            free(map->key_sym_map[key].syms);
+        }
+    }
+    free(map->key_sym_map);
+
+    free(map->modmap);
+    free(keymap->map);
+    keymap->map = NULL;
+}
+
+void
+XkbcFreeServerMap(struct xkb_keymap *keymap)
+{
+    struct xkb_server_map * map;
+
+    if (!keymap || !keymap->server)
+        return;
+
+    map = keymap->server;
+
+    free(map->explicit);
+    free(map->key_acts);
+    free(map->acts);
+    free(map->behaviors);
+    free(map->vmodmap);
+    free(keymap->server);
+    keymap->server = NULL;
+}
+
+int
+XkbcAllocCompatMap(struct xkb_keymap *keymap, unsigned nSI)
 {
     struct xkb_compat_map * compat;
     struct xkb_sym_interpret *prev_interpret;
 
-    if (!xkb)
+    if (!keymap)
         return BadMatch;
 
-    if (xkb->compat) {
-        if (xkb->compat->size_si >= nSI)
+    if (keymap->compat) {
+        if (keymap->compat->size_si >= nSI)
             return Success;
 
-        compat = xkb->compat;
+        compat = keymap->compat;
         compat->size_si = nSI;
         if (!compat->sym_interpret)
             compat->num_si = 0;
@@ -77,48 +405,49 @@ XkbcAllocCompatMap(struct xkb_keymap * xkb, unsigned which, unsigned nSI)
     compat->size_si = nSI;
     compat->num_si = 0;
     memset(&compat->groups[0], 0, XkbNumKbdGroups * sizeof(struct xkb_mods));
-    xkb->compat = compat;
+    keymap->compat = compat;
 
     return Success;
 }
 
 
 static void
-XkbcFreeCompatMap(struct xkb_keymap * xkb)
+XkbcFreeCompatMap(struct xkb_keymap *keymap)
 {
     struct xkb_compat_map * compat;
 
-    if (!xkb || !xkb->compat)
+    if (!keymap || !keymap->compat)
         return;
 
-    compat = xkb->compat;
+    compat = keymap->compat;
 
     free(compat->sym_interpret);
     free(compat);
-    xkb->compat = NULL;
+    keymap->compat = NULL;
 }
 
 int
-XkbcAllocNames(struct xkb_keymap * xkb, unsigned which, unsigned nTotalAliases)
+XkbcAllocNames(struct xkb_keymap *keymap, unsigned which,
+               unsigned nTotalAliases)
 {
     struct xkb_names * names;
 
-    if (!xkb)
+    if (!keymap)
         return BadMatch;
 
-    if (!xkb->names) {
-        xkb->names = uTypedCalloc(1, struct xkb_names);
-        if (!xkb->names)
+    if (!keymap->names) {
+        keymap->names = uTypedCalloc(1, struct xkb_names);
+        if (!keymap->names)
             return BadAlloc;
     }
-    names = xkb->names;
+    names = keymap->names;
 
-    if ((which & XkbKTLevelNamesMask) && xkb->map && xkb->map->types) {
+    if ((which & XkbKTLevelNamesMask) && keymap->map && keymap->map->types) {
         int i;
         struct xkb_key_type * type;
 
-        type = xkb->map->types;
-        for (i = 0; i < xkb->map->num_types; i++, type++) {
+        type = keymap->map->types;
+        for (i = 0; i < keymap->map->num_types; i++, type++) {
             if (!type->level_names) {
                 type->level_names = uTypedCalloc(type->num_levels, const char *);
                 if (!type->level_names)
@@ -128,10 +457,8 @@ XkbcAllocNames(struct xkb_keymap * xkb, unsigned which, unsigned nTotalAliases)
     }
 
     if ((which & XkbKeyNamesMask) && !names->keys) {
-        if (!xkb_keymap_keycode_range_is_legal(xkb))
-            return BadMatch;
-
-        names->keys = uTypedCalloc(xkb->max_key_code + 1, struct xkb_key_name);
+        names->keys = uTypedCalloc(keymap->max_key_code + 1,
+                                   struct xkb_key_name);
         if (!names->keys)
             return BadAlloc;
     }
@@ -163,17 +490,17 @@ XkbcAllocNames(struct xkb_keymap * xkb, unsigned which, unsigned nTotalAliases)
 }
 
 static void
-XkbcFreeNames(struct xkb_keymap * xkb)
+XkbcFreeNames(struct xkb_keymap *keymap)
 {
     struct xkb_names * names;
     struct xkb_client_map * map;
     int i;
 
-    if (!xkb || !xkb->names)
+    if (!keymap || !keymap->names)
         return;
 
-    names = xkb->names;
-    map = xkb->map;
+    names = keymap->names;
+    map = keymap->map;
 
     if (map && map->types) {
         struct xkb_key_type * type = map->types;
@@ -197,50 +524,48 @@ XkbcFreeNames(struct xkb_keymap * xkb)
     free(names->keys);
     free(names->key_aliases);
     free(names);
-    xkb->names = NULL;
+    keymap->names = NULL;
 }
 
 int
-XkbcAllocControls(struct xkb_keymap * xkb, unsigned which)
+XkbcAllocControls(struct xkb_keymap *keymap)
 {
-    if (!xkb)
+    if (!keymap)
         return BadMatch;
 
-    if (!xkb->ctrls) {
-        xkb->ctrls = uTypedCalloc(1, struct xkb_controls);
-        if (!xkb->ctrls)
+    if (!keymap->ctrls) {
+        keymap->ctrls = uTypedCalloc(1, struct xkb_controls);
+        if (!keymap->ctrls)
             return BadAlloc;
     }
 
-    if (!xkb->ctrls->per_key_repeat) {
-        xkb->ctrls->per_key_repeat = uTypedCalloc(xkb->max_key_code << 3,
-                                                  unsigned char);
-        if (!xkb->ctrls->per_key_repeat)
-            return BadAlloc;
-    }
+    keymap->ctrls->per_key_repeat = uTypedCalloc(keymap->max_key_code >> 3,
+                                                 unsigned char);
+    if (!keymap->ctrls->per_key_repeat)
+        return BadAlloc;
 
     return Success;
 }
 
 static void
-XkbcFreeControls(struct xkb_keymap * xkb)
+XkbcFreeControls(struct xkb_keymap *keymap)
 {
-    if (xkb && xkb->ctrls) {
-        free(xkb->ctrls->per_key_repeat);
-        free(xkb->ctrls);
-        xkb->ctrls = NULL;
+    if (keymap && keymap->ctrls) {
+        free(keymap->ctrls->per_key_repeat);
+        free(keymap->ctrls);
+        keymap->ctrls = NULL;
     }
 }
 
 int
-XkbcAllocIndicatorMaps(struct xkb_keymap * xkb)
+XkbcAllocIndicatorMaps(struct xkb_keymap *keymap)
 {
-    if (!xkb)
+    if (!keymap)
         return BadMatch;
 
-    if (!xkb->indicators) {
-        xkb->indicators = uTypedCalloc(1, struct xkb_indicator);
-        if (!xkb->indicators)
+    if (!keymap->indicators) {
+        keymap->indicators = uTypedCalloc(1, struct xkb_indicator);
+        if (!keymap->indicators)
             return BadAlloc;
     }
 
@@ -248,42 +573,41 @@ XkbcAllocIndicatorMaps(struct xkb_keymap * xkb)
 }
 
 static void
-XkbcFreeIndicatorMaps(struct xkb_keymap * xkb)
+XkbcFreeIndicatorMaps(struct xkb_keymap *keymap)
 {
-    if (xkb) {
-        free(xkb->indicators);
-        xkb->indicators = NULL;
+    if (keymap) {
+        free(keymap->indicators);
+        keymap->indicators = NULL;
     }
 }
 
 struct xkb_keymap *
-XkbcAllocKeyboard(struct xkb_context *context)
+XkbcAllocKeyboard(struct xkb_context *ctx)
 {
-    struct xkb_keymap *xkb;
+    struct xkb_keymap *keymap;
 
-    xkb = uTypedCalloc(1, struct xkb_keymap);
-    if (!xkb)
+    keymap = uTypedCalloc(1, struct xkb_keymap);
+    if (!keymap)
         return NULL;
 
-    xkb->refcnt = 1;
-    xkb_context_ref(context);
-    xkb->context = context;
+    keymap->refcnt = 1;
+    keymap->ctx = xkb_context_ref(ctx);
 
-    return xkb;
+    return keymap;
 }
 
 void
-XkbcFreeKeyboard(struct xkb_keymap * xkb)
+XkbcFreeKeyboard(struct xkb_keymap *keymap)
 {
-    if (!xkb)
+    if (!keymap)
         return;
 
-    XkbcFreeClientMap(xkb);
-    XkbcFreeServerMap(xkb);
-    XkbcFreeCompatMap(xkb);
-    XkbcFreeIndicatorMaps(xkb);
-    XkbcFreeNames(xkb);
-    XkbcFreeControls(xkb);
-    xkb_context_unref(xkb->context);
-    free(xkb);
+    XkbcFreeClientMap(keymap);
+    XkbcFreeServerMap(keymap);
+    XkbcFreeCompatMap(keymap);
+    XkbcFreeIndicatorMaps(keymap);
+    XkbcFreeNames(keymap);
+    XkbcFreeControls(keymap);
+    xkb_context_unref(keymap->ctx);
+    free(keymap);
 }