473,738 Members | 7,599 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

C data container similar to Perl style key-value array?

I am converting a Perl script over to "C" for a potential open source
project. I need some open source "C" code that will give me the same
functionality of a Perl Style associative array:

someArray["a_key_labe l"] = 6;

I know I can't get the same syntactic sugar as Perl offers, with the usage
of a string as the array key surrounded by square brackets. I just want the
general functionality, that's all. That is, a data container that will
maintain an internal list of key value pairs, with the ability to walk the
keys in sorted order. Also, the container should "auto-insert" a key-value
pair if it doesn't already exist in the container, when a particular key
value pair is referenced.

Do any of you know of any open source "C" code that provides a container
with the same behavior as Perl style arrays? URL's if you got 'em please.

Thanks.
Nov 14 '05 #1
5 3226
"Robert Oschler" <no************ @nospam.com> writes:
I am converting a Perl script over to "C" for a potential open source
project. I need some open source "C" code that will give me the same
functionality of a Perl Style associative array:

someArray["a_key_labe l"] = 6;


I think that's the syntax Awk uses; Perl uses
$someArray{"a_k ey_label"} = 6;
(and refers to the data structure as a "hash", not as an "associativ e
array").

In a Perl hash, the key is a string, and the value can be any
arbitrary scalar value (string, number, reference, undef). You're not
going to get the same functionality in C without substantial syntactic
overhead. The closest C equivalent to a Perl scalar would be a
structure consisting of an enumeration value indicating a type, and a
union of all the types that can be stored in it. The job is simpler
if you can limit the stored values to one type (int, char*, etc.).

Perl, unlike C, also takes care of storage management for you. For
example, if you do:
$foo{"bar"} = "some string value";
$foo{"bar"} = "Some Other String Value";
the second assignment will cause the memory allocated for "some string
value" to be deallocated. In C, you'll have to take care of this
yourself (though a well-designed interface can make it easier).

<OT>
I think some of container classes in the C++ standard library do some
of what you're looking for. You might consider writing a C wrapper
for one of them -- or just implementing the project in C++. If you go
that route, of course, this isn't the place to ask about it.
</OT>

Sorry I don't have a good answer for you, but perhaps I've helped nail
down the question a bit.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #2
In article <BI************ ********@adelph ia.com>,
Robert Oschler <no************ @nospam.com> wrote:
I am converting a Perl script over to "C" for a potential open source
project. I know I can't get the same syntactic sugar as Perl offers, with the usage
of a string as the array key surrounded by square brackets. I just want the
general functionality, that's all. That is, a data container that will
maintain an internal list of key value pairs, with the ability to walk the
keys in sorted order.


There is no built-in ability in perl to walk the keys in sorted
order. If you walk the keys, you will get them in hash order,
and the perl implementers guarantee that the order *will* change
from time to time with different versions of perl. If I recall
correctly, newer versions of perl will use a -different- order
each time unless you use some perl magic.

In order to walk the elements in key-sorted order in perl, you have
to extract the keys, sort the resulting list according to
your sort criteria, and then iterate through the resulting
list
--
Usenet is like a slice of lemon, wrapped around a large gold brick.
Nov 14 '05 #3
ro******@ibd.nr c-cnrc.gc.ca (Walter Roberson) writes:
In article <BI************ ********@adelph ia.com>,
Robert Oschler <no************ @nospam.com> wrote:
I am converting a Perl script over to "C" for a potential open source
project.

I know I can't get the same syntactic sugar as Perl offers, with the usage
of a string as the array key surrounded by square brackets. I just want the
general functionality, that's all. That is, a data container that will
maintain an internal list of key value pairs, with the ability to walk the
keys in sorted order.


There is no built-in ability in perl to walk the keys in sorted
order. If you walk the keys, you will get them in hash order,
and the perl implementers guarantee that the order *will* change
from time to time with different versions of perl. If I recall
correctly, newer versions of perl will use a -different- order
each time unless you use some perl magic.

In order to walk the elements in key-sorted order in perl, you have
to extract the keys, sort the resulting list according to
your sort criteria, and then iterate through the resulting
list


Which, as it turns out, is very easy to do, since "sort" is a built-in
operator:

foreach my $key (sort keys %hash) {
print "$key => $hash{$key}\n";
}

Or, if that's too verbose for you:

map { print "$_ => $hash{$_}\n" } sort keys %hash;

A C version of this would almost certainly be more verbose, with more
explicit code to take care of things that Perl does behind the scenes.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #4
Robert Oschler wrote:
I am converting a Perl script over to "C" for a potential open source
project. I need some open source "C" code that will give me the same
functionality of a Perl Style associative array:

someArray["a_key_labe l"] = 6;

I know I can't get the same syntactic sugar as Perl offers, with the usage
of a string as the array key surrounded by square brackets. I just want the
general functionality, that's all. That is, a data container that will
maintain an internal list of key value pairs, with the ability to walk the
keys in sorted order. Also, the container should "auto-insert" a key-value
pair if it doesn't already exist in the container, when a particular key
value pair is referenced.

Do any of you know of any open source "C" code that provides a container
with the same behavior as Perl style arrays? URL's if you got 'em please.

Thanks.

You will have to do the sorting yourself, however I have attached my
implementation which I use in other projects that works great for this
type of thing (it's actually a configuration parser). Hope this helps.

Joe Estock

--BEGIN config.h:

/* $Id: config.h,v 1.3 2005/03/06 00:23:49 joe Exp $ */

#ifndef _CONFIG_H
#define _CONFIG_H

struct config_settings
{
char **key;
char **value;
};

int config_set(stru ct config_settings *, char *, char *);
int config_set_ex(s truct config_settings *, int, char *);
char *config_get(str uct config_settings *, char *);
char *config_get_ex( struct config_settings *, int);
void rehash_config(s truct config_settings *, char *);
int save_config(str uct config_settings *, char *);
void deinit_config(s truct config_settings *);
void trim(char *);
int init_config(str uct config_settings *, char *);

#endif /* !defined(_CONFI G_H) */

--END config.h

--BEGIN config.c

/* $Id: config.c,v 1.6 2005/03/12 07:59:40 joe Exp $ */

/**
* This is a general configuration parser. Nothing fancy
* is done here and nothing specific to the main configuration
* file is handled here. This file contains the building blocks
* for handling the configuration files by parsing the file and
* splitting up the various configuration settings and their
* values.
*/

#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "config.h"
#include "stdbool.h"

/**
* Sets the specified key with the specified value. If an
* error is encountered, -1 is returned otherwise the index
* of the newly inserted key is returned.
*
* @param config Pointer to a previously malloced config_settings
* @param key Key to change or set
* @param value value for key
* @return -1 on failure, index of item otherwise
*/
int config_set(stru ct config_settings *config, char *key, char *value)
{
unsigned int i;

if(key == NULL || config == NULL || config->key == NULL)
{
return(-1);
}

for(i = 0; config->key[i] != NULL; i++)
{
if(!strcasecmp( config->key[i], key))
{
return(config_s et_ex(config, i, value));
}
}

return(-1);
}

/**
* Sets the specified key with the specified value. If an
* error is encountered, -1 is returned otherwise the index
* of the newly inserted key is returned.
*
* @see config_set()
* @param config Pointer to a previously malloced config_settings
* @param index index of key to change or set
* @param value value for key
* @return -1 on failure, index of item otherwise
*/
int config_set_ex(s truct config_settings *config, int index, char *value)
{
char *tmp;

if((tmp = malloc(strlen(v alue) + 1)) == NULL)
{
perror("malloc" );
return(-1);
}
memset(tmp, '\0', strlen(value) + 1);
strcpy(tmp, value);

free(config->value[index]);
config->value[index] = tmp;

return(index);
}

/**
* Returns the value associated with key
*
* @param config Pointer to a previously malloced config_settings
* @param key Key to retreive value for
* @return Value of key or NULL if nonexistant or empty
*/
char *config_get(str uct config_settings *config, char *key)
{
unsigned int i;

if(key == NULL || config == NULL || config->key == NULL)
{
return(NULL);
}

for(i = 0; config->key[i] != NULL; i++)
{
if(!strcasecmp( config->key[i], key))
{
return(config->value[i]);
}
}

return(NULL);
}

/**
* Returns the value associated with key
*
* @see config_get()
* @param config Pointer to a previously malloced config_settings
* @param index Index of key to retreive value for
* @return Value of key or NULL if nonexistant or empty
*/
char *config_get_ex( struct config_settings *config, int index)
{
return(config->value[index]);
}

/**
* Reloads the configuration file
*
* @see save_config()
* @param config Pointer to a previously malloced config_settings
* @param filename Filename to read configuration data from
*/
void rehash_config(s truct config_settings *config, char *filename)
{
deinit_config(c onfig);
init_config(con fig, filename);
}

/**
* Saves the new configuration parameters to specified file
*
* @see rehash_config()
* @param config Pointer to a previously malloced config_settings
* @param filename Filename to store keys and values in
* @return true on success, false on failure
*/
bool save_config(str uct config_settings *config, char *filename)
{
FILE *fp;
unsigned int i;

if(config == NULL || config->key == NULL || filename == NULL)
{
return(false);
}

if((fp = fopen(filename, "w")) == NULL)
{
return(false);
}

fprintf(fp, "# %s - %s\n",
filename,
"Automatica lly generated by geekbot via save_config");
for(i = 0; config->key[i] != NULL; i++)
{
fprintf(fp, "%s = \"%s\"\n", config->key[i], config->value[i] == NULL
? "" : config->value[i]);
}

fclose(fp);
return(true);
}

/**
* Free up any resources used for specified configuration
*
* @see init_config()
* @param config Pointer to a previously malloced config_settings
*/
void deinit_config(s truct config_settings *config)
{
unsigned int i;

if(config == NULL || (config->key == NULL && config->value == NULL))
{
return;
}

for(i = 0; config->key[i] != NULL; i++)
{
if(config->key[i] != NULL) { free(config->key[i]); }
if(config->value[i] != NULL) { free(config->value[i]); }
}

free(config->key);
free(config->value);
}

/**
* Removes leading and trailing spaces as well as any
* newlines from the end of a string
*
* @param s string to trim
*/
void trim(char *s)
{
unsigned int len = strlen(s);
unsigned int i = 0;

if(len == 0)
{
return;
}

for(i = 0; i < len && isspace(s[i]); i++) ; /* nothing */
if(i > 0)
{
memmove(s, &s[i], strlen(&s[i]) + 1);
}

if((len = strlen(s)) == 0)
{
return;
}

i = len;
while(s[i - 1] == '\r' || s[i - 1] == '\n' || isspace(s[i - 1]))
{
s[i - 1] = '\0';
i--;
}

/*while(s[strlen(s) - 1] == '\r' || s[strlen(s) - 1] == '\n' ||
isspace(s[strlen(s) - 1]))
{
s[strlen(s) - 1] = '\0';
}*/
}

/**
* Initializes the configuration found in specified filename
*
* @param config Pointer to a previously malloced config_settings
* @param filename Filename to read keys and values from
* @return true on success, false on failure
*/
int init_config(str uct config_settings *config, char *filename)
{
FILE *fp;
char buf[2048];
char *tokenptr;
unsigned int i;
char **test;

if(config == NULL)
return(false);

if(!(fp = fopen(filename, "r")))
{
return(false);
}

config->key = malloc(sizeof(c har *) * 1);
config->value = malloc(sizeof(c har *) * 1);
config->key[0] = NULL;
config->value[0] = NULL;

memset(buf, '\0', 2048);

i = 0;
while(!feof(fp) )
{
memset(buf, '\0', 2048);
if(fgets(buf, 2048, fp) == NULL)
break;

trim(buf);

if(buf == NULL || strlen(buf) == 0 || buf[0] == '#')
continue;

tokenptr = strtok(buf, "=");

if(tokenptr != NULL)
{
trim(tokenptr);
if((config->key[i] = malloc(strlen(t okenptr) + 1)) == NULL)
return(false);
memset(config->key[i], '\0', strlen(tokenptr ) + 1);
strcpy(config->key[i], tokenptr);

tokenptr = strtok(NULL, "=");

if(tokenptr != NULL)
{
trim(tokenptr);

if(tokenptr[0] == '"')
memmove(tokenpt r, &tokenptr[1], strlen(&tokenpt r[1]) + 1);

if(tokenptr[strlen(tokenptr ) - 1] == '"')
tokenptr[strlen(tokenptr ) - 1] = '\0';

if(strlen(token ptr) == 0)
{
config->value[i] = NULL;
}
else
{
if((config->value[i] = malloc(strlen(t okenptr) + 1)) == NULL)
return(false);
memset(config->value[i], '\0', strlen(tokenptr ) + 1);
strcpy(config->value[i], tokenptr);
}
}
else
{
config->value[i] = malloc(2);
strcpy(config->value[i], "\0");
}

i++;
if((test = realloc(config->key, sizeof(char *) * (i + 1))) == NULL)
return(false);

config->key = test;
config->key[i] = NULL;

if((test = realloc(config->value, sizeof(char *) * (i + 1))) == NULL)
return(false);

config->value = test;
config->value[i] = NULL;
}
}

fclose(fp);

return(true);
}

--END config.c
Nov 14 '05 #5
Robert Oschler wrote:
I am converting a Perl script over to "C" for a potential open source
project. I need some open source "C" code that will give me the same
functionality of a Perl Style associative array:


As others mentioned, you have to do the sorting yourself, but you might
look at the glib library (part of gtk+, but not dependent on having X
running). It has a number of utility functions for C, that makes C a
lot easier to use.

Jon
----
Learn to program using Linux assembly language
http://www.cafeshops.com/bartlettpublish.8640017
Nov 14 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
2873
by: Ney André de Mello Zunino | last post by:
Hello. The issue is quite known: you have a block-level container holding a set of floated elements and you need that the container's content height take the floated elements' dimensions into consideration. E.g.: <div class="images"> <div class="image"><img src="example1.png" width="160" height="120" alt=""></div> <div class="image"><img src="example2.png" width="160" height="120"
3
1601
by: Colin Young | last post by:
I'm having a bit of a problem with my DataList when I try to update from the user's input. I've included relevant excerpts at the end of this message. In the UpdateCommand code, the "PageLevelTextBox" appears to be found (it isn't returning null), but the Text property is an empty string (""). Am I missing something really obvious? Thanks Colin
0
3112
by: Alex | last post by:
Interested in more .NET stuff visit www.dedicatedsolutions.co.uk The DataList is not as powerful as the DataGrid. It requires more work from you since it has no default data presentation format. However, the DataGrid begins to get very cumbersome as the number of columns of data you present increases. Anything more than half a dozen columns or so and you probably induce horizontal scrolling - a real no-no for me. If you put such a...
2
1912
by: John Holmes | last post by:
I am using radioButton controls in a data repeater and would like to incorporate the 'key' field into the 'id' attribute of the radioButton controls and name them something like: 'rad' + '<%# (string)DataBinder.Eval(Container.DataItem, "ParcelID") %>' + PropType1 I think part of the problem is that intially there is no data bound to this repeater section. The data doesn't get built until the user clicks a button on the form and then...
5
2790
by: tshad | last post by:
Is there a way to carry data that I have already read from the datagrid from page to page? I am looking at my Datagrid that I page through and when the user says get the next page, I have to go to the database to get the next page. Is there a way to use the dataset to allow us to read back and forth in it instead of going back to the database to get it? Thanks,
16
2072
by: Sensei | last post by:
Hi! I'm looking for something similar to the map container, but with a slight modification, a unique key, with multiple assignments to each one. I think some container in the STL has it, but I cannot see it. So I can assign to a key like a map: // pseudo c++ code container<int, int> m;
3
3232
by: David Golightly | last post by:
I'm taking a stab at making CSS sparklines - see http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=0001OR&topic_id=1&topic= <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" > <head> <title>Sparklines</title> <style type="text/css">
1
2430
by: Stephen Barrett | last post by:
I have an application that was originally built with ASP.Net 1.1. We finally got permission to migrate to 2.0. Due to time constraints we migrated the web projects to 2.0 web application projects to minimize required changes initially. I am stuck on a problem using a data grid. I have a usercontrol that has a DataGrid on it. The datagrid has an item template that loads another common user control for every row. I am getting
3
5091
by: jacob navia | last post by:
Abstract: Continuing the discussion about abstract data types, in this discussion group, a string collection data type is presented, patterned after the collection in C# and similar languages (Java). It stores character strings, and resizes itself to accommodate new strings when needed. Interface: ----------
162
10281
by: Sh4wn | last post by:
Hi, first, python is one of my fav languages, and i'll definitely keep developing with it. But, there's 1 one thing what I -really- miss: data hiding. I know member vars are private when you prefix them with 2 underscores, but I hate prefixing my vars, I'd rather add a keyword before it. Python advertises himself as a full OOP language, but why does it miss one of the basic principles of OOP? Will it ever be added to python?
0
8969
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9476
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9335
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
9263
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
8210
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
4570
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
4825
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3279
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2193
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.