<commit_before><?php

  /* 
    This file is provided to you under the Apache License,
    Version 2.0 (the "License"); you may not use this file
    except in compliance with the License.  You may obtain
    a copy of the License at
   
      http://www.apache.org/licenses/LICENSE-2.0
   
    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.    
  */

class JiakClient {
    function JiakClient($jiakIP, $jiakPort) {
        $this->jiakIP = $jiakIP;
        $this->jiakPort = $jiakPort;
        $this->JKP = "/jiak/";
    }
    
    function _do_req($method, $uri, $body = "", $header = array()) {
        $ch = curl_init();
        $url = "http://" . $this->jiakIP . ":" . $this->jiakPort . $uri;
        
        // Disable 100-continue header
        $header[] = 'Expect:';
        
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        
        if ($method == "GET") {
            curl_setopt($ch, CURLOPT_HTTPGET, 1);
        
        } else if ($method == "POST") {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        
        } else if ($method == "PUT") {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        
        } else if ($method == "DELETE") {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
        }
        
        $resp = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return array("resp" => $resp, "http_code" => $http_code);
    }
    
    function _expect($status, $data) {
        $http_code = $data['http_code'];
        $resp = $data['resp'];
        if ($http_code != $status) {
            throw new Exception ("_do_req: " . $http_code . ": " . $resp);
        }
        return json_decode($resp, true);
    }
    
    function set_bucket_schema($bucket, $allowed_fields, 
        $required_fields = array(),
        $write_mask = null, $read_mask = null) {
        if ($write_mask == null)
            $write_mask = $allowed_fields;
        if ($read_mask == null)
            $read_mask = $allowed_fields;
        return $this->_expect(204,
            $this->_do_req("PUT", $this->JKP . $bucket,
                json_encode( array (
                    "schema" => array (
                        "allowed_fields" => $allowed_fields,
                        "required_fields" => $required_fields,
                        "write_mask" => $write_mask,
                        "read_mask" => $read_mask))),
                array("Content-type: application/json")));
    }
    
    function bucket_info($bucket) {
        return $this->_expect(200, $this->_do_req("GET", $this->JKP . $bucket));
    }
    
    function store_all($ar) {
        foreach($ar as $o) {
            $this->store($o);
        }
    }
    
    function store($obj) {
        $new_data = $this->_expect(200,
            $this->_do_req("PUT",
                $this->JKP . $obj->bucket . "/" . $obj->key .
                "?returnbody=true",
                $obj->to_json(),
                array("Content-type: application/json;charset=UTF-8")));
        $obj->update($new_data);
        return $obj;
    }
    
    function fetch($bucket, $key) {
        $resp = $this->_do_req("GET", $this->JKP . $bucket . "/" . $key);
        if ($resp['http_code'] == 404) {
            return null;
        }
        $data = $this->_expect(200, $resp);
        return $this->_make_object($data);
    }
    
    function delete($bucket, $key) {
        $resp = $this->_do_req("DELETE", $this->JKP .
            $bucket . "/" . $key);
        $http_code = $resp['http_code'];
        if ($http_code == 404) return false;
        else if ($http_code == 204) return true;
        throw Exception("delete: " . $http_code . ": " . $resp['resp']);
    }
    
    function walk($bucket, $key, $spec) {
        $resp = $this->_do_req("GET", $this->JKP . $bucket . "/" . $key . "/" .
            $this->_convert_walk_spec($spec));
        
        if ($resp['http_code'] == 404) {
            return array();
        }
        
        $data = $this->_expect(200, $resp);
        $objlists = $data['results'];
        return $this->_convert_objlists($objlists);
    }
    
    function _convert_objlists($objlists) {
        $ar = array();
        foreach($objlists as $objlist) {
            foreach($objlist as $obj) {
                $ar[] = $this->_make_object($obj);
            }
        }
        return $ar;
    }
    
    function _make_object($data) {
        $o = new JiakObject($data['bucket'], $data['key']);
        $o->update($data);
        return $o;
    }
    
    function _convert_walk_spec($spec) {
        $s = "/";
        foreach($spec as $el) {
            $s .= $el[0] . "," . $el[1] . "," . $el[2] . ",";
        }
        $s = str_replace(",\n", "", $s."\n");
        return $s;
    }
}

class JiakObject {
    function JiakObject($bucket, $key, 
        $links = array(), $obj = array()) {
        $this->bucket = $bucket;
        $this->key = $key;
        $this->links = $links;
        $this->object = $obj;
    }
    
    function update($data) {
        $this->object = $data['object'];
        $this->links = $data['links'];
        $this->vtag = $data['vtag'];
        $this->lastmod = $data['lastmod'];
        $this->vclock = $data['vclock'];
    }
    
    function set($k, $v) {
        $this->object[$k] = $v;
    }
    
