struct var *add(struct array *args) { struct var *v, *ret; unsigned i; ret = calloc(1, sizeof(struct var)); ret->name = "__add__"; ret->type = ((struct var *)arrobj(args, 0))->type; if (ret->type == V_INT || ret->type == V_DOUB) return arith(args, ADD); else if (ret->type == V_STR) { for (i = 0; i < arrcnt(args); i++) { v = arrobj(args, i); if (!ret->val.sval) ret->val.sval = calloc(1, 1); ret->val.sval = realloc(ret->val.sval, strlen(ret->val.sval) + strlen(v->val.sval) + 1); strcat(ret->val.sval, v->val.sval); } } else if (ret->type == V_ARR) { ret->val.aval = ((struct var *)arrobj(args, 0))->val.aval; for (i = 1; i < arrcnt(args); i++) { v = arrobj(args, i); arradd(ret->val.aval, v); } } return ret; }
struct func *strtofunc(const char *s, struct func *f, struct expr *expr, struct dict *funcs) { char *argstr, *funcname, *tok, *funcpy; struct func *call, *funcarg; struct token *atok; struct var *arg; tok = strdup(s); while (isspace(*tok)) tok++; /* remove leading whitespace */ if (!strpbrk(tok, " ")) { call = dictobj(funcs, tok); if (!call) error(-1, "No such function %s\nLine: %s\n", funcname, expr->expr); call->args = arrnew(NULL); return call; } argstr = strdup(strpbrk(tok, " ")); funcname = strtok(tok, " "); call = dictobj(funcs, funcname); if (!call) error(-1, "No such function %s\nLine: %s\n", funcname, expr->expr); call->args = arrnew(NULL); arg = NULL; atok = gettok(argstr); /* funcname becomes the name of the arg here */ while (atok != NULL) { funcname = atok->tok; switch (atok->type) { case T_LIT: arg = strtolit(atok->tok, f, expr); arg->name = funcname; break; case T_VAR: arg = dictobj(f->scope, funcname); if (!arg) error(-2, "No such variable %s\nLine: %s\n", funcname, expr->expr); break; case T_FUNC: funcpy = strdup(atok->tok); funcpy++; funcpy[strlen(funcpy) - 1] = 0; funcarg = strtofunc(funcpy, f, expr, funcs); if (funcarg->type == F_NORM) arg = exec(funcarg, funcs); else if (funcarg->type == F_SPEC) arg = funcarg->spec(funcarg->args); break; default: atok = atok->next; continue; } arradd(call->args, arg); atok = atok->next; } return call; }
/** * Go from /user/playlist/song to ["user", "playlist", "song"] * return: array_t* of char* */ static array_t *sc_split_path(const char *path) { const char *delim = "/"; array_t *ret = arrnew(); char *dup = strdup(path); char *user = strtok(dup, delim); if (!user) { free(user); return ret; } arradd(ret, (void*)strdup(user)); while (1) { char *next = strtok(NULL, delim); if (!next) break; arradd(ret, (void*)strdup(next)); } free(dup); return ret; }
const array_t *sc_tracks_from_json(cJSON *root) { int len = cJSON_GetArraySize(root); array_t *tracks = arrnew(); for (int i = 0; i < len; i++) { cJSON *track_json = cJSON_GetArrayItem(root, i); sc_track_t *track = sc_track_from_json(track_json); if (track) { arradd(tracks, (void*)track); } } cJSON_Delete(root); return tracks; }
const array_t *sc_get_playlists(sc_t *sc) { char *url = sc_create_url(SC_EUSERS, SC_EPLAYLISTS, sc->username, SC_ARG_LEN(0), SC_DEFAULT_ARG_LIST(sc->client_id)); cJSON *root = http_get_json(url); free(url); array_t *playlists = arrnew(cJSON_GetArraySize(root)); for (int i = 0; i < cJSON_GetArraySize(root); i++) { cJSON *playlist = cJSON_GetArrayItem(root, i); arradd(playlists, (void*)sc_playlist_from_json(playlist)); } cJSON_Delete(root); return playlists; }
sc_playlist_t* sc_playlist_from_json(cJSON *json) { // json array cJSON *tracks_json = cJSON_GetObjectItem(json, "tracks"); array_t *songs = arrnews(cJSON_GetArraySize(tracks_json)); for (int i = 0; i < cJSON_GetArraySize(tracks_json); i++ ) { cJSON *cur = cJSON_GetArrayItem(tracks_json, i); sc_track_t *track = sc_track_from_json(cur); if (track) { arradd(songs, (void*)track); } } char *id_buffer; I_TO_A(cJSON_GetObjectItem(json, "id")->valueint, id_buffer); sc_playlist_t* ret = sc_playlist_new( id_buffer, cJSON_GetObjectItem(json, "title")->valuestring, songs); return ret; }