|
| 1 | +/****************************************************************************** |
| 2 | + * |
| 3 | + * Copyright 2021 Nikolay Shaplov (Postgres Professional) |
| 4 | + * |
| 5 | + * Licensed under the Apache License, Version 2.0 (the "License"); |
| 6 | + * you may not use this file except in compliance with the License. |
| 7 | + * You may obtain a copy of the License at |
| 8 | + * |
| 9 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | + * |
| 11 | + * Unless required by applicable law or agreed to in writing, software |
| 12 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | + * See the License for the specific language governing permissions and |
| 15 | + * limitations under the License. |
| 16 | + * |
| 17 | + ******************************************************************************/ |
| 18 | + |
| 19 | +#include<string.h> |
| 20 | + |
| 21 | +#include<exception> |
| 22 | +#include<string> |
| 23 | +#include<cstdlib> |
| 24 | +#include<vector> |
| 25 | +#include<cassert> |
| 26 | +#defineWANT_TEST_EXTRAS |
| 27 | +#include<tap++/tap++.h> |
| 28 | + |
| 29 | +#include"blobstamper/blobstamper.h" |
| 30 | +#include"blobstamper/dict.h" |
| 31 | + |
| 32 | +#include"test-chars-stamps.h" |
| 33 | + |
| 34 | +usingnamespaceTAP; |
| 35 | + |
| 36 | +char short_sample[]="1234567"; |
| 37 | +char longer_sample[]="z1234567*89abcde&fghijklmnopqrstuvwxyzAB%CDEFGHIJKLMNOPQRSTUVWXYZ!"; |
| 38 | +unsigned char bin_sample[]= {49, 22, 152, 226, 89, 119, 247, 115, 43, 42, 243, 71, 234, 231, 91, 35, 78, 108, 115, 39, 181, 248, 211, 52, 47, 94, 60, 237, 18, 39, 148, 62, 205, 214, 156, 184, 18, 201, 84, 183, 74, 134, 94, 72, 14, 116, 145, 109, 1, 230, 17, 95, 154, 100, 60, 15, 12, 102, 20, 115, 35, 183, 47, 176, 78, 176, 189, 113, 131, 93, 206, 62, 158, 166, 131, 95, 232, 217, 32, 171, 87, 31, 172, 160, 66, 160, 222, 134, 253, 1, 7, 191, 91, 125, 81, 148, 41, 46, 38, 171, 83, 215, 79, 34, 23, 215, 183, 118, 236, 191, 59, 160, 135, 58, 32, 199, 170, 183, 213, 53, 162, 138, 178, 118, 23, 202, 133, 8, 192, 183, 195, 199, 250, 29, 230, 34, 159, 10, 145, 74, 121, 85, 168, 204, 192, 25, 232, 88, 85, 76, 61, 168, 247, 128, 141, 176, 112, 113, 100, 201, 82, 183, 219, 236, 226, 171, 85, 97, 160, 1, 50, 250, 161, 51, 61, 220, 167, 227, 195, 17, 164, 211, 189, 130, 52, 167, 169, 42, 17, 29, 95, 15, 178, 165, 110, 87, 149, 214, 55, 12, 236, 138, 2, 245, 158, 84, 140, 24, 225, 169, 115, 16, 130, 253, 237, 182, 95, 109, 4, 28, 249, 4, 254, 166, 62, 107, 228, 113, 130, 127, 70, 79, 140, 41, 84, 218, 134, 146, 88, 65, 24, 174, 252, 253, 226, 214, 22, 92, 248, 14, 29, 60, 180, 94, 30, 186, 0}; |
| 39 | + |
| 40 | + |
| 41 | + |
| 42 | +//class SimpeRecursionNode; |
| 43 | +//class TestRNode1; |
| 44 | +//class TestRNode2; |
| 45 | +//class TestRNode3; |
| 46 | + |
| 47 | +size_t |
| 48 | +Proportion(ORACLE_TYPE oracle,size_t min,size_t max) |
| 49 | +{ |
| 50 | +/* Sorry explanation is in Russian. PR translation if you can*/ |
| 51 | +/* Считаем пропорацию, с округлением вниз. |
| 52 | + * Диапазон увиличиваем на единицу, чтобы хвост диапазона пресказания при |
| 53 | + * округлении вниз как раз попадал в последний элемент целевого диапозона. |
| 54 | + * Разброс предсказания увеличиваем на единицу, так чтобы ровно на конец |
| 55 | + * хвоста диапазона предсказания не попасть никогда и тогда он не округлиться |
| 56 | + * в max + 1*/ |
| 57 | +size_t delta = max - min +1; |
| 58 | +size_t res =floor(((float) oracle) / ((float) ORACLE_MAX +1) * delta ); |
| 59 | +return min + res; |
| 60 | +} |
| 61 | + |
| 62 | +classPoolPickerStamp :publicvirtual StampBaseStr |
| 63 | +{ |
| 64 | +protected: |
| 65 | + std::vector<std::shared_ptr<StampBaseStr>> pool; |
| 66 | + std::vector<std::weak_ptr<StampBaseStr>> weak_pool; |
| 67 | + |
| 68 | +public: |
| 69 | +PoolPickerStamp(std::vector<std::shared_ptr<StampBaseStr>> new_pool); |
| 70 | +~PoolPickerStamp() {fprintf(stderr,"DESTROY!\n");}; |
| 71 | + |
| 72 | + std::stringExtractStr(std::shared_ptr<Blob> blob)override; |
| 73 | +virtualvoidadd_weak(std::shared_ptr<StampBaseStr> stamp); |
| 74 | +virtualboolisRecursive(); |
| 75 | +virtualintminSize()override; |
| 76 | +virtualintmaxSize()override; |
| 77 | +}; |
| 78 | + |
| 79 | + |
| 80 | +PoolPickerStamp::PoolPickerStamp(std::vector<std::shared_ptr<StampBaseStr>> new_pool) |
| 81 | + : pool{new_pool} |
| 82 | +{ |
| 83 | +for(auto stamp : pool) |
| 84 | + { |
| 85 | + std::weak_ptr<StampBaseStr> wp = stamp; |
| 86 | + weak_pool.push_back(wp); |
| 87 | + } |
| 88 | +} |
| 89 | + |
| 90 | +bool |
| 91 | +PoolPickerStamp::isRecursive() |
| 92 | +{ |
| 93 | +if(is_recursive || is_in_recursion) |
| 94 | +returntrue; |
| 95 | + is_in_recursion =true; |
| 96 | +for(auto stamp : pool) |
| 97 | + { |
| 98 | +if (stamp->isRecursive()) |
| 99 | + { |
| 100 | + is_recursive =true;// Once recursive -- recursive forever. |
| 101 | + is_in_recursion =false; |
| 102 | +returntrue; |
| 103 | + } |
| 104 | + } |
| 105 | + is_in_recursion =false; |
| 106 | +returnfalse; |
| 107 | +} |
| 108 | + |
| 109 | +std::string |
| 110 | +PoolPickerStamp::ExtractStr(std::shared_ptr<Blob> blob) |
| 111 | +{ |
| 112 | +fprintf(stderr,"*"); |
| 113 | +static ORACLE_STAMP stamp_oracle; |
| 114 | + ORACLE_TYPE oracle = stamp_oracle.ExtractValue(blob); |
| 115 | + |
| 116 | + std::vector<std::weak_ptr<StampBaseStr>> target_pool; |
| 117 | +for(auto stamp : weak_pool) |
| 118 | + { |
| 119 | +if (stamp.lock()->minSize() <= blob->Size()) |
| 120 | + { |
| 121 | + target_pool.push_back(stamp); |
| 122 | + } |
| 123 | + } |
| 124 | + |
| 125 | +size_tindex =Proportion(oracle,0, target_pool.size() -1); |
| 126 | +return target_pool[index].lock()->ExtractStr(blob); |
| 127 | +} |
| 128 | + |
| 129 | +int |
| 130 | +PoolPickerStamp::minSize() |
| 131 | +{ |
| 132 | +int res = INT_MAX; |
| 133 | +/* Do not check is_recursive here: even if stamp is known to be recursive we |
| 134 | + * still should iterate all his non-recursive children to find real minimal |
| 135 | + * size*/ |
| 136 | +if (is_in_recursion) |
| 137 | +return res; |
| 138 | + is_in_recursion =1;/* Do not use isRecursive() inside as it uses same flag*/ |
| 139 | +for(auto stamp : pool) |
| 140 | + { |
| 141 | +int candidat = stamp->minSize(); |
| 142 | +if (res > candidat) |
| 143 | + res = candidat; |
| 144 | + } |
| 145 | + is_in_recursion =0; |
| 146 | + res += ORACLE_SIZE; |
| 147 | +return res; |
| 148 | +} |
| 149 | + |
| 150 | +int |
| 151 | +PoolPickerStamp::maxSize() |
| 152 | +{ |
| 153 | +int res =0; |
| 154 | +if (is_recursive || is_in_recursion) |
| 155 | +return -1; |
| 156 | + is_in_recursion =1;/* Do not use isRecursive() inside as it uses same flag*/ |
| 157 | +for(auto stamp : pool) |
| 158 | + { |
| 159 | +int candidat = stamp->maxSize(); |
| 160 | +if (candidat == -1) |
| 161 | +return -1; |
| 162 | +if (res < candidat) |
| 163 | + res = candidat; |
| 164 | + } |
| 165 | + is_in_recursion =0; |
| 166 | + res += ORACLE_SIZE; |
| 167 | +return res; |
| 168 | +} |
| 169 | + |
| 170 | +void |
| 171 | +PoolPickerStamp::add_weak(std::shared_ptr<StampBaseStr> stamp) |
| 172 | +{ |
| 173 | + weak_pool.push_back(stamp); |
| 174 | +} |
| 175 | + |
| 176 | +classStampJSONInt :publicvirtual StampArithm<longint> |
| 177 | +{ |
| 178 | +}; |
| 179 | + |
| 180 | +classStampJSONFloat :publicvirtual StampArithm<double> |
| 181 | +{ |
| 182 | +}; |
| 183 | + |
| 184 | +classStampJSONString :publicvirtual StampDictT<DictLCAlphaSmall> |
| 185 | +{ |
| 186 | +protected: |
| 187 | +public: |
| 188 | + std::stringExtractStr(std::shared_ptr<Blob> blob)override; |
| 189 | +}; |
| 190 | + |
| 191 | + |
| 192 | +std::string |
| 193 | +StampJSONString::ExtractStr(std::shared_ptr<Blob> blob) |
| 194 | +{ |
| 195 | + std::string res ="\"" + StampDictT<DictLCAlphaSmall>::ExtractStr(blob) +"\""; |
| 196 | +return res; |
| 197 | +} |
| 198 | + |
| 199 | + |
| 200 | +classStampJSONArray:publicStampStrEnumerator |
| 201 | +{ |
| 202 | +private: |
| 203 | +public: |
| 204 | +StampJSONArray(std::shared_ptr<PoolPickerStamp> picker) |
| 205 | + :StampStrEnumerator(picker,",","[","]") {}; |
| 206 | +}; |
| 207 | + |
| 208 | + |
| 209 | + |
| 210 | +int |
| 211 | +main() |
| 212 | +{ |
| 213 | +// auto dict =std::make_shared<DictLCAlphaSmall>(); |
| 214 | +// auto stamp_d = std::make_shared<StampDict>(dict); |
| 215 | +// auto stamp_d = std::make_shared<StampDictT<DictLCAlphaSmall>>(); |
| 216 | +// auto stamp_i = std::make_shared<StampArithm<long int>>(); |
| 217 | +// auto stamp_f = std::make_shared<StampArithm<float>>(); |
| 218 | +// |
| 219 | +auto stamp_d = std::make_shared<StampJSONString>(); |
| 220 | +auto stamp_i = std::make_shared<StampJSONInt>(); |
| 221 | +auto stamp_f = std::make_shared<StampJSONFloat>(); |
| 222 | + |
| 223 | + |
| 224 | +// PoolPickerStamp stamp({stamp_i, stamp_f, stamp_d}); |
| 225 | + std::shared_ptr<PoolPickerStamp>picker(newPoolPickerStamp({stamp_i, stamp_f, stamp_d})); |
| 226 | +// picker->add_weak(picker); |
| 227 | +auto stamp_a = std::make_shared<StampJSONArray>(picker); |
| 228 | + picker->add_weak(stamp_a); |
| 229 | + |
| 230 | + |
| 231 | + std::shared_ptr<Blob> blob = std::make_shared<Blob>((char *)bin_sample,strlen((char *)bin_sample)); |
| 232 | + |
| 233 | + |
| 234 | +fprintf(stderr,"%i %i\n",stamp_a->minSize(), stamp_a->maxSize()); |
| 235 | +// for(int i =0; i<25; i++) |
| 236 | + { |
| 237 | + std::string s = stamp_a->ExtractStr(blob); |
| 238 | + |
| 239 | +fprintf(stderr,"%i %s\n",picker->isRecursive(), s.c_str()); |
| 240 | + } |
| 241 | + |
| 242 | + |
| 243 | + |
| 244 | +TEST_START(6); |
| 245 | + { |
| 246 | +is(Proportion(0,0,255),0); |
| 247 | +is(Proportion(255,0,255),0); |
| 248 | +is(Proportion(256,0,255),1); |
| 249 | +is(Proportion(65535,0,255),255); |
| 250 | +is(Proportion(65535-255,0,255),255); |
| 251 | +is(Proportion(65535-256,0,255),254); |
| 252 | + |
| 253 | + } |
| 254 | + TEST_END; |
| 255 | +} |