    function get($k) {<commit_msg>url-quote buckets and keys in jiak.php<commit_after><?php

  /* 
    This file is provided to you under the Apache License,
    Version 2.0 (the "License"); you may not use this file
    except in compliance with the License.  You may obtain
    a copy of the License at
   
      http://www.apache.org/licenses/LICENSE-2.0
   
    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.    
  */

class JiakClient {
    function JiakClient($jiakIP, $jiakPort) {
        $this->jiakIP = $jiakIP;
        $this->jiakPort = $jiakPort;
        $this->JKP = "/jiak/";
    }
    
    function _do_req($method, $uri, $body = "", $header = array()) {
        $ch = curl_init();
        $url = "http://" . $this->jiakIP . ":" . $this->jiakPort . $uri;
        
        // Disable 100-continue header
        $header[] = 'Expect:';
        
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
        
        if ($method == "GET") {
            curl_setopt($ch, CURLOPT_HTTPGET, 1);
        
        } else if ($method == "POST") {
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        
        } else if ($method == "PUT") {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT");
            curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
        
        } else if ($method == "DELETE") {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
        }
        
        $resp = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        return array("resp" => $resp, "http_code" => $http_code);
    }
    
    function _expect($status, $data) {
        $http_code = $data['http_code'];
        $resp = $data['resp'];
        if ($http_code != $status) {
            throw new Exception ("_do_req: " . $http_code . ": " . $resp);
        }
        return json_decode($resp, true);
    }
    
    function set_bucket_schema($bucket, $allowed_fields, 
        $required_fields = array(),
        $write_mask = null, $read_mask = null) {
        if ($write_mask == null)
            $write_mask = $allowed_fields;
        if ($read_mask == null)
            $read_mask = $allowed_fields;
        return $this->_expect(204,
            $this->_do_req("PUT", $this->JKP . urlencode($bucket),
                json_encode( array (
                    "schema" => array (
                        "allowed_fields" => $allowed_fields,
                        "required_fields" => $required_fields,
                        "write_mask" => $write_mask,
                        "read_mask" => $read_mask))),
                array("Content-type: application/json")));
    }
    
    function bucket_info($bucket) {
        return $this->_expect(200,
            $this->_do_req("GET", $this->JKP . urlencode($bucket)));
    }
    
    function store_all($ar) {
        foreach($ar as $o) {
            $this->store($o);
        }
    }
    
    function store($obj) {
        $new_data = $this->_expect(200,
            $this->_do_req("PUT",
                $this->JKP . urlencode($obj->bucket) . "/" .
                urlencode($obj->key) . "?returnbody=true",
                $obj->to_json(),
                array("Content-type: application/json;charset=UTF-8")));
        $obj->update($new_data);
        return $obj;
    }
    
    function fetch($bucket, $key) {
        $resp = $this->_do_req("GET",
                    $this->JKP . urlencode($bucket) . "/" . urlencode($key));
        if ($resp['http_code'] == 404) {
            return null;
        }
        $data = $this->_expect(200, $resp);
        return $this->_make_object($data);
    }
    
    function delete($bucket, $key) {
        $resp = $this->_do_req("DELETE", $this->JKP .
                    urlencode($bucket) . "/" . urlencode($key));
        $http_code = $resp['http_code'];
        if ($http_code == 404) return false;
        else if ($http_code == 204) return true;
        throw Exception("delete: " . $http_code . ": " . $resp['resp']);
    }
    
    function walk($bucket, $key, $spec) {
        $resp = $this->_do_req("GET", $this->JKP . urlencode($bucket) .
            "/" . urlencode($key) . "/" . $this->_convert_walk_spec($spec));
        
        if ($resp['http_code'] == 404) {
            return array();
        }
        
        $data = $this->_expect(200, $resp);
        $objlists = $data['results'];
        return $this->_convert_objlists($objlists);
    }
    
    function _convert_objlists($objlists) {
        $ar = array();
        foreach($objlists as $objlist) {
            foreach($objlist as $obj) {
                $ar[] = $this->_make_object($obj);
            }
        }
        return $ar;
    }
    
    function _make_object($data) {
        $o = new JiakObject($data['bucket'], $data['key']);
        $o->update($data);
        return $o;
    }
    
    function _convert_walk_spec($spec) {
        $s = "";
        foreach($spec as $el) {
            $s .= urlencode($el[0]) . "," . urlencode($el[1]) . "," . $el[2] . "/";
        }
        return $s;
    }
}

class JiakObject {
    function JiakObject($bucket, $key, 
        $links = array(), $obj = array()) {
        $this->bucket = $bucket;
        $this->key = $key;
        $this->links = $links;
        $this->object = $obj;
    }
    
    function update($data) {
        $this->object = $data['object'];
        $this->links = $data['links'];
        $this->vtag = $data['vtag'];
        $this->lastmod = $data['lastmod'];
        $this->vclock = $data['vclock'];
    }
    
    function set($k, $v) {
        $this->object[$k] = $v;
    }
    
    function get($k) {
{'fraction_non_alphanumeric': 0.1616509751176866, 'fraction_numerical': 0.006893073301950235, 'mean_word_length': 1.839379474940334, 'pattern_counts': {'":': 6, '<': 5, '<?xml version=': 0, '>': 101, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5588157', 'n_tokens_mistral': 3834, 'n_tokens_neox': 3697, 'n_words': 782}