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; }
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; }
/** * 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; }