00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "config.h"
00038
00039 #include "Array.h"
00040 #include "util.h"
00041 #include "debug.h"
00042 #include "InternalErr.h"
00043 #include "escaping.h"
00044
00045 #include <algorithm>
00046 #include <functional>
00047
00048 using namespace std;
00049
00050 void
00051 Array::_duplicate(const Array &a)
00052 {
00053 _shape = a._shape;
00054 }
00055
00056
00057
00058
00059
00060
00061
00069 void
00070 Array::update_length(int)
00071 {
00072 int length = 1;
00073 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00074 length *= (*i).c_size > 0 ? (*i).c_size : 1;
00075 }
00076
00077 set_length(length);
00078 }
00079
00080
00081
00082
00098 Array::Array(const string &n, BaseType *v) : Vector(n, 0, dods_array_c)
00099 {
00100 add_var(v);
00101 }
00102
00104 Array::Array(const Array &rhs) : Vector(rhs)
00105 {
00106 _duplicate(rhs);
00107 }
00108
00110 Array::~Array()
00111 {
00112 DBG(cerr << "Entering ~Array (" << this << ")" << endl);
00113 DBG(cerr << "Exiting ~Array" << endl);
00114 }
00115
00116 BaseType *
00117 Array::ptr_duplicate()
00118 {
00119 return new Array(*this);
00120 }
00121
00122 Array &
00123 Array::operator=(const Array &rhs)
00124 {
00125 if (this == &rhs)
00126 return *this;
00127
00128 dynamic_cast<Vector &>(*this) = rhs;
00129
00130 _duplicate(rhs);
00131
00132 return *this;
00133 }
00134
00154 void
00155 Array::add_var(BaseType *v, Part)
00156 {
00157 if (v && v->type() == dods_array_c) {
00158 Array &a = dynamic_cast<Array&>(*v);
00159 Vector::add_var(a.var());
00160 Dim_iter i = a.dim_begin();
00161 Dim_iter i_end = a.dim_end();
00162 while (i != i_end) {
00163 append_dim(a.dimension_size(i), a.dimension_name(i));
00164 ++i;
00165 }
00166 }
00167 else {
00168 Vector::add_var(v);
00169 }
00170 }
00171
00183 void
00184 Array::append_dim(int size, string name)
00185 {
00186 dimension d;
00187
00188
00189 d.size = size;
00190 d.name = www2id(name);
00191
00192
00193 d.start = 0;
00194 d.stop = size - 1;
00195 d.stride = 1;
00196 d.c_size = size;
00197 #if 0
00198 d.selected = true;
00199 #endif
00200 _shape.push_back(d);
00201
00202 update_length(size);
00203 }
00204
00211 void
00212 Array::reset_constraint()
00213 {
00214 set_length(-1);
00215
00216 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
00217 (*i).start = 0;
00218 (*i).stop = (*i).size - 1;
00219 (*i).stride = 1;
00220 (*i).c_size = (*i).size;
00221 #if 0
00222 (*i).selected = true;
00223 #endif
00224 update_length((*i).size);
00225 }
00226 }
00227
00228
00238 void
00239 Array::clear_constraint()
00240 {
00241 reset_constraint();
00242 #if 0
00243 for (Dim_iter i = _shape.begin(); i != _shape.end(); i++) {
00244 (*i).start = 0;
00245 (*i).stop = 0;
00246 (*i).stride = 0;
00247 (*i).c_size = 0;
00248 (*i).selected = false;
00249 }
00250
00251 set_length(-1);
00252 #endif
00253 }
00254
00255
00256
00257 static const char *array_sss = \
00258 "Invalid constraint parameters: At least one of the start, stride or stop \n\
00259 specified do not match the array variable.";
00260
00280 void
00281 Array::add_constraint(Dim_iter i, int start, int stride, int stop)
00282 {
00283 dimension &d = *i ;
00284
00285
00286
00287
00288
00289 if (start >= d.size || stop >= d.size || stride > d.size || stride <= 0)
00290 throw Error(malformed_expr, array_sss);
00291
00292 if (((stop - start) / stride + 1) > d.size)
00293 throw Error(malformed_expr, array_sss);
00294
00295 d.start = start;
00296 d.stop = stop;
00297 d.stride = stride;
00298
00299 d.c_size = (stop - start) / stride + 1;
00300
00301 DBG(cerr << "add_constraint: c_size = " << d.c_size << endl);
00302 #if 0
00303 d.selected = true;
00304 #endif
00305 update_length(d.c_size);
00306 }
00307
00309 Array::Dim_iter
00310 Array::dim_begin()
00311 {
00312 return _shape.begin() ;
00313 }
00314
00316 Array::Dim_iter
00317 Array::dim_end()
00318 {
00319 return _shape.end() ;
00320 }
00321
00331 unsigned int
00332 Array::dimensions(bool )
00333 {
00334 unsigned int dim = 0;
00335 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00336 dim++;
00337 #if 0
00338 if (constrained) {
00339 if ((*i).selected)
00340 dim++;
00341 }
00342 else {
00343 dim++;
00344 }
00345 #endif
00346 }
00347
00348 return dim;
00349 }
00350
00368 int
00369 Array::dimension_size(Dim_iter i, bool constrained)
00370 {
00371 int size = 0;
00372
00373 if (!_shape.empty()) {
00374 if (constrained)
00375 size = (*i).c_size;
00376 else
00377 size = (*i).size;
00378 }
00379
00380 #if 0
00381 if (constrained) {
00382 if ((*i).selected)
00383 size = (*i).c_size;
00384 else
00385 size = 0;
00386 }
00387 else
00388 size = (*i).size;
00389 #endif
00390
00391 return size;
00392 }
00393
00412 int
00413 Array::dimension_start(Dim_iter i, bool )
00414 {
00415 return (!_shape.empty()) ? (*i).start : 0;
00416
00417 #if 0
00418 int start = 0;
00419
00420 if (!_shape.empty())
00421 start = (*i).start;
00422
00423 #if array_selected
00424 if (constrained) {
00425 if ((*i).selected)
00426 start = (*i).start;
00427 else
00428 start = 0;
00429 }
00430 else
00431 start = (*i).start;
00432 #endif
00433
00434 return start;
00435 #endif
00436 }
00437
00456 int
00457 Array::dimension_stop(Dim_iter i, bool )
00458 {
00459 return (!_shape.empty()) ? (*i).stop : 0;
00460
00461 #if 0
00462 int stop = 0;
00463
00464 if (!_shape.empty())
00465 stop = (*i).stop;
00466
00467 #if array_selected
00468 if (constrained) {
00469 if ((*i).selected)
00470 stop = (*i).stop;
00471 else
00472 stop = 0;
00473 }
00474 else
00475 stop = (*i).stop;
00476 #endif
00477
00478 return stop;
00479 #endif
00480 }
00481
00501 int
00502 Array::dimension_stride(Dim_iter i, bool )
00503 {
00504 return (!_shape.empty()) ? (*i).stride : 0;
00505
00506 #if 0
00507 int stride = 0;
00508
00509 if (!_shape.empty())
00510 stride = (*i).stride;
00511
00512 #if array_selected
00513 if (constrained) {
00514 if ((*i).selected)
00515 stride = (*i).stride;
00516 else
00517 stride = 0;
00518 }
00519 else
00520 stride = (*i).stride;
00521 #endif
00522
00523 return stride;
00524 #endif
00525 }
00526
00537 string
00538 Array::dimension_name(Dim_iter i)
00539 {
00540
00541
00542
00543
00544
00545 if (_shape.empty())
00546 throw InternalErr(__FILE__, __LINE__,
00547 "*This* array has no dimensions.");
00548 return (*i).name;
00549 }
00550
00568 void
00569 Array::print_decl(FILE *out, string space, bool print_semi,
00570 bool constraint_info, bool constrained)
00571 {
00572 if (constrained && !send_p())
00573 return;
00574
00575
00576 var()->print_decl(out, space, false, constraint_info, constrained);
00577
00578 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00579 #if 0
00580 if (constrained && !((*i).selected))
00581 continue;
00582 #endif
00583 fprintf(out, "[") ;
00584 if ((*i).name != "") {
00585 fprintf(out, "%s = ", id2www((*i).name).c_str()) ;
00586 }
00587 if (constrained) {
00588 fprintf(out, "%d]", (*i).c_size) ;
00589 }
00590 else {
00591 fprintf(out, "%d]", (*i).size) ;
00592 }
00593 }
00594
00595 if (print_semi) {
00596 fprintf(out, ";\n") ;
00597 }
00598 }
00599
00617 void
00618 Array::print_decl(ostream &out, string space, bool print_semi,
00619 bool constraint_info, bool constrained)
00620 {
00621 if (constrained && !send_p())
00622 return;
00623
00624
00625 var()->print_decl(out, space, false, constraint_info, constrained);
00626
00627 for (Dim_citer i = _shape.begin(); i != _shape.end(); i++) {
00628 #if 0
00629 if (constrained && !((*i).selected))
00630 continue;
00631 #endif
00632 out << "[" ;
00633 if ((*i).name != "") {
00634 out << id2www((*i).name) << " = " ;
00635 }
00636 if (constrained) {
00637 out << (*i).c_size << "]" ;
00638 }
00639 else {
00640 out << (*i).size << "]" ;
00641 }
00642 }
00643
00644 if (print_semi) {
00645 out << ";\n" ;
00646 }
00647 }
00648
00649 void
00650 Array::print_xml(FILE *out, string space, bool constrained)
00651 {
00652 print_xml_core(out, space, constrained, "Array");
00653 }
00654
00655 void
00656 Array::print_xml(ostream &out, string space, bool constrained)
00657 {
00658 print_xml_core(out, space, constrained, "Array");
00659 }
00660
00661 void
00662 Array::print_as_map_xml(FILE *out, string space, bool constrained)
00663 {
00664 print_xml_core(out, space, constrained, "Map");
00665 }
00666
00667 void
00668 Array::print_as_map_xml(ostream &out, string space, bool constrained)
00669 {
00670 print_xml_core(out, space, constrained, "Map");
00671 }
00672
00673 class PrintArrayDim : public unary_function<Array::dimension&, void>
00674 {
00675 FILE *d_out;
00676 string d_space;
00677 bool d_constrained;
00678 public:
00679 PrintArrayDim(FILE *o, string s, bool c)
00680 : d_out(o), d_space(s), d_constrained(c)
00681 {}
00682
00683 void operator()(Array::dimension &d)
00684 {
00685 int size = d_constrained ? d.c_size : d.size;
00686 if (d.name.empty())
00687 fprintf(d_out, "%s<dimension size=\"%d\"/>\n", d_space.c_str(),
00688 size);
00689 else
00690 fprintf(d_out, "%s<dimension name=\"%s\" size=\"%d\"/>\n",
00691 d_space.c_str(), id2xml(d.name).c_str(), size);
00692 }
00693 };
00694
00695 void
00696 Array::print_xml_core(FILE *out, string space, bool constrained, string tag)
00697 {
00698 if (constrained && !send_p())
00699 return;
00700
00701 fprintf(out, "%s<%s", space.c_str(), tag.c_str());
00702 if (!name().empty())
00703 fprintf(out, " name=\"%s\"", id2xml(name()).c_str());
00704 fprintf(out , ">\n");
00705
00706 get_attr_table().print_xml(out, space + " ", constrained);
00707
00708 BaseType *btp = var();
00709 string tmp_name = btp->name();
00710 btp->set_name("");
00711 btp->print_xml(out, space + " ", constrained);
00712 btp->set_name(tmp_name);
00713
00714 for_each(dim_begin(), dim_end(),
00715 PrintArrayDim(out, space + " ", constrained));
00716
00717 fprintf(out, "%s</%s>\n", space.c_str(), tag.c_str());
00718 }
00719
00720 class PrintArrayDimStrm : public unary_function<Array::dimension&, void>
00721 {
00722 ostream &d_out;
00723 string d_space;
00724 bool d_constrained;
00725 public:
00726 PrintArrayDimStrm(ostream &o, string s, bool c)
00727 : d_out(o), d_space(s), d_constrained(c)
00728 {}
00729
00730 void operator()(Array::dimension &d)
00731 {
00732 int size = d_constrained ? d.c_size : d.size;
00733 if (d.name.empty())
00734 d_out << d_space << "<dimension size=\"" << size << "\"/>\n" ;
00735 else
00736 d_out << d_space << "<dimension name=\"" << id2xml(d.name)
00737 << "\" size=\"" << size << "\"/>\n" ;
00738 }
00739 };
00740
00741 void
00742 Array::print_xml_core(ostream &out, string space, bool constrained, string tag)
00743 {
00744 if (constrained && !send_p())
00745 return;
00746
00747 out << space << "<" << tag ;
00748 if (!name().empty())
00749 out << " name=\"" << id2xml(name()) << "\"" ;
00750 out << ">\n" ;
00751
00752 get_attr_table().print_xml(out, space + " ", constrained);
00753
00754 BaseType *btp = var();
00755 string tmp_name = btp->name();
00756 btp->set_name("");
00757 btp->print_xml(out, space + " ", constrained);
00758 btp->set_name(tmp_name);
00759
00760 for_each(dim_begin(), dim_end(),
00761 PrintArrayDimStrm(out, space + " ", constrained));
00762
00763 out << space << "</" << tag << ">\n" ;
00764 }
00765
00776 unsigned int
00777 Array::print_array(FILE *out, unsigned int index, unsigned int dims,
00778 unsigned int shape[])
00779 {
00780 if (dims == 1) {
00781 fprintf(out, "{") ;
00782 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00783 var(index++)->print_val(out, "", false);
00784 fprintf(out, ", ") ;
00785 }
00786 var(index++)->print_val(out, "", false);
00787 fprintf(out, "}") ;
00788
00789 return index;
00790 }
00791 else {
00792 fprintf(out, "{") ;
00793
00794
00795
00796
00797
00798
00799 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00800 index = print_array(out, index, dims - 1, shape + 1);
00801 fprintf(out, ",") ;
00802 }
00803 index = print_array(out, index, dims - 1, shape + 1);
00804 fprintf(out, "}") ;
00805
00806 return index;
00807 }
00808 }
00809
00820 unsigned int
00821 Array::print_array(ostream &out, unsigned int index, unsigned int dims,
00822 unsigned int shape[])
00823 {
00824 if (dims == 1) {
00825 out << "{" ;
00826 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00827 var(index++)->print_val(out, "", false);
00828 out << ", " ;
00829 }
00830 var(index++)->print_val(out, "", false);
00831 out << "}" ;
00832
00833 return index;
00834 }
00835 else {
00836 out << "{" ;
00837
00838
00839
00840
00841
00842
00843 for (unsigned i = 0; i < shape[0] - 1; ++i) {
00844 index = print_array(out, index, dims - 1, shape + 1);
00845 out << "," ;
00846 }
00847 index = print_array(out, index, dims - 1, shape + 1);
00848 out << "}" ;
00849
00850 return index;
00851 }
00852 }
00853
00854 void
00855 Array::print_val(FILE *out, string space, bool print_decl_p)
00856 {
00857
00858
00859
00860
00861
00862
00863 if (print_decl_p) {
00864 print_decl(out, space, false, false, false);
00865 fprintf(out, " = ") ;
00866 }
00867
00868 unsigned int *shape = new unsigned int[_shape.size()];
00869 unsigned int index = 0;
00870 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < _shape.size(); i++)
00871 shape[index++] = dimension_size(i, true);
00872
00873 print_array(out, 0, _shape.size(), shape);
00874
00875 delete [] shape; shape = 0;
00876
00877 if (print_decl_p) {
00878 fprintf(out, ";\n") ;
00879 }
00880 }
00881
00882 void
00883 Array::print_val(ostream &out, string space, bool print_decl_p)
00884 {
00885
00886
00887
00888
00889
00890
00891 if (print_decl_p) {
00892 print_decl(out, space, false, false, false);
00893 out << " = " ;
00894 }
00895
00896 unsigned int *shape = new unsigned int[dimensions(true)];
00897 unsigned int index = 0;
00898 for (Dim_iter i = _shape.begin(); i != _shape.end() && index < dimensions(true); ++i)
00899 shape[index++] = dimension_size(i, true);
00900
00901 print_array(out, 0, dimensions(true), shape);
00902
00903 delete [] shape; shape = 0;
00904
00905 if (print_decl_p) {
00906 out << ";\n" ;
00907 }
00908 }
00909
00919 bool
00920 Array::check_semantics(string &msg, bool)
00921 {
00922 bool sem = BaseType::check_semantics(msg) && !_shape.empty();
00923
00924 if (!sem)
00925 msg = "An array variable must have dimensions";
00926
00927 return sem;
00928 }
00929
00938 void
00939 Array::dump(ostream &strm) const
00940 {
00941 strm << DapIndent::LMarg << "Array::dump - ("
00942 << (void *)this << ")" << endl ;
00943 DapIndent::Indent() ;
00944 Vector::dump(strm) ;
00945 strm << DapIndent::LMarg << "shape:" << endl ;
00946 DapIndent::Indent() ;
00947 Dim_citer i = _shape.begin() ;
00948 Dim_citer ie = _shape.end() ;
00949 unsigned int dim_num = 0 ;
00950 for (; i != ie; i++) {
00951 strm << DapIndent::LMarg << "dimension " << dim_num++ << ":"
00952 << endl ;
00953 DapIndent::Indent() ;
00954 strm << DapIndent::LMarg << "name: " << (*i).name << endl ;
00955 strm << DapIndent::LMarg << "size: " << (*i).size << endl ;
00956 strm << DapIndent::LMarg << "start: " << (*i).start << endl ;
00957 strm << DapIndent::LMarg << "stop: " << (*i).stop << endl ;
00958 strm << DapIndent::LMarg << "stride: " << (*i).stride << endl ;
00959 strm << DapIndent::LMarg << "constrained size: " << (*i).c_size
00960 << endl ;
00961 #if 0
00962 strm << DapIndent::LMarg << "selected: " << (*i).selected << endl ;
00963 #endif
00964 DapIndent::UnIndent() ;
00965 }
00966 DapIndent::UnIndent() ;
00967 DapIndent::UnIndent() ;
00968 }
00969