/** * [List] + [List] * * Returns a new list, containing elements of itself and the other * list. * * In other languages: * Dutch: [Reeks] + [Reeks] | Geeft de reeks die bestaat uit de samenvoeging van gegeven reeksen. */ ctr_object* ctr_array_add(ctr_object* myself, ctr_argument* argumentList) { ctr_object* otherArray = argumentList->object; ctr_object* newArray = ctr_array_new(CtrStdArray, NULL); int i; for(i = myself->value.avalue->tail; i<myself->value.avalue->head; i++) { ctr_argument* pushArg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); ctr_argument* elnumArg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); ctr_object* elnum = ctr_build_number_from_float((ctr_number) i); elnumArg->object = elnum; pushArg->object = ctr_array_get(myself, elnumArg); ctr_array_push(newArray, pushArg); ctr_heap_free( elnumArg ); ctr_heap_free( pushArg ); } if (otherArray->info.type == CTR_OBJECT_TYPE_OTARRAY) { for(i = otherArray->value.avalue->tail; i<otherArray->value.avalue->head; i++) { ctr_argument* pushArg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); ctr_argument* elnumArg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); ctr_object* elnum = ctr_build_number_from_float((ctr_number) i); elnumArg->object = elnum; pushArg->object = ctr_array_get(otherArray, elnumArg); ctr_array_push(newArray, pushArg); ctr_heap_free( elnumArg ); ctr_heap_free( pushArg ); } } return newArray; }
/** * @internal * * Returns an array from the request, either for GET, POST or COOKIE. */ ctr_object* ctr_request_array(ctr_object* myself, ctr_argument* argumentList, CGI_varlist* varlist) { ctr_object* cgiVarObject; ctr_object* list; char* cgiVar; const CGI_value* value; char* val; ctr_argument* arg; int i = 0; list = ctr_array_new(CtrStdArray, NULL); cgiVarObject = ctr_internal_cast2string(argumentList->object); cgiVar = ctr_heap_allocate_cstring( cgiVarObject ); value = CGI_lookup_all(varlist, (const char*)cgiVar); ctr_heap_free( cgiVar ); if (value == NULL) { return list; } for (i = 0; value[i] != 0; i++) { arg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); val = (char*) value[i]; arg->object = ctr_build_string_from_cstring(val); ctr_array_push(list, arg); ctr_heap_free( arg ); } return list; }
ctr_object* ctr_json_create_object(json_t* root, ctr_object* gt) { switch(json_typeof(root)) { case JSON_OBJECT: { ctr_object* sub = ctr_internal_create_object(CTR_OBJECT_TYPE_OTOBJECT); ctr_set_link_all(sub, gt); // size_t size; const char *key; json_t *value; ctr_argument* argl = ctr_heap_allocate(sizeof(*argl)); argl->next = ctr_heap_allocate(sizeof(*argl)); // size = json_object_size(root); json_object_foreach(root, key, value) { char* k = (char*)key; ctr_object* ko = ctr_build_string_from_cstring(k); ctr_object* vo = ctr_json_create_object(value, gt); argl->object = vo; argl->next->object = ko; sub = ctr_map_put(sub, argl); } ctr_heap_free(argl->next); ctr_heap_free(argl); return sub; } case JSON_ARRAY: { ctr_object* arr = ctr_array_new(CtrStdArray, NULL); ctr_argument* arg = ctr_heap_allocate(sizeof(ctr_argument)); size_t i; size_t size = json_array_size(root); for (i = 0; i < size; i++) { arg->object = ctr_json_create_object(json_array_get(root, i), gt); ctr_array_push(arr, arg); } ctr_heap_free(arg); return arr; } case JSON_STRING: { ctr_object* str = ctr_build_string((char*)json_string_value(root), json_string_length(root)); return str; } case JSON_INTEGER: { return ctr_build_number_from_float(json_integer_value(root)); } case JSON_REAL: { return ctr_build_number_from_float(json_real_value(root)); } case JSON_FALSE: { return ctr_build_bool(0); } case JSON_TRUE: { return ctr_build_bool(1); } case JSON_NULL: { return ctr_build_nil(); } default: { CtrStdFlow = ctr_build_string_from_cstring("Unrecognized JSON type"); return CtrStdNil; } }
/** * [List] fill: [Number] with: [Object] * * Fills the list with the specified number of objects. * * Usage: * * ☞ a := List new fill: 42 with: 'x'. * * In other languages: * Dutch: [Reeks] vul: [Getal] met: [Object] * Vult de reeks op met een gespecificeerd aantal elementen. */ ctr_object* ctr_array_fill( ctr_object* myself, ctr_argument* argumentList ) { size_t n; int i; ctr_argument* newArgumentList; n = ctr_internal_cast2number( argumentList->object )->value.nvalue; newArgumentList = ctr_heap_allocate( sizeof(ctr_argument) ); newArgumentList->object = argumentList->next->object; for(i = 0; i < n; i ++ ) { ctr_array_push( myself, newArgumentList ); } ctr_heap_free(newArgumentList); return myself; }
/** * [List] copy * * Copies the list. The list object will answer this message by * returning a shallow copy of itself. This means that the values in the * newly returned list can be replaced or deleted without affecting * the original one. However, modifying the values in the list will * still cause their counterparts in the original list to be modified * as well. * In the example we replace the first item (1) in b with 999. * The first element in a will still be 1 though because we have created * copy b by sending the message 'copy' to a and assiging the result * to b. * * Usage: * * ☞ a := List ← 1 ; 2 ; 3. * ☞ b := a copy. * b put: 999 at: 1. * * In other languages: * Dutch: [Reeks] kopieer | Maakt een kopie van de reeks. */ ctr_object* ctr_array_copy(ctr_object* myself, ctr_argument* argumentList) { ctr_size i = 0; ctr_object* copy = ctr_array_new( CtrStdArray, argumentList ); ctr_argument* arg = ctr_heap_allocate(sizeof(ctr_argument)); ctr_argument* index = ctr_heap_allocate( sizeof( ctr_argument ) ); for(i = myself->value.avalue->tail; i<myself->value.avalue->head; i++) { index->object = ctr_build_number_from_float((ctr_number) i); arg->object = ctr_array_get( myself, index ); ctr_array_push( copy, arg ); } ctr_heap_free( arg ); ctr_heap_free( index ); return copy; }
/** * [Map] values * * Returns an array containing all the keys in the map. * The order of the keys is undefined. Use the sort message * to enforce a specific order. * * Usage: * * ☞ city := List ← 'London' ; 'Paris' ; 'Berlin'. * ☞ temperature := List ← '15' ; '16' ; '15'. * * ☞ weather := temperature by: city. * temperatures := weather values sort: { * :a :b ↲ (a compare: b). * }. * * In other languages: * Dutch: [Lijst] waarden | Geeft alle waarden uit de lijst als een reeks. */ ctr_object* ctr_map_values(ctr_object* myself, ctr_argument* argumentList) { ctr_object* list; ctr_mapitem* m; ctr_argument* element; list = ctr_array_new( CtrStdArray, argumentList ); m = myself->properties->head; element = ctr_heap_allocate( sizeof( ctr_argument ) ); while( m ) { element->object = m->value; ctr_array_push( list, element ); m = m->next; } ctr_heap_free( element ); return list; }
/** * StringSplit * * Converts a string to an array by splitting the string using * the specified delimiter (also a string). */ ctr_object* ctr_string_split(ctr_object* myself, ctr_argument* argumentList) { char* str = myself->value.svalue->value; long len = myself->value.svalue->vlen; ctr_object* delimObject = ctr_internal_cast2string(argumentList->object); char* dstr = delimObject->value.svalue->value; long dlen = delimObject->value.svalue->vlen; ctr_argument* arg; char* elem; ctr_object* arr = ctr_array_new(CtrStdArray, NULL); long i; long j = 0; char* buffer = malloc(sizeof(char)*len); for(i=0; i<len; i++) { buffer[j] = str[i]; j++; if (ctr_internal_memmem(buffer, j, dstr, dlen, 0)!=NULL) { elem = malloc(sizeof(char)*(j-dlen)); memcpy(elem,buffer,j-dlen); arg = malloc(sizeof(ctr_argument)); arg->object = ctr_build_string(elem, j-dlen); ctr_array_push(arr, arg); free(arg); j=0; } } if (j>0) { elem = malloc(sizeof(char)*j); memcpy(elem,buffer,j); arg = malloc(sizeof(ctr_argument)); arg->object = ctr_build_string(elem, j); ctr_array_push(arr, arg); free(arg); } free(buffer); return arr; }
/** * [Array] from: [Begin] to: [End] * * Copies part of an array indicated by from and to and * returns a new array consisting of a copy of this region. */ ctr_object* ctr_array_from_to(ctr_object* myself, ctr_argument* argumentList) { ctr_argument* pushArg; ctr_argument* elnumArg; ctr_object* elnum; ctr_object* startElement = ctr_internal_cast2number(argumentList->object); ctr_object* count = ctr_internal_cast2number(argumentList->next->object); int start = (int) startElement->value.nvalue; int len = (int) count->value.nvalue; int i = 0; ctr_object* newArray = ctr_array_new(CtrStdArray, NULL); for(i = start; i < start + len; i++) { pushArg = CTR_CREATE_ARGUMENT(); elnumArg = CTR_CREATE_ARGUMENT(); elnum = ctr_build_number_from_float((ctr_number) i); elnumArg->object = elnum; pushArg->object = ctr_array_get(myself, elnumArg); ctr_array_push(newArray, pushArg); } return newArray; }
/** * [List] from: [Begin] length: [End] * * Copies part of an array indicated by from and to and * returns a new array consisting of a copy of this region. * * In other languages: * Dutch: [Reeks] van: [Getal] lengte: [Getal] | Geeft subreeks. */ ctr_object* ctr_array_from_length(ctr_object* myself, ctr_argument* argumentList) { ctr_argument* pushArg; ctr_argument* elnumArg; ctr_object* elnum; ctr_object* startElement = ctr_internal_cast2number(argumentList->object); ctr_object* count = ctr_internal_cast2number(argumentList->next->object); int start = (int) startElement->value.nvalue; int len = (int) count->value.nvalue; int i = 0; ctr_object* newArray = ctr_array_new(CtrStdArray, NULL); for(i = start; i < start + len; i++) { pushArg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); elnumArg = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); elnum = ctr_build_number_from_float((ctr_number) i); elnumArg->object = elnum; pushArg->object = ctr_array_get(myself, elnumArg); ctr_array_push(newArray, pushArg); ctr_heap_free( elnumArg ); ctr_heap_free( pushArg ); } return newArray; }
/** * [List] put: [Object] at: [Number] * * Puts an object (which can be anything) in the list * at the specified position. * The list will be automatically expanded if the position number * is higher than the maximum of the list. * * Usage: * * ☞ fruits := List new. * ☞ fruits put: 'apples' at: 5. * * In other languages: * Dutch: [Reeks] zet: [Object] bij: [Getal] * Plaatst het object op de aangegeven positie in de reeks. */ ctr_object* ctr_array_put(ctr_object* myself, ctr_argument* argumentList) { ctr_object* putValue = argumentList->object; ctr_object* putIndex = ctr_internal_cast2number(argumentList->next->object); ctr_size putIndexNumber; ctr_size head; ctr_size tail; if (putIndex->value.nvalue < 0) { CtrStdFlow = ctr_build_string_from_cstring( CTR_ERR_BOUNDS ); CtrStdFlow->info.sticky = 1; return myself; } head = (ctr_size) myself->value.avalue->head; tail = (ctr_size) myself->value.avalue->tail; putIndexNumber = (ctr_size) putIndex->value.nvalue; if (head <= putIndexNumber) { ctr_size j; for(j = head; j <= putIndexNumber; j++) { ctr_argument* argument; argument = (ctr_argument*) ctr_heap_allocate( sizeof( ctr_argument ) ); argument->object = CtrStdNil; ctr_array_push(myself, argument); ctr_heap_free( argument ); } myself->value.avalue->head = putIndexNumber + 1; } if (putIndexNumber < tail) { ctr_size j; for(j = tail; j > putIndexNumber; j--) { *(myself->value.avalue->elements + j) = CtrStdNil; } myself->value.avalue->tail = putIndexNumber; } *(myself->value.avalue->elements + putIndexNumber) = putValue; return myself; }
/** * [Array] put: [Element] at: [Index] * * Puts a value in the array at the specified index. * Array will be automatically expanded if the index is higher than * the maximum index of the array. * * Usage: * * fruits := Array new. * fruits put: 'apples' at: 5. */ ctr_object* ctr_array_put(ctr_object* myself, ctr_argument* argumentList) { ctr_object* putValue = argumentList->object; ctr_object* putIndex = ctr_internal_cast2number(argumentList->next->object); ctr_size putIndexNumber; ctr_size head; ctr_size tail; if (putIndex->value.nvalue < 0) { CtrStdError = ctr_build_string_from_cstring("Index out of bounds.\0"); return myself; } head = (ctr_size) myself->value.avalue->head; tail = (ctr_size) myself->value.avalue->tail; putIndexNumber = (ctr_size) putIndex->value.nvalue; if (head <= putIndexNumber) { ctr_size j; for(j = head; j <= putIndexNumber; j++) { ctr_argument* argument; argument = CTR_CREATE_ARGUMENT(); argument->object = CtrStdNil; ctr_array_push(myself, argument); } myself->value.avalue->head = putIndexNumber + 1; } if (putIndexNumber < tail) { ctr_size j; for(j = tail; j > putIndexNumber; j--) { *(myself->value.avalue->elements + j) = CtrStdNil; } myself->value.avalue->tail = putIndexNumber; } *(myself->value.avalue->elements + putIndexNumber) = putValue; return myself; }
/** * [List] ← [Element1] ; [Element2] ; ... * * Creates a new instance of a list and initializes this * array with a first element, useful for literal-like List * notations. In the example we create a new list consisting * of the numbers 1, 2 and 3. * * Usage: * * a := List ← 1 ; 2 ; 3. * * In other languages: * Dutch: [Reeks] ← [Element1] ; [Element2] ; ... | De pijl maakt een nieuwe reeks en voegt het eerste * element direct toe, opvolgende elementen kunnen worden gescheiden door puntkomma's (;), hiermee * voegt men telkens een nieuw element toe aan de reeks. */ ctr_object* ctr_array_new_and_push(ctr_object* myclass, ctr_argument* argumentList) { ctr_object* s = ctr_array_new(myclass, NULL); return ctr_array_push(s, argumentList); }